casl: Abilities don't behave the way I expected from the docs

Hey @stalniy, First of all, thank you for the great library. I’ve been going through the docs and, no matter what, I can’t make the rules work as I would like to.

Describe the bug

My goal is to define a set of abilities so that we can only access a Person with id = 2. Therefore:

  • I shouldn’t be able to access a Person with an ID != 2
  • I shouldn’t be able to access a Person without specifying an ID

To Reproduce

Minimal example to reproduce:

import { Ability, InferSubjects, AbilityBuilder, subject } from "@casl/ability";

export type Actions = "create" | "read" | "update" | "delete";

interface Person {
  id: number;
}

export type SubjectTypes = Person | "Person";
export type Subjects = InferSubjects<SubjectTypes>;
export type MyAbility = Ability<[Actions, Subjects]>;

const getAbilities = (): MyAbility => {
  const { can, cannot, build } = new AbilityBuilder<MyAbility>();
  can("read", "Person", { id: { $in: [ 2 ] } })
  return build()
}

const abilities = getAbilities()
console.log(abilities.can("read", "Person"))
console.log(abilities.can("read", subject("Person", {id: 1})))
console.log(abilities.can("read", subject("Person", {id: 2})))

Expected behavior I would expect to get: -> console.log(abilities.can("read", "Person")) -> False (because I should only be able to access Person with ID = 2) -> console.log(abilities.can("read", subject("Person", {id: 1}))) -> False -> console.log(abilities.can("read", subject("Person", {id: 2}))) -> True

What I get instead is true to all the conditions.

I also tried using defineAbility instead:

const abilities = defineAbility((can) => {
  can("read", "Person", { id: { $in: [2] } });
});

and in that case, I get: -> console.log(abilities.can("read", "Person")) -> True (shouldn’t it be false?) -> console.log(abilities.can("read", subject("Person", {id: 1}))) -> False Ok -> console.log(abilities.can("read", subject("Person", {id: 2}))) -> True Ok

Interactive example

https://codesandbox.io/s/modern-breeze-q5ue1?file=/src/index.ts

CASL Version

@casl/ability - v 4.1.6

Environment:

Windows 10, Node JS: v12.16.1

Do you have any idea why I’m facing these problems? Thank you for your time

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 22 (10 by maintainers)

Most upvoted comments

I read about grammar difference between may and might. And the last one fits better. So let’s stick to “might” for now

RFC is a good idea. Take into consideration:

  1. rule definitions through AbilityBuilder (so we don’t need to add may to AbilityBuilder)
  2. accessibleBy method in @casl/mongoose. Will it be clear what records will be returned if you define both can have Apple and can have green apple

So, we don’t confuse people more

Maybe I can create an issue and propose it like an RFC and see what others think about it ?