Skip to content

Commit

Permalink
Breaking change: throw when attempting to re-define actions, roles or…
Browse files Browse the repository at this point in the history
… entities.

This prevents accidentally overwriting authorization rules with weaker
rules. Such an accident becomes more likely as apps grow in size and
could lead to an security vulnerability.

Fixes tschaub#11
  • Loading branch information
markstos committed Apr 2, 2021
1 parent 996a9b9 commit e7e2768
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 9 deletions.
1 change: 1 addition & 0 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ module.exports = function(grunt) {
var testSrc = 'test/**/*.js';

var lintOptions = {
esversion: 6,
curly: true,
eqeqeq: true,
indent: 2,
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ Register a getter for a role. If the role is a string of the form
`entity.relation`, a getter for the entity must be registered with the
[`entity`](#manager.entity) method. Roles without `.` are "simple" roles (e.g.
`"admin"`) and no entity is looked up. Throws [`ConfigError`](#configerror) if
called with an invalid role name.
called with an invalid or duplicate role name.

#### <a id='manager.entity'>`entity(type, getter)`</a>

Expand All @@ -183,7 +183,7 @@ called with an invalid role name.
generated while getting the entity and the second is the target entity.

Register a getter for an entity. Throws [`ConfigError`](#configerror) if called
with invalid arguments.
with invalid arguments or duplicate entity name.

#### <a id='manager.action'>`action(name, roles)`</a>

Expand All @@ -194,7 +194,7 @@ with invalid arguments.

Specify the roles that a user must have to perform the named action. Throws
[`ConfigError`](#configerror) if the provided roles have not yet been registered
with the [`role`](#manager.role) method.
with the [`role`](#manager.role) method or if the action name is a duplicate.

#### <a id='manager.can'>`can(action)`</a>

Expand Down
15 changes: 15 additions & 0 deletions lib/manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@ Manager.prototype.action = function(name, roles) {
}
return role;
});

if (name in this.actionDefs_) {
throw new errors.ConfigError(`action already registered: ${name}`);
}

this.actionDefs_[name] = roles;
};

Expand Down Expand Up @@ -181,6 +186,11 @@ Manager.prototype.entity = function(type, getter) {
throw new errors.ConfigError(
'Entity getter must be a function that takes two arguments');
}

if (type in this.entityGetters_) {
throw new errors.ConfigError(`entity already registered: ${type}`);
}

this.entityGetters_[type] = getter;
};

Expand Down Expand Up @@ -294,6 +304,11 @@ Manager.prototype.role = function(role, getter) {
throw new errors.ConfigError(
'Getters for simple roles (without entities) take two arguments');
}

if (role.name in this.roleGetters_) {
throw new errors.ConfigError(`role already registered: ${role.name}`);
}

this.roleGetters_[role.name] = getter;
};

Expand Down
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,8 @@
"dependencies": {
"async": "^0.9.0",
"pause": "0.0.1"
},
"engines": {
"node": ">=10"
}
}
39 changes: 33 additions & 6 deletions test/lib/manager.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,16 +107,25 @@ describe('Manager', function() {
// pretend nobody is admin
done(null, false);
});
auth.role('page.author', function(page, req, done) {
// pretend everybody is author
done(null, true);
});

assert.throws(function() {
auth.action('can edit page', ['admin', 'page.author']);
});
});

it('throws when attempting to define action twice', function() {
auth.role('admin', function(req, done) {
done(null, false);
});

auth.action('can edit page', ['admin']);

assert.throws(function() {
auth.action('can edit page', ['admin']);
});
});


});

describe('#can()', function() {
Expand Down Expand Up @@ -318,6 +327,16 @@ describe('Manager', function() {
}, ConfigError);
});

it('throws when attempting to define entity twice', function() {
assert.doesNotThrow(function() {
auth.entity('page', (req, done) => done(null, {}));
});
assert.throws(() => {
auth.entity('page', (req, done) => done(null, {}));
});
});


});

describe('#role()', function() {
Expand Down Expand Up @@ -405,7 +424,15 @@ describe('Manager', function() {
}, ConfigError);
});

});

it('throws when attempting to define a role twice', function() {
auth.role('admin', function(req, done) {
// pretend nobody is admin
done(null, false);
});

assert.throws(() => {
auth.role('admin', (req, done) => done(null, false));
});
});
});
});

0 comments on commit e7e2768

Please sign in to comment.