Hi. Thanks for sharing this repo and posting that article. Really helpful.
I modified and tried the abilities.js
for a simpler use case (no anonymous access, no user-specific acl):
abilities.js
const { AbilityBuilder, Ability } = require('casl');
const { Forbidden } = require('@feathersjs/errors');
const TYPE_KEY = Symbol.for('type');
Ability.addAlias('update', 'patch');
Ability.addAlias('read', ['get', 'find']);
Ability.addAlias('remove', 'delete');
Ability.addAlias('create', 'create');
function subjectName(subject) {
if (!subject || typeof subject === 'string') {
return subject;
}
return subject[TYPE_KEY];
}
function defineAbilitiesFor(groupName) {
const { rules, can } = AbilityBuilder.extract();
/* eslint-disable */
switch(groupName) {
case 'Administrators':
can('manage', 'all');
break;
case 'Sales':
can('manage', ['events']);
break;
case 'Logistics':
can('read', 'deliveries');
break;
case 'Warehouse':
can('manage', 'inventories');
break;
}
/* eslint-enable */
return new Ability(rules, { subjectName });
}
module.exports = function authorize(name = null) {
return async function(context) {
const action = context.method;
const service = name || context.path;
const groupName = context.params.user.groupName;
const ability = defineAbilitiesFor(groupName);
if (ability.cannot(action, service)) {
throw new Forbidden(`You are not allowed to ${action} ${service}`);
}
return context;
};
};
This is how it's being called:
app.hooks.js
module.exports = {
before: {
all: [
authenticate('jwt'),
when(
context => context.params.provider && `/${context.path}` !== context.app.get('authentication').path,
authorize(),
),
logger()
],
find: [ includer() ],
get: [ includer() ],
create: [],
update: [],
patch: [],
remove: []
},
after: {
all: [ logger() ],
find: [ dehydrator() ],
get: [],
create: [],
update: [],
patch: [],
remove: []
},
error: {
all: [ logger() ],
find: [],
get: [],
create: [],
update: [],
patch: [],
remove: []
}
};
It works on simple tests (eg, simple find) but when I use it with the mobile app I'm working on, I'm having this error:
error: RangeError: Maximum call stack size exceeded
at Array.reduce (native)
It works when I remove the authorize hook. Any hints on how I can further debug this? Thanks.