@incdevco/framework
Version:
node.js lambda framework
198 lines (102 loc) • 3.64 kB
JavaScript
'use strict';
var Promise = require('bluebird');
var Utilities = require('../utilities');
class ACL {
constructor() {
this.parents = {};
this.resources = {};
this.rules = {};
}
allow(role, resource, privileges, assertion) {
var self = this;
resource = resource || '*';
privileges = privileges || '*';
if (typeof assertion !== 'function') {
assertion = true;
}
if (!Array.isArray(privileges)) {
privileges = [privileges];
}
this.rules[role] = this.rules[role] || {};
this.resources[resource] = this.resources[resource] || {};
this.rules[role][resource] = this.rules[role][resource] || {};
privileges.forEach(function(privilege) {
self.resources[resource][privilege] = assertion;
self.rules[role][resource][privilege] = assertion;
});
return this;
}
getRoleParents(role, parents) {
var first, rolesParents, self = this;
first = (parents) ? false : true;
parents = parents || [];
rolesParents = this.parents[role] || [];
parents = parents.concat(rolesParents);
rolesParents.forEach(function (rolesParent) {
parents = self.getRoleParents(rolesParent, parents);
});
if (first) { // run only once
// remove duplicates
parents = Utilities.unique(parents);
}
return parents;
}
inherit(role, parents) {
this.parents[role] = this.parents[role] || [];
this.parents[role] = this.parents[role].concat(parents);
return this;
}
isAllowed(role, resource, privileges, locals) {
var promise = Promise.resolve(false), roles = [role], self = this;
roles = roles.concat(this.getRoleParents(role));
roles.forEach(function (role) {
promise = promise.then(function (result) {
if (result) { // is allowed
return result;
} else { // not allowed, try next one
return self.isRoleAllowed(role, resource, privileges, locals);
}
});
});
return promise;
}
isRoleAllowed(role, resource, privileges, locals) {
var promises= [], self = this;
if (!Array.isArray(privileges)) {
privileges = [privileges];
}
privileges.forEach(function(privilege) {
promises.push(self.isRoleAllowedPrivilege(role, resource, privilege, locals));
});
return Promise.all(promises)
.then(function (results) {
var allowed = false;
var notAllowed = false;
results.forEach(function (result) {
if (!result) {
notAllowed = true;
}
});
if (!notAllowed) {
allowed = true;
}
return allowed;
});
}
isRoleAllowedPrivilege(role, resource, privilege, locals) {
var self = this;
return Promise.try(function () {
var assertion = false;
if (self.rules[role]
&& self.rules[role][resource]) {
assertion = self.rules[role][resource][privilege];
if (assertion
&& typeof assertion === 'function') {
return assertion(locals);
}
}
return assertion;
});
}
}
module.exports = ACL;