casl library
Isomorphic authorisation for Dart.
Define what a user may do as a list of rules, then ask one question everywhere:
final ability = (AbilityBuilder()
..can('read', 'Article')
..can('update', 'Article', {'authorId': currentUserId}))
.build();
ability.can('update', article);
The rule format is CASL.js's, so a server running @casl/ability can send
its rules straight to a Dart client and both will agree about what they
mean. That agreement is the point: authorisation duplicated in two languages
drifts, and the drift is invisible until somebody sees a button they should
not have.
It is checked rather than asserted. Ninety cases are run through the real
@casl/ability and replayed here, so a divergence fails a build instead of
reaching a user. The handful of places the two deliberately differ are
listed in the README, and each one is pinned by a fixture that records the
reason.
Two things worth knowing before you start
The last matching rule wins. Not "cannot beats can" — writing cannot
and then can permits. This is what lets rule sets be layered.
Declare your subject types. runtimeType is unreliable in obfuscated
release builds, so use the CaslSubject mixin or the subject() helper
rather than letting the library guess. See CaslSubject.
Classes
-
Ability<
A extends String, S extends String> - What a user may do, and the only thing the rest of an app needs to ask.
-
AbilityBuilder<
A extends String, S extends String> - Collects rules in the order they are written, then builds an ability.
-
AbilityUpdate<
A extends String, S extends String> - A rule change, as reported to an Ability.on listener.
-
AccessibleFields<
A extends String, S extends String> - Which fields of a subject may be touched, asked over and over.
- CaslFields
- Reading values out of a subject, the way conditions need them read.
- CompoundCondition
-
Several conditions combined —
and,or,nor,not. - Condition
- A parsed condition, ready to be evaluated.
- ConditionInterpreter
- Evaluates a parsed Condition against a subject.
- ConditionsMatch
- The result of compiling one rule's conditions.
- FieldCondition
- A test applied to one field of the subject.
-
ForbiddenErrorCheck<
A extends String, S extends String> - A permission check that can be given a message before it runs.
- ForcedSubject
- An object paired with the subject type it should be checked as.
- MongoConditionsMatch
- A rule's conditions, parsed once and ready to be asked.
- MongoQueryParser
- Turns a MongoDB-shaped query into a Condition tree.
- OperatorCall
- Everything an operator needs in order to parse itself.
- ParsedConditions
- A ConditionsMatch that can hand back the tree it parsed.
-
QueryLanguage<
R> - How that language combines things.
- RawRule
- One rule, exactly as it travels over the wire.
- Rule
- A RawRule compiled for asking questions of.
-
RuleAdder<
A extends String, S extends String> - Writes one rule. AbilityBuilder.can and AbilityBuilder.cannot are these.
-
RuleIndex<
A extends String, S extends String> - Rules, indexed by subject type and action so a check does not scan them all.
- RuleRef
- A handle on the rule just written, so a reason can be attached to it.
Enums
- UnparsableCondition
- What to do with a condition the parser cannot make sense of.
Mixins
- CaslRecord
- A type whose fields conditions can be matched against.
- CaslSubject
- A type that knows which subject type rules are written about it.
Extensions
-
AbilityGuard
on Ability<
A, S> - Turns a permission check into a guard that throws.
Constants
- anyAction → const String
- The action that stands for every action.
- anySubjectType → const String
- The subject type that stands for every subject type.
-
defaultCompoundInterpreters
→ const Map<
String, CompoundInterpreter> - The compound operators.
-
defaultFieldInterpreters
→ const Map<
String, FieldInterpreter> - The field operators the built-in parser can produce.
- defaultFieldsMatcher → const FieldsMatcher
- The default FieldsMatcher — fieldPatternMatcher.
-
defaultOperators
→ const Map<
String, OperatorParser> - The field operators CASL.js ships with, and only those.
-
logicalOperators
→ const Map<
String, OperatorParser> - The logical operators CASL leaves out, ready to be switched on.
Functions
-
caslCompare(
Object? a, Object? b) → int - Orders two values the way the condition operators need them ordered.
-
caslStrictJsEquality(
Object? a, Object? b) → bool -
Equality as JavaScript's
===decides it, for bug-compatibility with@casl/ability. -
createAliasResolver(
Map< String, Object> aliases, {String anyActionName = anyAction, bool validate = true}) → ResolveActions - Builds a resolver from a map of alias to what it means.
-
createMongoAbility<
A extends String, S extends String> (List< RawRule> rules, {MongoQueryParser? parser, FieldReader read = CaslFields.read, PartialDetectSubjectType? detectSubjectType, String anyActionName = anyAction, String anySubjectTypeName = anySubjectType, ResolveActions? resolveActions, bool strictJsEquality = false, UnparsableCondition onUnparsableCondition = UnparsableCondition.fail, ConditionInterpreter? interpreter}) → Ability<A, S> - An ability that understands MongoDB-style conditions. The usual entry point.
-
defineAbility<
A extends String, S extends String> (void define(RuleAdder< A, S> can, RuleAdder<A, S> cannot), {AbilityFactory<A, S> ? create}) → Ability<A, S> - An ability in one expression, which is how CASL's own documentation writes nearly every example.
-
defineAbilityAsync<
A extends String, S extends String> (Future< void> define(RuleAdder<A, S> can, RuleAdder<A, S> cannot), {AbilityFactory<A, S> ? create}) → Future<Ability< A, S> > - defineAbility for rules that need something awaited on the way.
-
detectSubjectTypeByRuntimeType(
Object value) → String - The default, in order of how much it can be trusted.
-
fieldPatternMatcher(
List< String> fields) → bool Function(String field) -
Matches a field name against patterns, with
*and**. -
mongoConditionsMatcher(
{MongoQueryParser parser = const MongoQueryParser(), FieldReader read = CaslFields.read, ValueEquality equals = deepEquals, ConditionInterpreter? interpreter}) → ConditionsMatcher - Builds the conditions matcher, optionally over a custom parser or reader.
-
packRules(
List< RawRule> rules, {String packSubject(String subjectType)?}) → List<PackedRule> -
Squeezes rules into the array form CASL.js's
packRulesproduces. -
permittedFieldsOf<
A extends String, S extends String> (Ability< A, S> ability, A action, Object? subject, {required List<String> allFields}) → List<String> -
Which fields of
subjectmay be touched byaction. -
rulesToAst<
A extends String, S extends String> (Ability< A, S> ability, A action, S subjectType) → Condition? - The Condition form of rulesToCondition — the one most callers want.
-
rulesToCondition<
R> (List< Rule> rules, RuleConverter<R> convert, QueryLanguage<R> language) → R? - Turns a grant into a filter: "which records may this user act on".
-
rulesToFields<
A extends String, S extends String> (Ability< A, S> ability, A action, S subjectType) → Map<String, Object?> -
The values a new subject must have for
actionto be permitted on it. -
subject(
String type, Object? value) → ForcedSubject -
Pairs
valuewith the subjecttypeit should be checked as. -
unpackRules(
List< Object?> packed, {String unpackSubject(String subjectType)?}) → List<RawRule> -
Reads what packRules wrote, or what CASL.js's
packRuleswrote.
Typedefs
-
AbilityFactory<
A extends String, S extends String> = Ability< A, S> Function(List<RawRule> rules) - Builds the ability an AbilityBuilder has collected rules for.
-
AbilityUpdateListener<
A extends String, S extends String> = void Function(AbilityUpdate< A, S> event) - Called when an ability's rules change. See Ability.on.
- CompoundInterpreter = bool Function(CompoundCondition node, Object? subject, ConditionInterpreter interpreter)
- How one parsed compound operator combines its parts.
-
ConditionsMatcher
= ConditionsMatch Function(Map<
String, Object?> conditions) -
Compiles a rule's
conditionsinto something that can be asked. - DetectSubjectType = String Function(Object value)
- Works out which subject type an arbitrary object should be checked as.
- FieldInterpreter = bool Function(FieldCondition node, Object? subject, ConditionInterpreter interpreter)
- How one parsed field operator decides whether a subject satisfies it.
- FieldReader = Object? Function(Object target, String field)
- Reads one field from one object.
-
FieldsMatcher
= bool Function(String field) Function(List<
String> fields) -
Compiles a rule's
fieldsinto a predicate over one field name. - ForbiddenMessageBuilder = String Function(ForbiddenError error)
- Builds the message shown when something is refused.
- OperatorParser = Condition Function(OperatorCall call)
-
How one
$operatorbecomes a Condition. -
PackedRule
= List<
Object?> - One rule in its compact wire form: a JSON array, not an object.
- PartialDetectSubjectType = String? Function(Object value)
- Works out the subject type for the objects it recognises, and defers on the rest by returning null.
-
ResolveActions
= List<
String> Function(List<String> actions) - Expands an action into itself plus everything it stands for.
-
RuleConverter<
R> = R Function(Rule rule) - How the conditions of one rule become whatever a query builder speaks.
- Unsubscribe = void Function()
- Stops an Ability.on listener listening.
- ValueEquality = bool Function(Object? a, Object? b)
- Decides whether two condition values count as equal.
Exceptions / Errors
- ConditionFormatException
- Thrown when a rule's conditions cannot be parsed.
- ForbiddenError
- Thrown when an action is not permitted.