Skip to content

Latest commit

 

History

History
1585 lines (944 loc) · 62 KB

CHANGELOG.md

File metadata and controls

1585 lines (944 loc) · 62 KB

Change Log

All notable changes to this project will be documented in this file.

5.4.3 (2021-08-17)

Bug Fixes

  • release: force release because of disable pre/post hook execution of pnpm (39c20f6)

5.4.2 (2021-08-17)

Bug Fixes

  • ability: makes sure that other event handlers are not lost when last handler is unregistered (ff3e75f)

5.4.1 (2021-08-16)

Bug Fixes

  • ability: ensure ability call all event handlers during emit (fdf2095)

5.4.0 (2021-08-11)

Features

  • ability: adds posibility to define custom any action and any subject type instead of using manage and all (#533) (9226583), closes #527

5.3.1 (2021-05-12)

Bug Fixes

  • adjusts package tags to improve discoverability (73e88b0)

5.3.0 (2021-05-10)

Features

  • types: exposes HKT types in CASL (related to #505) (9f91ac4))

5.2.2 (2021-01-27)

Bug Fixes

  • types: relaxes types for resolveAction AbilityOptions property (2af2927)

5.2.1 (2021-01-23)

Bug Fixes

  • ability: removes generic parameters from AnyAbility type (5566ac8)

5.2.0 (2021-01-22)

Bug Fixes

  • ability: hides Public private type under interface (2524431), closes #446

Features

5.1.2 (2021-01-03)

Bug Fixes

  • types: change type of detectSubjectType return value to be of SubjectType (d76b18b), closes #430

5.1.1 (2020-12-29)

Bug Fixes

  • types: adds return type annotation to detectSubjectType method (b514146)
  • types: reverts ForcedSubject<T> to be an interface (f48b0a0)

5.1.0 (2020-12-26)

Bug Fixes

  • 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)

Code Refactoring

  • extra: makes fieldsFrom option to be mandatory for permittedFieldsOf (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 and possibleRulesFor (b8c324d)
  • types: restricts which utility types are exported by library (e98618f)

Features

  • builder: improves typings for AbilityBuilder [skip release] (ebd4d17), closes #379
  • builder: improves typings of AbilityBuilder['can'] and AbilityBuilder['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

Performance Improvements

  • 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 in permittedFieldsOf (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)

BREAKING CHANGES

  • types: types AliasesMap, TaggedInterface, AbilityTupleType, ToAbilityTypes, AnyObject are no longer exported by the library

  • extra: makes fieldsFrom option to be mandatory for permittedFieldsOf. This reduces confusion around why permittedFieldsOf returns empty array when user can manage entity fields. So, now this logic is just explicit and clear

    Before

    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 object

    Before

    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 and cannot methods of AbilityBuilder now restricts what fields and operators can be used inside conditions (i.e., MongoQuery). Also these methods now suggests object fields based on passed instance

    Before

    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)

Bug Fixes

  • 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)

Bug Fixes

  • build: ensure dist is updated before (0a879f7)

5.1.0-next.13 (2020-12-19)

Bug Fixes

  • types: ensure ForceSubject generic parameter is preserved in resulting d.ts files (e97e5fe)

Reverts

  • extra: makes rulesToQuery return an object with Object prototype (dcb7254)

5.1.0-next.12 (2020-11-18)

Bug Fixes

  • ability: replaces getters with functions to ensure terser properly minifies them (386ecb6)
  • extra: makes permittedFieldsOf to iterate from the end of array (81e6409)

Code Refactoring

  • extra: makes fieldsFrom option to be mandatory for permittedFieldsOf [skip release] (df29b0d)
  • types: restricts which utility types are exported by library (e98618f)

Reverts

  • builder: reverts back AbilityBuilder generic parameter (aa7b45f)

BREAKING CHANGES

  • types: types AliasesMap, TaggedInterface, AbilityTupleType, ToAbilityTypes, AnyObject are no longer exported by the library

  • extra: makes fieldsFrom option to be mandatory for permittedFieldsO f. This reduces confusion around why permittedFieldsOf returns empty array when user can manage entity fields. So, now this logic is just explicit and clear

    Before

    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)

Bug Fixes

  • README: removes explanation duplicated from intro guide (6315aa7)

Code Refactoring

  • ruleIndex: detectSubjectType option is now responsible only for detecting subject type from objects [skip release] (ebeaadc)

BREAKING CHANGES

  • 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 object

    Before

    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)

Code Refactoring

  • ruleIndex: removes possibility to pass subject to rulesFor and possibleRulesFor [skip release] (b8c324d)

Performance Improvements

  • ruleIndex: removes subject type detection from _buildIndexFor (13fe934)

BREAKING CHANGES

  • 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)

Performance Improvements

  • events: converts LinkedItem into POJO and regular functions (6f2de73)
  • extra: replaces object with Set in permittedFieldsOf (a9260d1)

5.1.0-next.8 (2020-09-26)

Performance Improvements

  • rule: ensures conditions/field matcher created only when we have object/field to check (110a69d)

5.1.0-next.7 (2020-09-25)

Performance Improvements

  • events: moves out side-effect from LinkedItem constructor (3657c7f)

5.1.0-next.6 (2020-09-25)

Performance Improvements

  • events: handles event removal in space efficient way (71246e2)

5.1.0-next.5 (2020-09-23)

Bug Fixes

  • 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)

Performance Improvements

  • ability: replaces object for storing index with ES6 Map (d1fa117)

5.1.0-next.3 (2020-08-28)

Performance Improvements

  • ability: creates conditions and field matcher lazily (4ae7799)

5.1.0-next.2 (2020-08-27)

Features

  • builder: improves typings for AbilityBuilder [skip release] (ebd4d17), closes #379
  • builder: improves typings of AbilityBuilder['can'] and AbilityBuilder['cannot'] methods [skip release] (98ffbfc), closes #333

Performance Improvements

  • events: utilizes LinkedList for storing event handlers (e2fd265)
  • rules: improves merging logic of rules of subject and manage all (6f8a13a)

BREAKING CHANGES

  • 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 and cannot methods of AbilityBuilder now restricts what fields and operators can be used inside conditions (i.e., MongoQuery). Also these methods now suggests object fields based on passed instance

    Before

    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)

Features

  • 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)

Bug Fixes

  • 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!

Bug Fixes

  • ability: removes sift specific types from casl (9f18b31)

Code Refactoring

  • ability: removes deprecated types and fields (bf5ef73), closes #355
  • package: replaces siftjs with @ucast/mongo2js (41e53aa), closes #350

Features

  • ability: stores ast property in Rule if conditionsMatcher has ast (53e5e28), closes #350

BREAKING CHANGES

  • package: replaces siftjs with @ucast/mongo2js. This changed MongoQuery type and buildMongoQueryMatcher function parameters. Influences users who implemented custom sift operators:

    • MongoQuery accepted a generic type of AdditionalOperators, now it accepts an object interface and custom operators
    • MongoQueryOperators is renamed to MongoQueryFieldOperators and now accepts Value generic parameter
    • buildMongoQuery now accepts 3 optional parameters: custom parsing instruction, custom operator interpreters and options for JavaScript interpreters
    • Ability 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 custom equal 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, use detectSubjectType instead

  • LegacyClaimRawRule and LegacySubjectRawRule are both removed, so you are no longer allowed to use actions in rule definition, use action property instead

  • Ability throws an error if you specify a rule with property field 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)

Bug Fixes

  • 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)

Bug Fixes

  • package: makes sure the latest casl works with Angular 8.x (91ee505), closes #337

4.1.4 (2020-06-02)

Bug Fixes

  • ability: makes sure error for wrong Ability usage is thrown (db62daf), closes #334

4.1.3 (2020-05-27)

Bug Fixes

  • 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)

Bug Fixes

  • ability: throws error when trying to check permissions on field with unconfigured fieldMatcher option (e5f2add), closes #330

4.1.1 (2020-05-25)

Bug Fixes

  • README: adds a note about js examples and link to TypeScript support (bd9dc59), closes #305

4.1.0 (2020-05-19)

Bug Fixes

  • deps: update dependency sift to v13 (fa3eecc)

Features

  • error: makes ForbiddenError.ability to be a readonly public prop (3a0342d), closes #264

4.0.8 (2020-04-29)

Bug Fixes

  • dist: ensure object spread operator is converted to Object.assign in ES6 build (fefc955)

4.0.7 (2020-04-22)

Bug Fixes

  • alias: simplifies types for expandActions (395dde7)

4.0.6 (2020-04-20)

Bug Fixes

  • can: changes link in exception to new documentation (c133d4e)

4.0.5 (2020-04-17)

Bug Fixes

  • ability: relax types for MongoQueryOperators (2960064)

4.0.4 (2020-04-11)

Bug Fixes

  • README: updates README to the latest version. makes sure all links are working (839441c)

4.0.3 (2020-04-10)

Bug Fixes

  • ability: reverts back ability.rules types to RawRule (6d6b85f)

4.0.2 (2020-04-10)

Bug Fixes

  • 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)

Bug Fixes

  • ability: makes sure extra submodule is published (096e4f7), closes #284

4.0.0 (2020-04-09)

Bug Fixes

  • ability: ensures that ForbiddenError correctly inherits Error 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

Features

  • 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 and conditionsMatcher (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 into PureAbility (base class) and Ability (preconfigured PureAbility) (9536205), closes #249

BREAKING CHANGES

  • subjectName: subject name now returns all for subjects which type cannot be determined

  • api: removes deprecated methods:

    • ability.throwUnlessCan in favor of ForbiddenError.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 used crud, 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 use conditionsMatcher and fieldMatcher 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) or buildMongoQueryMatcher 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 of defineAbility and AbilityBuilder.extract in favor of new 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 accepts Ability 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 form action, 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 to detectSubjectType, 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.

Features

  • ability: adds possibility to specify custom error messages (#245) (4b48562), closes #241

Bug Fixes

  • deps: update dependency sift to v9 (cf3aa9a)

Features

  • ability: uses CSP build of sift.js (f238813), closes #234

Features

  • ability: adds support for field patterns in rules (#213) (55ad2db), closes #194

Features

  • ability: adds support for field patterns in rules (#213) (55ad2db), closes #194

Performance Improvements

  • ability: checks for fields only if fields were specified in rules (da013d4)

Bug Fixes

  • extra: fixes edge cases when building query to database (#206) (437d4e7)

Bug Fixes

  • extra: add rulesToFields TS definition (#205) (b772ad6)

Features

  • ability: adds validation of 3rd parameter to Ability.can (9df032c), closes #192

Bug Fixes

  • ability: returns null from rulesToQuery if ability has only inverted rules (744061c), closes #170

Bug Fixes

  • ability: copies event listeners before calling them (3148da1), closes #159

Bug Fixes

  • ability: prevent creation of manage alias (4ca1268), closes #119
  • ability: updates ts definitions for Ability (2c989b2), closes #119

Features

  • ability: adds support for manage action (d9ab56c), closes #119

BREAKING CHANGES

  • 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

Bug Fixes

  • ability: adds on method into typescript defs (86e35cc)

Bug Fixes

  • 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

Bug Fixes

  • ability: adds additional check to rulesToFields (a6f4875)

Bug Fixes

  • package: changes location of ES5M modules (2b1ad4e), closes #89

Bug Fixes

  • deps: update dependency sift to v6 (791f78c)

Features

  • ability: adds rulesToFields method (4bf9ddc), closes #86

2.3.0 (2018-05-09)

Features

  • ability: allows AbilityBuilder to accept the subject's Type (#61) (0de1bf0), closes #58

2.2.0 (2018-05-04)

Features

  • ability: adds forbidden reasons (1c01c42), closes #45

2.1.0 (2018-04-26)

Features

  • ability: adds alias action to actions Rule field (88d82a8)
  • ability: adds pack/unpack rules methods (c60ab5d), closes #44

2.0.3 (2018-04-16)

Bug Fixes

  • ability: ignores inverted rule with conditions when checking subject type (36916dc), closes #53

2.0.2 (2018-04-03)

Features

  • ability: allows to pass subjects as comma separated items (7612425)
  • builder: allows to pass async function in AbilityBuilder.define (def07c7)

Performance

  • ability: improves performance of permittedFieldsOf helper function (7612425)

Bug Fixes

  • builder: returns RuleBuilder from AbilityBuilder#cannot (def07c7)

2.0.0 (2018-03-23)

Features

  • ability: implement per field rules support (471358f), closes #18
  • extra: adds permittedAttributesOf (3474fcc), closes #18

Breaking Changes

  • 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

Migration Guide

  1. 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'
  1. 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
  1. 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)

  1. 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)

Bug Fixes

  • ability: adds check when action is aliased to itself (facbe10)

Features

  • ability: adds on method and trigger update event in update method (a3af0ed)

1.0.6 (2017-12-19)

Bug Fixes

  • ts: fixes return type of mongo related functions (67e02bc)

1.0.5 (2017-12-19)

Bug Fixes

  • ts: adds conditions to typescript definitions (a345da7)

1.0.4 (2017-12-18)

Bug Fixes

  • 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)

Bug Fixes

  • ability: passes original subject into rulesFor instead of parsed one (0496053)

Features

  • typescript: adds d.ts file (9e73719), closes #7

1.0.0 (2017-07-28)

Documentation

  • adds all required documentation and examples of integration for v1

0.3.4 (2017-07-24)

Bug Fixes

  • 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)

Features

  • ability: adds support for $regex condition (fc438a1)

0.2.4 (2017-07-24)

Bug Fixes

  • error: fixes ForbiddenError instanceof checks in umd build (e0a910c)

0.2.1 (2017-07-20)

0.2.0 (2017-07-18)

Features