Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

118 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

feathers-permissions

CI Dependency Status Download Status

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.

Installation

npm install feathers-permissions --save

Important: The feathers-permissions hook should be used after the authenticate() hook from @feathersjs/authentication.

Simple example

The following example will limit all messages service calls to users that have admin in their roles:

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: [
    authenticate('jwt'),
    checkPermissions({
      roles: [ 'admin' ]
    })
  ]
});

// User from the database
const user = {
  email: 'someuser@example.com',
  permissions: [ 'admin' ]
}

Documentation

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).

Options

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.

Permission format

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:

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:

app.service('messages').hooks({
  before: checkPermissions({
    roles: context => {
      return [ 'admin', context.path ];
    }
  })
});

Permissions can also be assembled asynchronously:

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;
    }
  })
});

Conditionally restricting permissions

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:

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'
        })
      )
    ]
  }
});

More examples

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
});

License

Copyright (c) 2019

Licensed under the MIT license.

About

Simple role and service method permissions for Feathers

Resources

Contributing

Stars

184 stars

Watchers

10 watching

Forks

Releases

Packages

Contributors

Languages