Simple permissions module for Feathers
npm install feathers-permissions


> Simple role and service method permissions for Feathers
> __Note:__ This module implements a hook simple role and service method based permissions checked against the permissions in a user (entity) object. More complex requirements can already be implemented as custom Feathers hooks. See here and here for more information.
```
npm install feathers-permissions --save
> __Important:__ The feathers-permissions hook should be used after the authenticate() hook from @feathersjs/authentication.
The following example will limit all messages service calls to users that have admin in their roles:
`js
const feathers = require('@feathersjs/feathers');
const memory = require('feathers-memory');
const checkPermissions = require('feathers-permissions');
const app = feathers();
app.use('/messages', memory());
app.service('messages').hooks({
before: checkPermissions({
roles: [ 'admin' ]
})
});
// User from the database
const user = {
email: 'someuser@example.com',
permissions: [ 'admin' ]
}
`
Feathers permissions allows you to grant and manage permissions in a flexible nature based on role and service method. Each object that requires permissions must have an array or a comma separated string of permissions stored on it (typically in your database).
The following options are available:
- roles - A list of permission roles to check or a function that takes the hook context and returns a list of roles. Can be a comma separated string of roles or an array of roles.entity
- (default: user) - The name of the entity (params[entity])field
- (default: permissions) - The name of the permissions field on the entity. May be dot separated to access nested fields.error
- - If set to false will not throw a Forbidden error but instead set params.permitted to true or false. Useful for chaining permission hooks.
The list of permissions will be obtained from params[entity] and field. It can be a comma separate list or an array of permissions in the following format:
- * - Allow everything${role}
- or ${role}:* - Allow every service method (find, get, create, update, patch, remove) for role*:${method}
- - Allow method service method for any role${role}:${method}
- - Allow method service method for role
This means the following use of feathers-permissions:
`js`
app.service('messages').hooks({
before: checkPermissions({
roles: [ 'admin', 'user' ]
})
});
Will allow user permissions containing , admin:, user: and the service method that is being called (e.g. admin:create or user:find and :create and *:find).
The following will create a dynamic permission based on the hook context.path:
`js`
app.service('messages').hooks({
before: checkPermissions({
roles: context => {
return [ 'admin', context.path ];
}
})
});
Permissions can also be assembled asynchronously:
`js
app.service('messages').hooks({
before: checkPermissions({
roles: async context => {
const { user } = context.params;
const roles = await app.service('roles').find({
query: {
userId: user._id
}
});
return roles.data;
}
})
});
`
To conditionally either allow access by roles or otherwise restrict to the current user, a combination of feathers-permissions - setting the error option to false - feathers-authentication-hooks and feathers-hooks-common#iff (checking for params.permitted) can be used:
`js`
app.service('messages').hooks({
before: {
find: [
checkPermissions({
roles: ['super_admin', 'admin'],
field: 'roles',
error: false
}),
iff(context => !context.params.permitted,
setField({
from: 'params.user._id',
as: 'params.query.userId'
})
)
]
}
});
`js
const feathers = require('@feathersjs/feathers');
const memory = require('feathers-memory');
const checkPermissions = require('feathers-permissions');
const app = feathers();
app.use('/messages', memory());
app.service('messages').hooks({
before: checkPermissions({
roles: [ 'admin', 'messages' ]
})
});
// User from the database (e.g. added via @feathersjs/authentication)
const user = {
email: 'someuser@example.com',
permissions: [ 'messages:find', 'messages:get' ]
// Also possible
permissions: 'messages:find,messages:get'
}
const admin = {
email: 'someuser@example.com',
permissions: [ 'admin:*' ]
}
// Will pass
app.service('messages').find({
user
});
// Will fail
app.service('messages').create({
user
});
// Will pass
app.service('messages').create({
provider: 'rest', // this will be set automatically by external calls
user: admin
});
``
Copyright (c) 2019
Licensed under the MIT license.