Casl: About ability inheritance

Created on 4 Sep 2018  路  1Comment  路  Source: stalniy/casl

Can Casl do such thing as ability inheritance?
For example how can I do such a thing like this?

const anyone = AbilityBuilder.define((can) => {
  can('read', 'all');
});
const admin = AbilityBuilder.define((can) => {
  can(What 'anyone' can do)
  can('update', 'all');
  can('remove', 'all');
});
question

>All comments

Hi @tanekim77

Sure, it's quite easy, you just need to keep everything in one ability. Just by quickly thinking I see 3 approaches:

  1. Use role index to detect what should be inherited
const ROLES = ['anyone', 'admin']

function defineAbilitiesFor(user) {
  const { can, rules } = AbilityBuilder.extract()
  const is = role => ROLES.indexOf(user.role) >= ROLES.indexOf(role);

  if (is('moderator')) {
     can('read', 'all')
  }

  if (is('admin')) {
    can('update', 'all');
    can('remove', 'all');
  }

  return new Ability(rules);
}
  1. Use class inheritance (this may be inflexible):
class AnyoneAbility {
  static build() {
    return new AnyoneAbility().ability;
  }

   constructor() {
      this.ability = AbilityBuilder.define(this.define.bind(this));
   }

   define(can, cannot) {
     can('read', 'all')
   }
}

class AdminAbility extends AnyoneAbility {
  define(can, cannot) {
    super.define(can, cannot);
    can('update', 'all');
    can('remove', 'all');
  }
}

const adminAbility = AdminAbility.build()
const anyoneAbility = AnyoneAbility.build()
  1. The same as above but with functions
function anyoneAbility(can, cannot) {
     can('read', 'all')
}

function adminAbility(can, cannot) {
    can('update', 'all');
    can('remove', 'all');
}

const ability = AbilityBuilder.define((can, cannot) => {
   if (/*something*/) {
      anyoneAbility(can, cannot);
   }

   if (/* something additionality */) {
     adminAbility(can, cannot);
   }
})

I guess you understood the basic idea :)

Thanks for using CASL!

Was this page helpful?
0 / 5 - 0 ratings