stalniy / casl

CASL is an isomorphic authorization JavaScript library which restricts what resources a given user is allowed to access
https://casl.js.org/
MIT License
5.93k stars 269 forks source link

Invalid result when checking ability with conditions #354

Closed izziaraffaele closed 4 years ago

izziaraffaele commented 4 years ago

Describe the bug Very simple rules conditions are not checked correctly on the subject passed to the ability checker class. Checking ability without providing a subject works as expected but as soon as I provide a subject I'm starting getting false positive. Is it a bug or am I doing something wrong?

To Reproduce

Node.js

const { AbilityBuilder, subject } = require("@casl/ability");

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

can(["read", "update", "delete"], "User", { id: "my-own-id" });

const ability = build();

console.log("Can update at least one user?", ability.can("update", "User")); // true

console.log("Can update my own user?", ability.can("update", subject("User", { id: "my-own-id" }))); // true

console.log("Can update other users?", ability.can("update", subject("User", { id: "another-user-id" }))); // true -> I expect this to be false

I also tried explicitly specifying cannot rules but I'm getting the same result

const { AbilityBuilder, subject } = require("@casl/ability");

const { can, cannot, build } = new AbilityBuilder();

cannot(["create", "read", "update", "delete"], "User");
can(["read", "update", "delete"], "User", { id: "my-own-id" });

....

Expected behavior In the example above I expect the log Can update other users? to be false as the id of the provided subject is different from the one stated in the rule definition

Interactive example https://codesandbox.io/s/heuristic-cherry-psefr

stalniy commented 4 years ago

I faced a common mistake. AbilityBuilder accepts an AbilityType which by default equals to PureAbility. Check the API docs - https://casl.js.org/v4/en/api/casl-ability#ability-builder-constructor

There are 2 types of Ability:

So, to fix your example, replace const { can, build } = new AbilityBuilder(); with const { can, build } = new AbilityBuilder(Ability);

stalniy commented 4 years ago

You can get some details here as well