Casl: error on new Ability(rules)

Created on 6 May 2020  路  16Comments  路  Source: stalniy/casl

Hi,
I'm using casl angular and have alredy update the version from 3.X to 4.
I have updated my code a little but doesn't work.

Current version:
"@casl/ability": "^4.0.8",
"@casl/angular": "^4.0.4",

private defineAbilityFor(user: Employee) {
    const { can, cannot, rules } = new AbilityBuilder();
    if (user.isAdmin) {
      can('manage', 'all');
    } else if (user.isUser) {
      can('read', 'all');
      for (const projectData of user.MandatoryProjectList) {
        can(['share', 'edit', 'assign'], 'Project', { idProject: projectData.idProject });
      }
      cannot(['edit', 'delete'], Company);
    }

    // return rules;
    return new Ability(rules);
  }

Returns a error on the line return new Ability(rules);

ERROR in src/app/services/auth.service.ts:86:24 - error TS2345: Argument of type '(ClaimRawRule | LegacyClaimRawRule | SubjectRawRule | LegacySubjectRawRule)[]' is not assignable to parameter of type '(SubjectRawRule | LegacySubjectRawRule)[]'.
Type 'ClaimRawRule | LegacyClaimRawRule | SubjectRawRule | LegacySubjectRawRule' is not assignable to type 'SubjectRawRule | LegacySubjectRawRule'.
Type 'ClaimRawRule' is not assignable to type 'SubjectRawRule | LegacySubjectRawRule'.
Type 'ClaimRawRule' is not assignable to type 'SubjectRawRule'.
Property 'subject' is optional in type 'ClaimRawRule' but required in type 'SubjectRawRule'.

86 return new Ability(rules);


Angular CLI: 9.1.4
Node: 10.15.3
OS: darwin x64

Angular: 9.1.4
... animations, cli, common, compiler, compiler-cli, core, forms
... language-service, platform-browser, platform-browser-dynamic
... router
Ivy Workspace: Yes

Package Version

@angular-devkit/architect 0.900.7
@angular-devkit/build-angular 0.900.7
@angular-devkit/build-optimizer 0.900.7
@angular-devkit/build-webpack 0.900.7
@angular-devkit/core 9.0.7
@angular-devkit/schematics 9.1.4
@angular/cdk 9.2.2
@angular/flex-layout 9.0.0-beta.29
@angular/material 9.2.2
@angular/material-moment-adapter 9.2.2
@ngtools/webpack 9.0.7
@schematics/angular 9.1.4
@schematics/update 0.901.4
rxjs 6.5.5
typescript 3.7.5
webpack 4.41.2

question

Most helpful comment

Starting from 4.0, AbilityBuilder accepts optional generic parameter TAbility, by default this parameter equals PureAbility. What you need to do is to change how you create AbilityBuilder:

const { can, cannot, rules } = new AbilityBuilder<Ability>();

For more details check the API docs

All 16 comments

Starting from 4.0, AbilityBuilder accepts optional generic parameter TAbility, by default this parameter equals PureAbility. What you need to do is to change how you create AbilityBuilder:

const { can, cannot, rules } = new AbilityBuilder<Ability>();

For more details check the API docs

By the way, you can simplify your rules by changing:

for (const projectData of user.MandatoryProjectList) {
        can(['share', 'edit', 'assign'], 'Project', { idProject: projectData.idProject });
      }

to

const projectIds = user.MandatoryProjectList.map(projectData => projectData.idProject)
can(['share', 'edit', 'assign'], 'Project', { idProject: { $in: projectIds } });

I tried the minumum code, but the error persist...
I tried too remove the node_modules folder and install another time, but nothing changes.

private defineAbilityFor(user: Employee) {
    const { can, cannot, rules } = new AbilityBuilder();
    can('manage', 'all');

    return new Ability(rules);
 }

Did you tried what I suggested?

I have tried what you sugget, but the problem is on the constructor from Ability, because not allow rules.

if i do that:

  private defineAbilityFor(user: Employee) {
    const { can, cannot, rules } = new AbilityBuilder();
    return new Ability(rules);
  }

the error still

Argument of type '(ClaimRawRule | LegacyClaimRawRule | SubjectRawRule | LegacySubjectRawRule)[]' is not assignable to parameter of type '(SubjectRawRule | LegacySubjectRawRule)[]'.
Type 'ClaimRawRule | LegacyClaimRawRule | SubjectRawRule | LegacySubjectRawRule' is not assignable to type 'SubjectRawRule | LegacySubjectRawRule'.
Type 'ClaimRawRule' is not assignable to type 'SubjectRawRule | LegacySubjectRawRule'.
Type 'ClaimRawRule' is not assignable to type 'SubjectRawRule'.
Property 'subject' is optional in type 'ClaimRawRule' but required in type 'SubjectRawRule'.

i'm trying that example, but it's a little complicated, and i can not apply it to my current project...

my code is:

export class AuthService {
  constructor(private http: HttpClient, private ability: Ability) { }

  private defineAbilityFor(user: Employee) {
    const { can, cannot, rules } = new AbilityBuilder(Ability);
    this.ability.update(rules);
  }
}

And the error is on line this.ability.update(rules)

Argument of type '(ClaimRawRule<string> | LegacyClaimRawRule<string> | SubjectRawRule<string, SubjectType, unknown> | LegacySubjectRawRule<string, SubjectType, unknown>)[]' is not assignable to parameter of type '(SubjectRawRule<string, SubjectType, Record<string | number | symbol, string | number | boolean | Record<string | number | symbol, any> | MongoQueryOperators>> | LegacySubjectRawRule<...>)[]'.
  Type 'ClaimRawRule<string> | LegacyClaimRawRule<string> | SubjectRawRule<string, SubjectType, unknown> | LegacySubjectRawRule<string, SubjectType, unknown>' is not assignable to type 'SubjectRawRule<string, SubjectType, Record<string | number | symbol, string | number | boolean | Record<string | number | symbol, any> | MongoQueryOperators>> | LegacySubjectRawRule<...>'.
    Type 'ClaimRawRule<string>' is not assignable to type 'SubjectRawRule<string, SubjectType, Record<string | number | symbol, string | number | boolean | Record<string | number | symbol, any> | MongoQueryOperators>> | LegacySubjectRawRule<...>'.
      Type 'ClaimRawRule<string>' is not assignable to type 'SubjectRawRule<string, SubjectType, Record<string | number | symbol, string | number | boolean | Record<string | number | symbol, any> | MongoQueryOperators>>'.
        Property 'subject' is optional in type 'ClaimRawRule<string>' but required in type 'SubjectRawRule<string, SubjectType, Record<string | number | symbol, string | number | boolean | Record<string | number | symbol, any> | MongoQueryOperators>>'.

Where come that unknown of SubjectRawRule?

The problem on the new Ability line because types of rules generated by AbilityBuilder are not compatible with the types that Ability expects. They have different defaults. That's why you need to provide Ability as a generic type to AbilityBuilder.

I have tried what you sugget, but the problem is on the constructor from Ability, because not allow rules.

if i do that:

  private defineAbilityFor(user: Employee) {
    const { can, cannot, rules } = new AbilityBuilder();
    return new Ability(rules);
  }

the error still

Argument of type '(ClaimRawRule | LegacyClaimRawRule | SubjectRawRule | LegacySubjectRawRule)[]' is not assignable to parameter of type '(SubjectRawRule | LegacySubjectRawRule)[]'.
Type 'ClaimRawRule | LegacyClaimRawRule | SubjectRawRule | LegacySubjectRawRule' is not assignable to type 'SubjectRawRule | LegacySubjectRawRule'.
Type 'ClaimRawRule' is not assignable to type 'SubjectRawRule | LegacySubjectRawRule'.
Type 'ClaimRawRule' is not assignable to type 'SubjectRawRule'.
Property 'subject' is optional in type 'ClaimRawRule' but required in type 'SubjectRawRule'.

If you think you know better, why do you ask me after all? :)

I created a simple example for you, so you can make sure this is true - https://codesandbox.io/s/typescript-examples-l0p8b?file=/src/index.ts

Close this as there is nothing to do from my side. Please check the docs and the examples

Ran into the same issue. Even the very first example code snippet from the README produces this error, so it is a bit rich to suggest checking the docs, in my opinion.
Adding the generic parameter does fix it, but is mentioned nowhere in the entire README, which is where most people trying out the package will look for (working) examples.

Glad there's an easy solution, though!

Thanks for the note. I鈥檒l fix the example in README. But I鈥檇 recommend to check docs instead - https://stalniy.github.io/casl/v4/en/guide/intro
You will find there a lot more, including a separate page for typescript support

in CASL v5, I鈥檒l remove some legacy types and errors will be easier to understand.

@stalniy is this the issue I'm seeing on the below Sandbox:

https://codesandbox.io/s/wonderful-meadow-02kls?file=/src/index.ts

I'm trying to test a basic RBAC set up and hit a similar typescript error. I thought the workaround might be to remove the Ability class on line 32:

const { can, build } = new AbilityBuilder<AppAbility>(Ability)

but that causes the results to be incorrect (all conditions turn true):

image

Any help in understanding the correct set up would be amazing. I'm trying to follow your cookbook recipe but it doesn't seem to validate so I created this slimmed-down version to try and see why :)

https://casl.js.org/v4/en/cookbook/roles-with-static-permissions

@theGC there are some typings issues in 4.x which I fixed in prerelease branch for v5. For now, you need to do this:

import { AbilityClass, Ability } from '@casl/ability'

type AppAbility = ...
const AppAbility = Ability as AbilityClass<AppAbility>;

const { can, build } = new AbilityBuilder<AppAbility>(AppAbility);

@stalniy that's got it, thank you and thanks for all your hard work on CASL. Been using it within Feathers for a few days now and it's making things much clearer in their structure and logic. Looking forward to v5 馃憤

In case it helps anyone else, I've updated the sandbox and pulled it more in line with the cookbook article:

https://codesandbox.io/s/casl-demo-roles-with-static-permissions-02kls?file=/src/index.ts

Was this page helpful?
0 / 5 - 0 ratings

Related issues

victorsilent picture victorsilent  路  4Comments

hckhanh picture hckhanh  路  3Comments

nidkil picture nidkil  路  5Comments

SebUndefined picture SebUndefined  路  4Comments

chickenandsnake picture chickenandsnake  路  6Comments