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
6.05k stars 270 forks source link

`AbilityBuilder` fails when the ability factory is an arrow function #981

Closed forivall closed 1 month ago

forivall commented 1 month ago

Describe the bug

AbilityBuilder fails when the ability factory is an arrow function with the error

TypeError: Cannot read properties of undefined (reading 'possibleRulesFor')
  at isAbilityClass (node_modules/@casl/ability/src/AbilityBuilder.ts:87:8)
  at AbilityBuilder.build (node_modules/@casl/ability/src/AbilityBuilder.ts:124:5)

This is because arrow functions don't have a .prototype property, and so isAbilityClass fails.

function isAbilityClass(factory: AbilityFactory<any>): factory is AnyClass {
  return typeof factory.prototype.possibleRulesFor === 'function';
  //                    ^ does not exist on arrow functions!
}

To Reproduce Steps to reproduce the behavior:

const wrappedCreateMongoAbility = (rules, options) => createMongoAbility(rules, { myOption: true, ...options });
const builder = new AbilityBuilder(wrappedCreateMongoAbility);
builder.can('read', 'foo');
builder.build();

Expected behavior

AbilityBuilder should work with arrow functions as the factory.

Interactive example (optional, but highly desirable) N/A

CASL Version

@casl/ability - v6.7.1 @casl/mongoose - v8.0.2

Environment:

NodeJS v20.13.1