Skip to content

Commit

Permalink
Merge pull request #2 from kozzztya/deny-not-allowed
Browse files Browse the repository at this point in the history
Deny not allowed routes
  • Loading branch information
kostia-official committed May 6, 2017
2 parents 69745f4 + 34501ea commit 3fa43e4
Show file tree
Hide file tree
Showing 10 changed files with 67 additions and 38 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ 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
jwt: {
secret: 'blab',
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "feathers-acl",
"version": "0.5.0",
"version": "0.6.0",
"description": "Declarative ACL for FeathersJS and Express apps",
"main": "dist/index.js",
"scripts": {
Expand Down
6 changes: 6 additions & 0 deletions src/deny-not-allowed.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
const _ = require('lodash');

module.exports = () => (req, res, next) => {
if (!_.has(req, 'acl.allowed')) return res.status(403).send('Route is not allowed.');
next();
};
12 changes: 7 additions & 5 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
const _ = require('lodash');
const ruleChecker = require('./rule-checker');
const jwtDecode = require('./jwt-decode');
const denyNotAllowed = require('./deny-not-allowed');

module.exports = (configs, { customRules, mongooseConnection, jwt } = {}) => function () {
module.exports = (configs, options = {}) => function () {
const app = this;
if (jwt) app.use(jwtDecode(jwt));

const check = ruleChecker({ customRules, mongooseConnection, jwt });
const check = ruleChecker(options);
if (options.jwt) app.use(jwtDecode(options.jwt));

_.forEach(configs, ({ url, method, allow }) => {

app.all(url, (req, res, next) => {
if (method !== req.method) return next();
req.acl = { allowed: true };

check(req.payload, allow, req)
.then(() => next())
.catch(err => res.status(err.status || 500).send(err.message));
});

});

if (options.denyNotAllowed) app.use(denyNotAllowed());
};
10 changes: 6 additions & 4 deletions test/env/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,22 @@ const lib = require('../../src');
const db = require('./db');
const jwt = require('./jwt');

module.exports = (config, customRules, payload) => {
module.exports = (config, options, payload) => {
const app = feathers();

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.configure(rest());
app.configure(hooks());
app.use((req, res, next) => {
if (payload) req.payload = payload;
if (payload) req.headers.authorization = jwt.sign(payload);
next();
});
app.configure(lib(config, {
customRules, mongooseConnection: db, jwt: { secret: jwt.secret }
}));
app.configure(lib(config, options &&
Object.assign({
mongooseConnection: db, jwt: { secret: jwt.secret }, denyNotAllowed: true
}, options)));
app.service('/posts', new Service({
Model: db.model('posts')
}));
Expand Down
27 changes: 27 additions & 0 deletions test/integration/deny-not-allowed.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
const { test, App } = require('../env');

const config = [
{
url: '/posts', method: 'GET',
allow: { roles: ['client'] }
}
];

test('should be allowed to read for client', async (t) => {
const app = App(config, {}, { roles: ['client'] });
const { error } = await app.get('/posts');
t.falsy(error);
});

test('should be allowed to delete all if no option set', async (t) => {
const app = App(config, { denyNotAllowed: false }, { roles: ['client'] });
const { error } = await app.delete('/posts');
t.falsy(error);
});

test('should be denied to delete all for client', async (t) => {
const app = App(config, {}, { roles: ['client'] });
const { error } = await app.delete('/posts');
t.is(error.status, 403);
t.is(error.text, 'Route is not allowed.');
});
12 changes: 12 additions & 0 deletions test/integration/lib-options.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
const { test, App } = require('../env');

const config = [{
url: '/posts', method: 'GET',
allow: { roles: ['client'] }
}];

test('should work without options', async (t) => {
const app = App(config, undefined, { roles: ['client'] });
const { error } = await app.get('/posts');
t.falsy(error);
});
3 changes: 3 additions & 0 deletions test/integration/rules.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
const { test, App } = require('../env');

const config = [{
url: '/posts', method: 'POST',
allow: { roles: ['admin'] }
}, {
url: '/posts/:id', method: 'GET',
allow: {
owner: { where: { _id: '{params.id}' }, model: 'posts', ownerField: 'userId' },
Expand Down
12 changes: 4 additions & 8 deletions test/integration/url.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
const { test, App } = require('../env');

const config = [
{
url: '/posts', method: 'POST',
allow: { roles: ['client'] }
},
{
url: '/posts', method: 'GET',
allow: { roles: ['admin'] }
Expand Down Expand Up @@ -40,11 +44,3 @@ test('should be denied to read one post for admin', async (t) => {

t.truthy(error);
});

test('should be allowed to delete post if no acl set', async (t) => {
const app = App(config, {}, {});
const post = await app.post('/posts');
const { error } = await app.delete('/posts/' + post.body._id);

t.falsy(error);
});
20 changes: 0 additions & 20 deletions test/unit/lib-arguments.test.js

This file was deleted.

0 comments on commit 3fa43e4

Please sign in to comment.