All notable changes to this project will be documented in this file.
5.4.3 (2021-08-17)
- release: force release because of disable pre/post hook execution of pnpm (39c20f6)
5.4.2 (2021-08-17)
- ability: makes sure that other event handlers are not lost when last handler is unregistered (ff3e75f)
5.4.1 (2021-08-16)
- ability: ensure ability call all event handlers during emit (fdf2095)
5.4.0 (2021-08-11)
- ability: adds posibility to define custom any action and any subject type instead of using
manage
andall
(#533) (9226583), closes #527
5.3.1 (2021-05-12)
- adjusts package tags to improve discoverability (73e88b0)
5.3.0 (2021-05-10)
5.2.2 (2021-01-27)
- types: relaxes types for
resolveAction
AbilityOptions
property (2af2927)
5.2.1 (2021-01-23)
- ability: removes generic parameters from
AnyAbility
type (5566ac8)
5.2.0 (2021-01-22)
5.1.2 (2021-01-03)
5.1.1 (2020-12-29)
- types: adds return type annotation to
detectSubjectType
method (b514146) - types: reverts
ForcedSubject<T>
to be an interface (f48b0a0)
5.1.0 (2020-12-26)
- ability: ensure default field matcher can match fields with partial patterns inside (362f49f), closes #388
- ability: replaces getters with functions to ensure terser properly minifies them (386ecb6)
- angular: fixes sourcemap generation for the code built by ngc (7715263), closes #387 #382
- build: ensure dist is updated before (0a879f7)
- conditions: moves logic related to compare complex types to @ucast/mongo2js (9bd6a1b)
- condtions: adds interpreter for
$and
parsing instruction (3166a32) - extra: makes
permittedFieldsOf
to iterate from the end of array (81e6409) - package: removes
engine
section that points to npm@6 (eecd12a), closes #417 - README: removes explanation duplicated from intro guide (6315aa7)
- types: ensure
ForceSubject
generic parameter is preserved in resulting d.ts files (e97e5fe) - types: makes parameters of
AbilityClass
optional (e7d0815)
- extra: makes
fieldsFrom
option to be mandatory forpermittedFieldsOf
(df29b0d) - ruleIndex:
detectSubjectType
option is now responsible only for detecting subject type from objects [skip release] (ebeaadc) - ruleIndex: removes possibility to pass subject to
rulesFor
andpossibleRulesFor
(b8c324d) - types: restricts which utility types are exported by library (e98618f)
- builder: improves typings for AbilityBuilder [skip release] (ebd4d17), closes #379
- builder: improves typings of
AbilityBuilder['can']
andAbilityBuilder['cannot']
methods (98ffbfc), closes #333 - esm: adds ESM support for latest Node.js through
exports
prop in package.json (cac2506), closes #331 - extra: adds
rulesToAST
that converts rules into @ucast AST (55fd6ee), closes #350
- ability: creates conditions and field matcher lazily (4ae7799)
- ability: replaces object for storing index with ES6 Map (d1fa117)
- events: converts LinkedItem into POJO and regular functions (6f2de73)
- events: handles event removal in space efficient way (71246e2)
- events: moves out side-effect from
LinkedItem
constructor (3657c7f) - events: utilizes LinkedList for storing event handlers (e2fd265)
- extra: replaces object with
Set
inpermittedFieldsOf
(a9260d1) - rule: ensures conditions/field matcher created only when we have object/field to check (110a69d)
- ruleIndex: removes subject type detection from
_buildIndexFor
(13fe934) - rules: improves merging logic of rules of subject and
manage all
(6f8a13a)
-
types: types
AliasesMap
,TaggedInterface
,AbilityTupleType
,ToAbilityTypes
,AnyObject
are no longer exported by the library -
extra: makes
fieldsFrom
option to be mandatory forpermittedFieldsOf
. This reduces confusion around whypermittedFieldsOf
returns empty array when user can manage entity fields. So, now this logic is just explicit and clearBefore
import { defineAbility } from '@casl/ability'; import { permittedFieldsOf } from '@casl/ability/extra'; const ability = defineAbility((can) => { can('read', 'Article'); }); const fields = permittedFieldsOf(ability, 'read', 'Article'); // []
After
import { defineAbility } from '@casl/ability'; import { permittedFieldsOf } from '@casl/ability/extra'; const ability = defineAbility((can) => { can('read', 'Article'); }); const ARTICLE_FIELDS = ['id', 'title', 'description']; const fields = permittedFieldsOf(ability, 'read', 'Article', { fieldsFrom: rule => rule.fields || ARTICLE_FIELDS }); // ['id', 'title', 'description']
-
ruleIndex: string and class (or function constructor) are the only possible subject types for now.
detectSubjectType
is now responsible only for detecting subject type from objectBefore
When providing subject type it was important to handle cases when passed in argument is a string or function. As an alternative it was possible to call built-in
detectSubjectType
which could catch this cases:import { Ability } from '@casl/ability'; const ability = new Ability([], { detectSubjectType(object) { if (object && typeof object === 'object') { return object.__typename; } return detectSubjectType(object); });
After
There is no need to handle subject type values in
detectSubjectType
function anymore. It's now handled internally:import { Ability } from '@casl/ability'; const ability = new Ability([], { detectSubjectType: object => object.__typename });
Also it's important to note that it's no longer possible to use classes and strings as subject types interchangeably as it was before. Now, if you want to use classes, you should use them everywhere and define custom
detectSubjecType
:Before
import { defineAbility } from '@casl/ability'; class Post {} const ability = defineAbility((can) => { can('read', Post); can('update', 'Post'); }); ability.can('read', 'Post') // true ability.can('read', Post) // true ability.can('update', Post) // true
After
import { defineAbility } from '@casl/ability'; class Post {} const ability = defineAbility((can) => { can('read', Post); can('update', 'Post'); }, { detectSubjectType: object => object.constructor }); ability.can('read', 'Post') // false, 'Post' and Post are considered different now ability.can('read', Post) // true ability.can('update', Post) // false, because `update` is configured for 'Post' string ability.can('read', new Post()) // true ability.can('update', new Post()) // false, because `update` is configured for 'Post' string and subject type of this object is `Post` class
-
ruleIndex:
rulesFor
,possibleRulesFor
,rulesToQuery
,ruleToAST
,rulesToFields
accepts only subject type now!Before
import { Ability } from '@casl/ability'; const ability = new Ability([ { action: 'read', subject: 'Post' } ]); class Post {} console.log(ability.rulesFor('read', new Post())); // [Rule] console.log(ability.rulesFor('read', 'Post')); // [Rule]
After
import { Ability } from '@casl/ability'; const ability = new Ability([ { action: 'read', subject: 'Post' } ]); class Post {} console.log(ability.rulesFor('read', new Post())); // throws exception console.log(ability.rulesFor('read', 'Post')); // [Rule]
Other functions and methods have the same behavior
-
builder: changes main generic parameter to be a class instead of instance and makes
defineAbility
to accept options as the 2nd argument.Before
import { AbilityBuilder, defineAbility, Ability } from '@casl/ability'; const resolveAction = (action: string) => {/* custom implementation */ }; const ability = defineAbility({ resolveAction }, (can) => can('read', 'Item')); const builder = new AbilityBuilder<Ability>(Ability);
After
import { AbilityBuilder, defineAbility, Ability } from '@casl/ability'; const resolveAction = (action: string) => {/* custom implementation */ }; const ability = defineAbility((can) => can('read', 'Item'), { resolveAction }); const builder = new AbilityBuilder(Ability); // first argument is now mandatory!
The 1st parameter to
AbilityBuilder
is now madatory. This allows to infer generic parameters from it and makes AbilityType that is built to be explicit. -
builder:
can
andcannot
methods ofAbilityBuilder
now restricts what fields and operators can be used inside conditions (i.e.,MongoQuery
). Also these methods now suggests object fields based on passed instanceBefore
import { AbilityBuilder, Ability, AbilityClass } from '@casl/ability'; interface Person { kind: 'Person' firstName: string lastName: string age: number address: { street: string city: string } } type AppAbility = Ability<['read', Person | Person['kind']]>; cons AppAbility = Ability as AbilityClass<AppAbility>; cons { can } = new AbilityBuilder(AppAbility); can('read', 'Person', { 'address.street': 'Somewhere in the world', fistName: 'John' // unintentional typo }); can('read', 'Person', ['fistName', 'lastName'], { // no intellisense for fields age: { $gt: 18 } })
After
Because provided keys in the example above doesn't exist on
Person
interface, TypeScript throws an error. So, we are safe from typos! But what about dot notation? It's also supported but in more typesafe way:import { AbilityBuilder, Ability, AbilityClass } from '@casl/ability'; interface Person { kind: 'Person' firstName: string lastName: string age: number address: { street: string city: string } } type AppAbility = Ability<['read', Person | Person['kind']]>; cons AppAbility = Ability as AbilityClass<AppAbility>; cons { can } = new AbilityBuilder(AppAbility); interface PersonQuery extends Person { 'address.street': Person['address']['street'] 'address.city': Person['address']['city'] } can<PersonQuery>('read', 'Person', { 'address.street': 'Somewhere in the world', fistName: 'John' // unintentional typo }); can<PersonQuery>('read', 'Person', ['firstName', 'lastName'], { age: { $gt: 18 } })
Intellisense and type checking for fields is also implemented! To be able to use wildcards in fields just add additional generic parameter:
can<PersonQuery, 'address.*'>('read', 'Person', ['firstName', 'address.*'], { age: { $gt: 18 } })
5.1.0-next.15 (2020-12-20)
- package: removes
engine
section that points to npm@6 (eecd12a), closes #417 - types: makes parameters of
AbilityClass
optional (e7d0815)
5.1.0-next.14 (2020-12-19)
- build: ensure dist is updated before (0a879f7)
5.1.0-next.13 (2020-12-19)
- types: ensure
ForceSubject
generic parameter is preserved in resulting d.ts files (e97e5fe)
- extra: makes
rulesToQuery
return an object withObject
prototype (dcb7254)
5.1.0-next.12 (2020-11-18)
- ability: replaces getters with functions to ensure terser properly minifies them (386ecb6)
- extra: makes
permittedFieldsOf
to iterate from the end of array (81e6409)
- extra: makes
fieldsFrom
option to be mandatory forpermittedFieldsOf
[skip release] (df29b0d) - types: restricts which utility types are exported by library (e98618f)
- builder: reverts back
AbilityBuilder
generic parameter (aa7b45f)
-
types: types
AliasesMap
,TaggedInterface
,AbilityTupleType
,ToAbilityTypes
,AnyObject
are no longer exported by the library -
extra: makes
fieldsFrom
option to be mandatory forpermittedFieldsO f
. This reduces confusion around whypermittedFieldsOf
returns empty array when user can manage entity fields. So, now this logic is just explicit and clearBefore
import { defineAbility } from '@casl/ability'; import { permittedFieldsOf } from '@casl/ability/extra'; const ability = defineAbility((can) => { can('read', 'Article'); }); const fields = permittedFieldsOf(ability, 'read', 'Article'); // []
After
import { defineAbility } from '@casl/ability'; import { permittedFieldsOf } from '@casl/ability/extra'; const ability = defineAbility((can) => { can('read', 'Article'); }); const ARTICLE_FIELDS = ['id', 'title', 'description']; const fields = permittedFieldsOf(ability, 'read', 'Article', { fieldsFrom: rule => rule.fields || ARTICLE_FIELDS }); // ['id', 'title', 'description']
5.1.0-next.11 (2020-10-17)
- README: removes explanation duplicated from intro guide (6315aa7)
- ruleIndex:
detectSubjectType
option is now responsible only for detecting subject type from objects [skip release] (ebeaadc)
-
ruleIndex: string and class (or function constructor) are the only possible subject types for now.
detectSubjectType
is now responsible only for detecting subject type from objectBefore
When providing subject type it was important to handle cases when passed in argument is a string or function. As an alternative it was possible to call built-in
detectSubjectType
which could catch this cases:import { Ability } from '@casl/ability'; const ability = new Ability([], { detectSubjectType(object) { if (object && typeof object === 'object') { return object.__typename; } return detectSubjectType(object); });
After
There is no need to handle subject type values in
detectSubjectType
function anymore. It's now handled internally:import { Ability } from '@casl/ability'; const ability = new Ability([], { detectSubjectType: object => object.__typename });
Also it's important to note that it's no longer possible to use classes and strings as subject types interchangeably together as it was before. Now, if you want to use classes, you should use them everywhere:
Before
import { defineAbility } from '@casl/ability'; class Post {} const ability = defineAbility((can) => { can('read', Post); can('update', 'Post'); }); ability.can('read', 'Post') // true ability.can('read', Post) // true ability.can('update', Post) // true
After
import { defineAbility } from '@casl/ability'; class Post {} const ability = defineAbility((can) => { can('read', Post); can('update', 'Post'); }); ability.can('read', 'Post') // false, 'Post' and Post are considered different now ability.can('read', Post) // true ability.can('update', Post) // false
5.1.0-next.10 (2020-10-17)
- ruleIndex: removes possibility to pass subject to
rulesFor
andpossibleRulesFor
[skip release] (b8c324d)
- ruleIndex: removes subject type detection from
_buildIndexFor
(13fe934)
-
ruleIndex:
rulesFor
,possibleRulesFor
,rulesToQuery
,ruleToAST
,rulesToFields
accepts only subject type now!Before
import { Ability } from '@casl/ability'; const ability = new Ability([ { action: 'read', subject: 'Post' } ]); class Post {} console.log(ability.rulesFor('read', new Post())); // [Rule] console.log(ability.rulesFor('read', 'Post')); // [Rule]
After
import { Ability } from '@casl/ability'; const ability = new Ability([ { action: 'read', subject: 'Post' } ]); class Post {} console.log(ability.rulesFor('read', new Post())); // throws exception console.log(ability.rulesFor('read', 'Post')); // [Rule]
Other functions and methods have the same behavior
5.1.0-next.9 (2020-09-28)
- events: converts LinkedItem into POJO and regular functions (6f2de73)
- extra: replaces object with
Set
inpermittedFieldsOf
(a9260d1)
5.1.0-next.8 (2020-09-26)
- rule: ensures conditions/field matcher created only when we have object/field to check (110a69d)
5.1.0-next.7 (2020-09-25)
- events: moves out side-effect from
LinkedItem
constructor (3657c7f)
5.1.0-next.6 (2020-09-25)
- events: handles event removal in space efficient way (71246e2)
5.1.0-next.5 (2020-09-23)
- ability: ensure default field matcher can match fields with partial patterns inside (362f49f), closes #388
- angular: fixes sourcemap generation for the code built by ngc (7715263), closes #387 #382
- condtions: adds interpreter for
$and
parsing instruction (3166a32)
5.1.0-next.4 (2020-08-28)
- ability: replaces object for storing index with ES6 Map (d1fa117)
5.1.0-next.3 (2020-08-28)
- ability: creates conditions and field matcher lazily (4ae7799)
5.1.0-next.2 (2020-08-27)
- builder: improves typings for AbilityBuilder [skip release] (ebd4d17), closes #379
- builder: improves typings of
AbilityBuilder['can']
andAbilityBuilder['cannot']
methods [skip release] (98ffbfc), closes #333
- events: utilizes LinkedList for storing event handlers (e2fd265)
- rules: improves merging logic of rules of subject and
manage all
(6f8a13a)
-
builder: changes main generic parameter restriction to accept any class and makes
defineAbility
to accept options as the 2nd argument.Before
import { AbilityBuilder, defineAbility, Ability } from '@casl/ability'; const resolveAction = (action: string) => {/* custom implementation */ }; const ability = defineAbility({ resolveAction }, (can) => can('read', 'Item')); const builder = new AbilityBuilder<Ability>(Ability);
After
import { AbilityBuilder, defineAbility, Ability } from '@casl/ability'; const resolveAction = (action: string) => {/* custom implementation */ }; const ability = defineAbility((can) => can('read', 'Item'), { resolveAction }); const builder = new AbilityBuilder(Ability); // first argument is now mandatory!
The 1st parameter to
AbilityBuilder
is now madatory. This allows to infer generic parameters from it and makes AbilityType that is built to be explicit. -
builder:
can
andcannot
methods ofAbilityBuilder
now restricts what fields and operators can be used inside conditions (i.e.,MongoQuery
). Also these methods now suggests object fields based on passed instanceBefore
import { AbilityBuilder, Ability, AbilityClass } from '@casl/ability'; interface Person { kind: 'Person' firstName: string lastName: string age: number address: { street: string city: string } } type AppAbility = Ability<['read', Person | Person['kind']]>; cons AppAbility = Ability as AbilityClass<AppAbility>; cons { can } = new AbilityBuilder(AppAbility); can('read', 'Person', { 'address.street': 'Somewhere in the world', fistName: 'John' // unintentional typo }); can('read', 'Person', ['fistName', 'lastName'], { // no intellisense for fields age: { $gt: 18 } })
After
Because provided keys in the example above doesn't exist on
Person
interface, TypeScript throws an error. So, we are safe from typos! But what about dot notation? It's also supported but in more typesafe way:import { AbilityBuilder, Ability, AbilityClass } from '@casl/ability'; interface Person { kind: 'Person' firstName: string lastName: string age: number address: { street: string city: string } } type AppAbility = Ability<['read', Person | Person['kind']]>; cons AppAbility = Ability as AbilityClass<AppAbility>; cons { can } = new AbilityBuilder(AppAbility); interface PersonQuery extends Person { 'address.street': Person['address']['street'] 'address.city': Person['address']['city'] } can<PersonQuery>('read', 'Person', { 'address.street': 'Somewhere in the world', fistName: 'John' // unintentional typo }); can<PersonQuery>('read', 'Person', ['firstName', 'lastName'], { age: { $gt: 18 } })
Intellisense and type checking for fields is also implemented! To be able to use wildcards in fields just add additional generic parameter:
can<PersonQuery, 'address.*'>('read', 'Person', ['firstName', 'address.*'], { age: { $gt: 18 } })
5.1.0-next.1 (2020-08-20)
- esm: adds ESM support for latest Node.js through
exports
prop in package.json (cac2506), closes #331 - extra: adds
rulesToAST
that converts rules into @ucast AST (55fd6ee), closes #350
5.0.1-next.1 (2020-08-11)
- conditions: moves logic related to compare complex types to @ucast/mongo2js (9bd6a1b)
Deprecated 5.0.0 (2020-08-10)
This version was released accidentally, PLEASE DO NOT USE IT!
- ability: removes sift specific types from casl (9f18b31)
- ability: removes deprecated types and fields (bf5ef73), closes #355
- package: replaces siftjs with @ucast/mongo2js (41e53aa), closes #350
-
package: replaces siftjs with @ucast/mongo2js. This changed
MongoQuery
type andbuildMongoQueryMatcher
function parameters. Influences users who implemented custom sift operators:MongoQuery
accepted a generic type of AdditionalOperators, now it accepts an object interface and custom operatorsMongoQueryOperators
is renamed toMongoQueryFieldOperators
and now acceptsValue
generic parameterbuildMongoQuery
now accepts 3 optional parameters: custom parsing instruction, custom operator interpreters and options for JavaScript interpretersAbility
does not compare objects anymore, so if you rely on value to equal specific object, then you need to either change your conditions or implement customequal
function
Before
import { MongoQuery, MongoQueryOperators, buildMongoQueryMatcher } from '@casl/ability'; import { $nor } from 'sift'; type CustomMongoQuery = MongoQuery<{ $customOperator: Function }>; type $eq = MongoQueryOperators['$eq']; const matcher = buildMongoQueryMatcher({ $nor })
After
import { MongoQuery, MongoQueryFieldOperators, buildMongoQueryMatcher } from '@casl/ability'; import { $nor, nor } from '@ucast/mongo2js' type CustomMongoQuery<T> = MongoQuery<T, { toplevel: { // can be used only on document level $customOperator: Function }, field: { // can be used only on field level $my: boolean } }> type $eq = MongoQueryFieldOperators['$eq']; // accepts optional `Value` generic parameter const matcher = buildMongoQueryMatcher({ $nor }, { nor }); ```
-
ability: removes deprecated options and types:
-
AbilityOptions['subjectName']
has been removed, usedetectSubjectType
instead -
LegacyClaimRawRule
andLegacySubjectRawRule
are both removed, so you are no longer allowed to useactions
in rule definition, useaction
property instead -
Ability
throws an error if you specify a rule with propertyfield
to be an empty array -
Ability
no longer warns about using only inverted rules. This may be done by intention, so now it's left up to developer to decide whether it's fine or not
4.1.6 (2020-09-06)
- ability: ensure default field matcher can match fields with partial patterns inside (362f49f), closes #388
- ability: removes sift specific types from casl (9f18b31)
- angular: fixes sourcemap generation for the code built by ngc (7715263), closes #387 #382
4.1.5 (2020-06-08)
4.1.4 (2020-06-02)
4.1.3 (2020-05-27)
- ability: makes sure Ability notifies about edge cases: empty fields array and field level checks without fieldMatcher (48a49ed), closes #329 #330 #328
4.1.2 (2020-05-27)
- ability: throws error when trying to check permissions on field with unconfigured fieldMatcher option (e5f2add), closes #330
4.1.1 (2020-05-25)
4.1.0 (2020-05-19)
- deps: update dependency sift to v13 (fa3eecc)
4.0.8 (2020-04-29)
- dist: ensure object spread operator is converted to
Object.assign
in ES6 build (fefc955)
4.0.7 (2020-04-22)
- alias: simplifies types for expandActions (395dde7)
4.0.6 (2020-04-20)
- can: changes link in exception to new documentation (c133d4e)
4.0.5 (2020-04-17)
- ability: relax types for MongoQueryOperators (2960064)
4.0.4 (2020-04-11)
- README: updates README to the latest version. makes sure all links are working (839441c)
4.0.3 (2020-04-10)
- ability: reverts back
ability.rules
types to RawRule (6d6b85f)
4.0.2 (2020-04-10)
- ability: improves inference of
abilities
by using virtual ts properties (c134642) - packages: makes eventual lib size to be smaller (93a3bec), closes #287
4.0.1 (2020-04-09)
4.0.0 (2020-04-09)
- ability: ensures that
ForbiddenError
correctly inheritsError
in ES5 (12a74f2), closes #248 - ability: extracts types to a separate file (df1fec1), closes #248
- ability: improves PackedRule type (a781921), closes #248
- ability: makes sure
AbilityBuilder
correctly detects conditions (1c35393), closes #248 - deps: update dependency sift to v12 (71593ca)
- mongoose: ensures mongoose works with MongoQuery conditions (f92b7df), closes #249
- ability: adds
subject
helper which allows to define subject type for DTO (834c24f) - ability: adds generic types to Ability and related types [skip ci] (4e56fda), closes #256
- ability: adds typescript support for checks only by action (b652df1), closes #107
- ability: allows to do fine grained config (2b97c57), closes #248
- ability: allows to pass
fieldMatcher
andconditionsMatcher
(d23af56), closes #258 - ability: allows to specify class as subject type (9c6041a), closes #187
- ability: improves typing for
GetSubjectName
and adds default values for generics (c089293), closes #256 - ability: makes aliasing to be tree-shakable and per
Ability
instance (fc22d49), closes #248 - ability: removes deprecated methods (7d26f56), closes #257
- ability: returns
all
for empty subjects (f5d41e0), closes #107 #256 - ability: split
Ability
intoPureAbility
(base class) andAbility
(preconfigured PureAbility) (9536205), closes #249
-
subjectName: subject name now returns
all
for subjects which type cannot be determined -
api: removes deprecated methods:
ability.throwUnlessCan
in favor ofForbiddenError.from(ability).throwUnlessCan
-
alias: aliasing functionality was refactored to support tree-shaking and have per instance:
Before:
import { Ability } from '@casl/ability'; Ability.addAlias('modify', ['create', 'update']); const ability = new Ability([]); ability.can('modify', 'Post');
After:
import { Ability, createAliasResolver } from '@casl/ability'; const resolveAction = createAliasResolver({ modify: ['create', 'update'] }); const ability = new Ability([], { resolveAction }); ability.can('modify', 'Post');
-
alias: no more default aliases are shipped with
@casl/ability
. So, if you usedcrud
, you need to add it yourself.Before:
import { AbilityBuilder } from '@casl/ability'; const ability = AbilityBuilder.define((can) => { can("crud", "Post"); }); ability.can("crud", "Post"); // true
After:
import { defineAbility, createAliasResolver } from '@casl/ability'; const resolveAction = createAliasResolver({ crud: ['create', 'read', 'update', 'delete'] }); const ability = defineAbility({ resolveAction }, (can) => { can("crud", "Post"); }); ability.can("crud", "Post"); // true
-
options: no more possibility to pass custom
Rule
class (this was undocumented feature). Now you should useconditionsMatcher
andfieldMatcher
instead.Before:
import { Ability, Rule } from '@casl/ability'; import sift from 'sift'; class MyCustomRule extends Rule { constructor(...args) { super(...args); this._matches = sift(/* custom sift options */) } } const ability = new Ability([], { RuleType: MySiftRule })
After:
Depending on the usecase you should use either
mongoConditionsMatcher
(to restrict rules) orbuildMongoQueryMatcher
to extend them. See docs for details:import { Ability, AbilityBuilder, buildMongoQueryMatcher, } from '@casl/ability'; import { $nor } from 'sift'; const conditionsMatcher = buildMongoQueryMatcher({ $nor }); export default function defineAbilityFor(user) { const { can, build } = new AbilityBuilder(Ability); can('read', 'Article', { $nor: [{ private: true }, { authorId: user.id }] }); return build({ conditionsMatcher }); }
-
builder: removes
AbilityBuilder.define
in favor ofdefineAbility
andAbilityBuilder.extract
in favor ofnew AbilityBuilder()
Before:
import { AbilityBuilder, Ability } from '@casl/ability'; const ability = AbilityBuilder.define((can, cannot) => { can('read', 'Post'); cannot('delete', 'Post', { private: true }); }); // or const { can, cannot, rules } = AbilityBuilder.extract(); can('read', 'Post'); cannot('delete', 'Post', { private: true }); const ability = new Ability(rules);
After:
import { defineAbility, AbilityBuilder, Ability } from '@casl/ability'; const ability = defineAbility((can, cannot) => { can('read', 'Post'); cannot('delete', 'Post', { private: true }); }); // or const { can, cannot, rules } = new AbilityBuilder(Ability); can('read', 'Post'); cannot('delete', 'Post', { private: true }); const ability = new Ability(rules);
-
error:
ForbiddenError
constructor now acceptsAbility
instance as a parameter. See API docs for details -
Ability:
emit
,buildIndexFor
,mergeRulesFor
are now private methods -
rule: deprecated use of
actions
in rules in favor of singular formaction
, however the 1st is still supported:Before:
const rules = [ { actions: 'read', subject: 'Post' } ];
After:
const rules = [ { action: 'read', subject: 'Post' } ]
-
options:
subjectName
option is renamed todetectSubjectType
, however the 1st name is still supported for backward compatibility. -
typescript: weak hand written declaration files are removed as
@casl/ability
has been completely rewritten to TypeScript.
@casl/ability-v3.4.0 (2019-12-22)
@casl/ability-v3.3.0 (2019-12-09)
- deps: update dependency sift to v9 (cf3aa9a)
@casl/ability-v3.2.0 (2019-07-28)
@casl/ability-v3.2.0 (2019-07-28)
@casl/ability-v3.1.2 (2019-07-08)
- ability: checks for fields only if fields were specified in rules (da013d4)
@casl/ability-v3.1.1 (2019-07-04)
@casl/ability-v3.1.0 (2019-07-01)
@casl/ability-v3.0.2 (2019-03-25)
@casl/ability-v3.0.1 (2019-02-16)
@casl/ability-v3.0.0 (2019-02-04)
- ability: prevent creation of
manage
alias (4ca1268), closes #119 - ability: updates ts definitions for
Ability
(2c989b2), closes #119
- ability:
manage
is not anymore an alias for CRUD but represents any action.
Let's consider the next example:
const ability = AbilityBuilder.define((can) => {
can('manage', 'Post')
can('read', 'User')
})
In @casl/[email protected] the definition above produces the next results:
ability.can('read', 'Post') // true
ability.can('publish', 'Post') // false, because `manage` is an alias for CRUD
In @casl/[email protected] the results:
ability.can('read', 'Post') // true
ability.can('publish', 'Post') // true, because `manage` represents any action
To migrate the code, just replace manage
with crud
and everything will work as previously.
- ability: prioritise rules with
all
subject in the same way as other rules
Let's consider the next example:
const ability = AbilityBuilder.define((can) => {
can('read', 'User', { id: 1 })
cannot('read', 'all')
})
According to rule ordering read all
rule must override read User
rule but in @casl/[email protected] there was a bug and this is not true:
ability.can('read', 'User') // true
In @casl/[email protected] this works as expected
ability.can('read', 'User') // false
@casl/ability-v2.5.1 (2018-11-11)
- ability: adds
on
method into typescript defs (86e35cc)
@casl/ability-v2.5.0 (2018-10-14)
- deps: update dependency sift to v7 (0c02695)
- README: changes links to @casl/ability to point to npm package instead to git root [skip ci] (a74086b), closes #102
@casl/ability-v2.4.2 (2018-07-02)
- ability: adds additional check to
rulesToFields
(a6f4875)
@casl/ability-v2.4.1 (2018-07-02)
@casl/ability-v2.4.0 (2018-07-02)
- deps: update dependency sift to v6 (791f78c)
2.3.0 (2018-05-09)
2.2.0 (2018-05-04)
2.1.0 (2018-04-26)
- ability: adds alias
action
toactions
Rule field (88d82a8) - ability: adds pack/unpack rules methods (c60ab5d), closes #44
2.0.3 (2018-04-16)
2.0.2 (2018-04-03)
- ability: allows to pass subjects as comma separated items (7612425)
- builder: allows to pass async function in
AbilityBuilder.define
(def07c7)
- ability: improves performance of
permittedFieldsOf
helper function (7612425)
- builder: returns RuleBuilder from AbilityBuilder#cannot (def07c7)
2.0.0 (2018-03-23)
- ability: implement per field rules support (471358f), closes #18
- extra: adds
permittedAttributesOf
(3474fcc), closes #18
- package: casl was split into several packages available under
@casl
npm scope - ability: subject specific rules now takes precedence over
all
rules - rulesToQuery: moves
rulesToQuery
into submodule@casl/ability/extra
- mongoose: moves mongo related functions into separate
@casl/mongoose
package
- CASL was split into several packages which are available under
@casl
scope.
Ability
related functionality now is in @casl/ability
package. casl
package is deperecated now.
Before:
import { AbilityBuilder } from 'casl'
Now:
import { AbilityBuilder } from '@casl/ability'
- Previously it was not possible to override
all
rule with subject specific inverted one. It was a bug and it's fixed.
Before:
const ability = AbilityBuilder.define((can, cannot) => {
can('read', 'all')
cannot('read', 'Post')
})
ability.can('read', 'Post') // true
Now:
with the same setup
ability.can('read', 'Post') // false
rulesToQuery
was moved into submodule. And its signature was changed
Before:
import { rulesToQuery } from 'casl'
rulesToQuery(ability.rulesFor('read', 'Post'), rule => ...)
Now:
import { rulesToQuery } from '@casl/ability/extra'
rulesToQuery(ability, 'read', 'Post', rule => ...)
This allows to ensure that people use this function correctly (i.e, by passing only 1 pair or action-subject rules)
- MongoDB integration was moved into @casl/mongoose.
Before:
import { toMongoQuery, mongoosePlugin } from 'casl'
Now:
import { toMongoQuery, accessibleRecordsPlugin } from '@casl/mongoose'
1.1.0 (2018-02-02)
- ability: adds check when action is aliased to itself (facbe10)
- ability: adds
on
method and triggerupdate
event inupdate
method (a3af0ed)
1.0.6 (2017-12-19)
- ts: fixes return type of mongo related functions (67e02bc)
1.0.5 (2017-12-19)
- ts: adds conditions to typescript definitions (a345da7)
1.0.4 (2017-12-18)
- ability: properly checks inverted rules when subject type is passed as string (e6f69e8)
1.0.2 (2017-08-02)
1.0.1 (2017-08-02)
- ability: passes original subject into
rulesFor
instead of parsed one (0496053)
1.0.0 (2017-07-28)
- adds all required documentation and examples of integration for v1
0.3.4 (2017-07-24)
- mongoose: adds proper modelName detection for mongoose query (0508400)
- query: fixes detection of forbidden query (7712eb2)
- query: makes query to be empty if there is at least one rule without conditions (d82c3fc)
0.3.0 (2017-07-24)
- ability: adds support for $regex condition (fc438a1)
0.2.4 (2017-07-24)
- error: fixes ForbiddenError instanceof checks in umd build (e0a910c)
0.2.1 (2017-07-20)
- casl: first release (8694688)