Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

error on new Ability(rules) #305

Closed
raugaral opened this issue May 6, 2020 · 16 comments
Closed

error on new Ability(rules) #305

raugaral opened this issue May 6, 2020 · 16 comments
Labels

Comments

@raugaral
Copy link

raugaral commented May 6, 2020

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<string, SubjectType, unknown> | LegacySubjectRawRule<string, SubjectType, unknown>)[]' is not assignable to parameter of type '(SubjectRawRule<string, SubjectType, unknown> | LegacySubjectRawRule<string, SubjectType, unknown>)[]'.
Type 'ClaimRawRule | LegacyClaimRawRule | SubjectRawRule<string, SubjectType, unknown> | LegacySubjectRawRule<string, SubjectType, unknown>' is not assignable to type 'SubjectRawRule<string, SubjectType, unknown> | LegacySubjectRawRule<string, SubjectType, unknown>'.
Type 'ClaimRawRule' is not assignable to type 'SubjectRawRule<string, SubjectType, unknown> | LegacySubjectRawRule<string, SubjectType, unknown>'.
Type 'ClaimRawRule' is not assignable to type 'SubjectRawRule<string, SubjectType, unknown>'.
Property 'subject' is optional in type 'ClaimRawRule' but required in type 'SubjectRawRule<string, SubjectType, unknown>'.

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

@stalniy
Copy link
Owner

stalniy commented May 6, 2020

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

@stalniy
Copy link
Owner

stalniy commented May 6, 2020

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 } });

@raugaral
Copy link
Author

raugaral commented May 6, 2020

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);
 }

@stalniy
Copy link
Owner

stalniy commented May 6, 2020

Did you tried what I suggested?

@stalniy
Copy link
Owner

stalniy commented May 6, 2020

@raugaral
Copy link
Author

raugaral commented May 6, 2020

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<string, SubjectType, unknown> | LegacySubjectRawRule<string, SubjectType, unknown>)[]' is not assignable to parameter of type '(SubjectRawRule<string, SubjectType, unknown> | LegacySubjectRawRule<string, SubjectType, unknown>)[]'.
Type 'ClaimRawRule | LegacyClaimRawRule | SubjectRawRule<string, SubjectType, unknown> | LegacySubjectRawRule<string, SubjectType, unknown>' is not assignable to type 'SubjectRawRule<string, SubjectType, unknown> | LegacySubjectRawRule<string, SubjectType, unknown>'.
Type 'ClaimRawRule' is not assignable to type 'SubjectRawRule<string, SubjectType, unknown> | LegacySubjectRawRule<string, SubjectType, unknown>'.
Type 'ClaimRawRule' is not assignable to type 'SubjectRawRule<string, SubjectType, unknown>'.
Property 'subject' is optional in type 'ClaimRawRule' but required in type 'SubjectRawRule<string, SubjectType, unknown>'.

@raugaral
Copy link
Author

raugaral commented May 6, 2020

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

@raugaral
Copy link
Author

raugaral commented May 6, 2020

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<string, SubjectType, unknown>?

@stalniy
Copy link
Owner

stalniy commented May 6, 2020

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.

@stalniy
Copy link
Owner

stalniy commented May 6, 2020

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<string, SubjectType, unknown> | LegacySubjectRawRule<string, SubjectType, unknown>)[]' is not assignable to parameter of type '(SubjectRawRule<string, SubjectType, unknown> | LegacySubjectRawRule<string, SubjectType, unknown>)[]'.
Type 'ClaimRawRule | LegacyClaimRawRule | SubjectRawRule<string, SubjectType, unknown> | LegacySubjectRawRule<string, SubjectType, unknown>' is not assignable to type 'SubjectRawRule<string, SubjectType, unknown> | LegacySubjectRawRule<string, SubjectType, unknown>'.
Type 'ClaimRawRule' is not assignable to type 'SubjectRawRule<string, SubjectType, unknown> | LegacySubjectRawRule<string, SubjectType, unknown>'.
Type 'ClaimRawRule' is not assignable to type 'SubjectRawRule<string, SubjectType, unknown>'.
Property 'subject' is optional in type 'ClaimRawRule' but required in type 'SubjectRawRule<string, SubjectType, unknown>'.

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

@stalniy
Copy link
Owner

stalniy commented May 6, 2020

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

@stalniy stalniy closed this as completed May 6, 2020
@Lippur
Copy link

Lippur commented May 23, 2020

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!

@stalniy
Copy link
Owner

stalniy commented May 24, 2020

Thanks for the note. I’ll fix the example in README. But I’d 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’ll remove some legacy types and errors will be easier to understand.

@theGC
Copy link

theGC commented Nov 10, 2020

@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

@stalniy
Copy link
Owner

stalniy commented Nov 10, 2020

@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);

@theGC
Copy link

theGC commented Nov 10, 2020

@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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants