Skip to content

Commit

Permalink
Add adminRoles options
Browse files Browse the repository at this point in the history
  • Loading branch information
kostia-official committed May 10, 2017
1 parent cbf39ac commit 4f8b5ee
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 20 deletions.
22 changes: 8 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,13 @@ const app = feathers();
app.configure(rest())
.configure(services)
.configure(acl(aclConfig, {
denyNotAllowed: true, // deny all routes without "allow" rules
mongooseConnection: db, // need for owner rule
denyNotAllowed: true, // deny all routes without "allow" rules
adminRoles: ['admin'], // allow all listed in config routes for this role
baseUrl: 'http://localhost:8080', // need for owner rule
jwt: {
secret: 'blab',
header: 'x-auth' // Default is 'Authorization'
options: {} // options for 'jsonwebtoken' lib
header: 'x-auth' // Default is 'Authorization'
options: {} // options for 'jsonwebtoken' lib
}
}));

Expand Down Expand Up @@ -71,7 +72,7 @@ It gets user's role from `req.payload.roles` array.

### Owner

Give access only for MongoDB document creator. First of all set:
Give access only for owner. Makes request to GET route and checks `ownerField`. First of all set:

```
app.configure(acl(config, { mongooseConnection: db }));
Expand All @@ -81,18 +82,11 @@ Then in config declare:

```
allow: {
owner: {
where: { _id: '{params.id}' },
model: 'posts',
ownerField: 'author'
}
owner: { ownerField: 'author' }
}
```

`where` - how to find needed document. Set in {} path to needed values in `req` object. Default is `{ _id: '{params.id}' }`.
`model` - mongoose model. By default can be got from route url. For example `posts` on `/posts`.
`ownerField` - where you store user id?

`ownerField` - where do you store user id?
It gets user's id from `req.payload.userId`.

### Authenticated
Expand Down
5 changes: 5 additions & 0 deletions src/rule-checker/has-role.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const _ = require('lodash');

module.exports = (adminRoles, payload) => {
return _.some(adminRoles, (role) => _.includes(_.get(payload, 'roles'), role));
};
5 changes: 4 additions & 1 deletion src/rule-checker/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ const promdash = require('promdash').default;
const rolesRule = require('./rules/roles');
const ownerRule = require('./rules/owner');
const authenticatedRule = require('./rules/authenticated');
const hasRole = require('./has-role');

module.exports = ({ customRules, baseUrl, adminRoles }) => (payload, allow, req) => {
if (hasRole(adminRoles, payload)) return Promise.resolve(true);

module.exports = ({ customRules, baseUrl }) => (payload, allow, req) => {
const rules = Object.assign({
roles: rolesRule(),
authenticated: authenticatedRule(),
Expand Down
5 changes: 4 additions & 1 deletion src/rule-checker/rules/roles.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
const _ = require('lodash');
const httpError = require('http-errors');
const hasRole = require('../has-role');

module.exports = () => (payload, allow) => {
const allowRolesList = _.get(allow, 'roles');
if (!allowRolesList) return Promise.resolve(true);

const roles = _.get(payload, 'roles');
const isAllowed = _.some(roles, (role) => _.includes(allowRolesList, role));
if (!roles) return Promise.reject(httpError(403, 'No role.'));

const isAllowed = hasRole(allowRolesList, payload);
if (!isAllowed) return Promise.reject(httpError(403, 'Wrong roles: ' + roles));

return Promise.resolve(isAllowed);
};
16 changes: 12 additions & 4 deletions test/integration/rules.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@ const { test, App } = require('../env');

const config = [{
url: '/posts', method: 'POST',
allow: { roles: ['admin'] }
allow: { roles: ['admin', 'client'] }
}, {
url: '/posts/:id', method: 'GET',
allow: {
owner: { where: { _id: '{params.id}' }, ownerField: 'userId' },
roles: ['admin']
roles: ['admin', 'client']
}
}];
const userId = '5901af327b35960019ee8b2e';

test('should be allowed for all rules', async (t) => {
const app = App(config, {}, { roles: ['admin'], userId });
const app = App(config, {}, { roles: ['client'], userId });
const post = await app.post('/posts').send({ userId });
const { error } = await app.get('/posts/' + post.body._id);

Expand All @@ -30,10 +30,18 @@ test('should be denied because of role', async (t) => {
});

test('should be denied because of owner', async (t) => {
const app = App(config, {}, { roles: ['admin'], userId });
const app = App(config, {}, { roles: ['client'], userId });
const post = await app.post('/posts').send();
const { error } = await app.get('/posts/' + post.body._id);

t.is(error.text, 'No permissions.');
t.is(error.status, 403);
});

test('should be denied because of admin role', async (t) => {
const app = App(config, { adminRoles: ['admin'] }, { roles: ['admin'] });
const post = await app.post('/posts').send();
const { error } = await app.get('/posts/' + post.body._id);

t.falsy(error);
});

0 comments on commit 4f8b5ee

Please sign in to comment.