feathersjs-ecosystem / feathers-permissions

Simple role and service method permissions for Feathers
MIT License
184 stars 29 forks source link

Dynamic Permission Creation not working as expected #69

Closed ericuldall closed 4 years ago

ericuldall commented 4 years ago

I assume I'm doing something incorrect here...

const checkPermissions = require('feathers-permissions');
module.exports = {
  before: {
    all: [
        checkPermissions({
          roles: async context => {
            const { user } = context.params;
            console.log('USER ROLES:', user.roles);
            const roles = await context.app.service('roles').find({
              query: {
                name: {
                  $in: user.roles
                }
              }
            });
            console.log('ROLES:', roles);
            let permissions = [];
            for (let role of roles.data) {
                permissions = permissions.concat(role.permissions);
            }
            console.log('PERMISSIONS:', permissions);
            return permissions;
          }
        })
    ],
    find: [],
    get: [],
    create: [],
    update: [],
    patch: [],
    remove: []
  },

  after: {
    all: [],
    find: [],
    get: [],
    create: [],
    update: [],
    patch: [],
    remove: []
  },

  error: {
    all: [],
    find: [],
    get: [],
    create: [],
    update: [],
    patch: [],
    remove: []
  }
};                                                                                                                                                                                                                                                                         

This is designed to allow roles that can be changed thus persisting new sets of permissions to users, rather than storing permissions in every user record. I've verified that in my test permissions returns ['*'] so it should not get any denied error. Am I using this method incorrectly?

Thanks!

ericuldall commented 4 years ago

I've found the issue. I was a bit lost in the roles/permissions rabbit hole... So what I needed to do was define the role for my service using roles: [context.path] and then add another hook before that to dynamically generate the users permissions based on the users roles. Idea being that a user may belong to multiple roles and all of those permissions should be combined.

Working Code Below

const checkPermissions = require('feathers-permissions');
const getUserPermissions = async context => {
  const { user } = context.params;
  const roles = await context.app.service('roles').find({
    query: {
      name: { $in: user.roles }
    }
  });
  let permissions = [];
  for (let role of roles.data) {
    permissions = permissions.concat(role.permissions);
  }
  context.params.user.permissions = permissions;
  return context;
};
module.exports = {
  before: {
    all: [
       getUserPermissions,
       checkPermissions({
         roles: context => {
            return [context.path]
         }
       })
    ]
  },

  after: {
    all: [],
    find: [],
    get: [],
    create: [],
    update: [],
    patch: [],
    remove: []
  },

  error: {
    all: [],
    find: [],
    get: [],
    create: [],
    update: [],
    patch: [],
    remove: []
  }
};

Sample Database Schema

// user collection
User {
...,
roles: ['admin', 'user']
}

// roles collection
Role {
name: 'admin',
permissions: ['*', ...]
}

Role {
name: 'user',
permissions: ['users:find', 'users:get', ...]
}

Works fantastically now :D