accesscontrol
Advanced tools
Comparing version 1.0.0 to 1.0.1
@@ -1,142 +0,163 @@ | ||
'use strict';Object.defineProperty(exports, "__esModule", { value: true });var _createClass = function () {function defineProperties(target, props) {for (var i = 0; i < props.length; i++) {var descriptor = props[i];descriptor.enumerable = descriptor.enumerable || false;descriptor.configurable = true;if ("value" in descriptor) descriptor.writable = true;Object.defineProperty(target, descriptor.key, descriptor);}}return function (Constructor, protoProps, staticProps) {if (protoProps) defineProperties(Constructor.prototype, protoProps);if (staticProps) defineProperties(Constructor, staticProps);return Constructor;};}();var _Factory = require('./Factory');var _Factory2 = _interopRequireDefault(_Factory); | ||
var _helper = require('./lib/helper');var _helper2 = _interopRequireDefault(_helper);function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };}function _classCallCheck(instance, Constructor) {if (!(instance instanceof Constructor)) {throw new TypeError("Cannot call a class as a function");}} | ||
'use strict'; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); | ||
var _Factory = require('./Factory'); | ||
var _Factory2 = _interopRequireDefault(_Factory); | ||
var _helper = require('./lib/helper'); | ||
var _helper2 = _interopRequireDefault(_helper); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
/** | ||
* AccessControl class that implements RBAC (Role-Based Access Control) basics | ||
* and ABAC (Attribute-Based Access Control) <i>resource</i> and <i>action</i> | ||
* attributes. | ||
* @author Onur Yıldırım (onur@cutepilot.com) | ||
* @license MIT | ||
* | ||
* | ||
* @example | ||
* var ac = new AccessControl(grants); | ||
* | ||
* ac.grant('admin').createAny('profile'); | ||
* | ||
* // or you can chain methods | ||
* ac.grant('admin') | ||
* .createAny('profile') | ||
* .readAny('profile', ["*", "!password"]) | ||
* .readAny('video') | ||
* .deleteAny('video'); | ||
* | ||
* // since these permissions have common resources, there is an alternative way: | ||
* ac.grant('admin') | ||
* .resource('profile').createAny().readAny(null, ["*", "!password"]) | ||
* .resource('video').readAny()..deleteAny(); | ||
* | ||
* ac.grant('user') | ||
* .readOwn('profile', ["uid", "email", "address.*", "account.*", "!account.roles"]) | ||
* .updateOwn('profile', ["uid", "email", "password", "address.*", "!account.roles"]) | ||
* .deleteOwn('profile') | ||
* .createOwn('video', ["*", "!geo.*"]) | ||
* .readAny('video') | ||
* .updateOwn('video', ["*", "!geo.*"]) | ||
* .deleteOwn('video'); | ||
* | ||
* var permission = ac.can('admin').readAny('profile'); | ||
* permission.granted // true | ||
* permission.attributes // ["*", "!password"] | ||
* permission.filter(data) // { uid, email, address, account } | ||
* | ||
* ac.deny('admin').createAny('profile'); | ||
* ac.can('admin').createAny('profile').granted // false | ||
* | ||
* // To add a grant but deny access | ||
* ac.grant('admin').createAny('profile', []); // no attributes allowed | ||
* ac.can('admin').createAny('profile').granted // false | ||
* | ||
* console.log(ac.getGrants()); | ||
* // outputs: | ||
* { | ||
* admin: { | ||
* profile: { | ||
* "read:any": ["*", "!password"], | ||
* "update:any": ["*"], | ||
* "delete:any": ["*"] | ||
* }, | ||
* video: { | ||
* "read:any": ["*"], | ||
* "update:any": ["*", "!userId"], | ||
* "delete:any": ["*"] | ||
* } | ||
* }, | ||
* user: { | ||
* profile: { | ||
* "read:own": ["uid", "email", "address.*", "!account.roles"], | ||
* "update:own": ["uid", "email", "password", "address.*", "!account.roles"], | ||
* "delete:own": ["*"] | ||
* }, | ||
* video: { | ||
* "create:own": ["*", "!geo.*"], | ||
* "read:any": ["*"], | ||
* "update:own": ["*", "!geo.*"], | ||
* "delete:own": ["*"], | ||
* } | ||
* } | ||
* } | ||
*/var | ||
AccessControl = function () { | ||
* AccessControl class that implements RBAC (Role-Based Access Control) basics | ||
* and ABAC (Attribute-Based Access Control) <i>resource</i> and <i>action</i> | ||
* attributes. | ||
* @author Onur Yıldırım (onur@cutepilot.com) | ||
* @license MIT | ||
* | ||
* | ||
* @example | ||
* var ac = new AccessControl(grants); | ||
* | ||
* ac.grant('admin').createAny('profile'); | ||
* | ||
* // or you can chain methods | ||
* ac.grant('admin') | ||
* .createAny('profile') | ||
* .readAny('profile', ["*", "!password"]) | ||
* .readAny('video') | ||
* .deleteAny('video'); | ||
* | ||
* // since these permissions have common resources, there is an alternative way: | ||
* ac.grant('admin') | ||
* .resource('profile').createAny().readAny(null, ["*", "!password"]) | ||
* .resource('video').readAny()..deleteAny(); | ||
* | ||
* ac.grant('user') | ||
* .readOwn('profile', ["uid", "email", "address.*", "account.*", "!account.roles"]) | ||
* .updateOwn('profile', ["uid", "email", "password", "address.*", "!account.roles"]) | ||
* .deleteOwn('profile') | ||
* .createOwn('video', ["*", "!geo.*"]) | ||
* .readAny('video') | ||
* .updateOwn('video', ["*", "!geo.*"]) | ||
* .deleteOwn('video'); | ||
* | ||
* var permission = ac.can('admin').readAny('profile'); | ||
* permission.granted // true | ||
* permission.attributes // ["*", "!password"] | ||
* permission.filter(data) // { uid, email, address, account } | ||
* | ||
* ac.deny('admin').createAny('profile'); | ||
* ac.can('admin').createAny('profile').granted // false | ||
* | ||
* // To add a grant but deny access | ||
* ac.grant('admin').createAny('profile', []); // no attributes allowed | ||
* ac.can('admin').createAny('profile').granted // false | ||
* | ||
* console.log(ac.getGrants()); | ||
* // outputs: | ||
* { | ||
* admin: { | ||
* profile: { | ||
* "read:any": ["*", "!password"], | ||
* "update:any": ["*"], | ||
* "delete:any": ["*"] | ||
* }, | ||
* video: { | ||
* "read:any": ["*"], | ||
* "update:any": ["*", "!userId"], | ||
* "delete:any": ["*"] | ||
* } | ||
* }, | ||
* user: { | ||
* profile: { | ||
* "read:own": ["uid", "email", "address.*", "!account.roles"], | ||
* "update:own": ["uid", "email", "password", "address.*", "!account.roles"], | ||
* "delete:own": ["*"] | ||
* }, | ||
* video: { | ||
* "create:own": ["*", "!geo.*"], | ||
* "read:any": ["*"], | ||
* "update:own": ["*", "!geo.*"], | ||
* "delete:own": ["*"], | ||
* } | ||
* } | ||
* } | ||
*/ | ||
var AccessControl = function () { | ||
/** | ||
* Initializes a new instance of `AccessControl` with the given grants. | ||
* | ||
* @param {Object|Array} grants - A list containing the access grant | ||
* definitions. See the structure of this object in the examples. | ||
* | ||
* @example | ||
* var grants = { | ||
* role1: { | ||
* resource1: { | ||
* "create:any": [ attrs ], | ||
* "read:own": [ attrs ] | ||
* }, | ||
* resource2: { | ||
* "create:any": [ attrs ], | ||
* "update:own": [ attrs ] | ||
* } | ||
* }, | ||
* role2: { ... } | ||
* }; | ||
* var ac = new AccessControl(grants); | ||
* | ||
* // The passed object can also be an array, such as a flat list | ||
* // fetched from a database. | ||
* | ||
* var flatList = [ | ||
* { role: "role1", resource: "resource1", action: "create:any", attributes: [ attrs ] }, | ||
* { role: "role1", resource: "resource1", action: "read:own", attributes: [ attrs ] }, | ||
* { role: "role2", ... }, | ||
* ... | ||
* ]; | ||
* | ||
* // We turn this list into a hashtable for better performance. We aggregate | ||
* // the list by roles first, resources second. If possession (in action | ||
* // value or as a separate property) is omitted, it will default to "any". | ||
* // e.g. "create" —> "create:any" | ||
* | ||
* // Below are equivalent: | ||
* { role: "role1", resource: "resource1", action: "create:any", attributes: [ attrs ] } | ||
* { role: "role1", resource: "resource1", action: "create", possession: "any", attributes: [ attrs ] } | ||
* | ||
* var ac = new AccessControl(flatList); | ||
* console.log(ac.getGrants()); | ||
* | ||
* // This flat list is turned into: | ||
* { | ||
* role1: { | ||
* resource1: { | ||
* "create:any": [ attrs ], | ||
* "read:own": [ attrs ] | ||
* }, | ||
* resource2: { | ||
* "create:any": [ attrs ], | ||
* "update:own": [ attrs ] | ||
* } | ||
* }, | ||
* role2: { ... } | ||
* } | ||
*/ | ||
function AccessControl() {var grants = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];_classCallCheck(this, AccessControl); | ||
* Initializes a new instance of `AccessControl` with the given grants. | ||
* | ||
* @param {Object|Array} grants - A list containing the access grant | ||
* definitions. See the structure of this object in the examples. | ||
* | ||
* @example | ||
* var grants = { | ||
* role1: { | ||
* resource1: { | ||
* "create:any": [ attrs ], | ||
* "read:own": [ attrs ] | ||
* }, | ||
* resource2: { | ||
* "create:any": [ attrs ], | ||
* "update:own": [ attrs ] | ||
* } | ||
* }, | ||
* role2: { ... } | ||
* }; | ||
* var ac = new AccessControl(grants); | ||
* | ||
* // The passed object can also be an array, such as a flat list | ||
* // fetched from a database. | ||
* | ||
* var flatList = [ | ||
* { role: "role1", resource: "resource1", action: "create:any", attributes: [ attrs ] }, | ||
* { role: "role1", resource: "resource1", action: "read:own", attributes: [ attrs ] }, | ||
* { role: "role2", ... }, | ||
* ... | ||
* ]; | ||
* | ||
* // We turn this list into a hashtable for better performance. We aggregate | ||
* // the list by roles first, resources second. If possession (in action | ||
* // value or as a separate property) is omitted, it will default to "any". | ||
* // e.g. "create" —> "create:any" | ||
* | ||
* // Below are equivalent: | ||
* { role: "role1", resource: "resource1", action: "create:any", attributes: [ attrs ] } | ||
* { role: "role1", resource: "resource1", action: "create", possession: "any", attributes: [ attrs ] } | ||
* | ||
* var ac = new AccessControl(flatList); | ||
* console.log(ac.getGrants()); | ||
* | ||
* // This flat list is turned into: | ||
* { | ||
* role1: { | ||
* resource1: { | ||
* "create:any": [ attrs ], | ||
* "read:own": [ attrs ] | ||
* }, | ||
* resource2: { | ||
* "create:any": [ attrs ], | ||
* "update:own": [ attrs ] | ||
* } | ||
* }, | ||
* role2: { ... } | ||
* } | ||
*/ | ||
function AccessControl() { | ||
var grants = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; | ||
_classCallCheck(this, AccessControl); | ||
this.setGrants(grants); | ||
@@ -155,4 +176,8 @@ // initiate our inner classes | ||
* @return {Object} - Hash-map of grants. | ||
*/_createClass(AccessControl, [{ key: 'getGrants', value: function getGrants() | ||
{ | ||
*/ | ||
_createClass(AccessControl, [{ | ||
key: 'getGrants', | ||
value: function getGrants() { | ||
return this._grants; | ||
@@ -162,12 +187,17 @@ } | ||
/** | ||
* Sets all access grants at once, from an object or array. | ||
* Note that this will reset the object and remove all previous grants. | ||
* @chainable | ||
* | ||
* @param {Object|Array} grantsObject - A list containing the access grant | ||
* definitions. | ||
* | ||
* @returns {AccessControl} - `AccessControl` instance for chaining. | ||
*/ }, { key: 'setGrants', value: function setGrants( | ||
grantsObject) {var _this = this; | ||
* Sets all access grants at once, from an object or array. | ||
* Note that this will reset the object and remove all previous grants. | ||
* @chainable | ||
* | ||
* @param {Object|Array} grantsObject - A list containing the access grant | ||
* definitions. | ||
* | ||
* @returns {AccessControl} - `AccessControl` instance for chaining. | ||
*/ | ||
}, { | ||
key: 'setGrants', | ||
value: function setGrants(grantsObject) { | ||
var _this = this; | ||
this._grants = {}; | ||
@@ -178,3 +208,5 @@ var type = _helper2.default.type(grantsObject); | ||
} else if (type === 'array') { | ||
grantsObject.forEach(function (item) {return _this._grantAccess(item);}); | ||
grantsObject.forEach(function (item) { | ||
return _this._grantAccess(item); | ||
}); | ||
} | ||
@@ -185,8 +217,11 @@ return this; | ||
/** | ||
* Resets the internal grants object and removes all previous grants. | ||
* @chainable | ||
* | ||
* @returns {AccessControl} - `AccessControl` instance for chaining. | ||
*/ }, { key: 'reset', value: function reset() | ||
{ | ||
* Resets the internal grants object and removes all previous grants. | ||
* @chainable | ||
* | ||
* @returns {AccessControl} - `AccessControl` instance for chaining. | ||
*/ | ||
}, { | ||
key: 'reset', | ||
value: function reset() { | ||
this._grants = {}; | ||
@@ -197,18 +232,23 @@ return this; | ||
/** | ||
* Extends the given role(s) with privileges of one or more other roles. | ||
* @chainable | ||
* | ||
* @param {String|Array} roles | ||
* Role(s) to be extended. | ||
* Single role as a `String` or multiple roles as an `Array`. | ||
* | ||
* @param {String|Array} extenderRoles | ||
* Role(s) to inherit from. | ||
* Single role as a `String` or multiple roles as an `Array`. | ||
* | ||
* @returns {AccessControl} - `AccessControl` instance for chaining. | ||
* | ||
* @throws {Error} - If a role tries to extend itself. | ||
*/ }, { key: 'extendRole', value: function extendRole( | ||
roles, extenderRoles) {var _this2 = this; | ||
* Extends the given role(s) with privileges of one or more other roles. | ||
* @chainable | ||
* | ||
* @param {String|Array} roles | ||
* Role(s) to be extended. | ||
* Single role as a `String` or multiple roles as an `Array`. | ||
* | ||
* @param {String|Array} extenderRoles | ||
* Role(s) to inherit from. | ||
* Single role as a `String` or multiple roles as an `Array`. | ||
* | ||
* @returns {AccessControl} - `AccessControl` instance for chaining. | ||
* | ||
* @throws {Error} - If a role is extended by itself. | ||
*/ | ||
}, { | ||
key: 'extendRole', | ||
value: function extendRole(roles, extenderRoles) { | ||
var _this2 = this; | ||
extenderRoles = _helper2.default.asArray(extenderRoles); | ||
@@ -221,4 +261,4 @@ _helper2.default.asArray(roles).forEach(function (role) { | ||
_this2._grants[role] = { | ||
$extend: extenderRoles.concat() }; | ||
$extend: extenderRoles.concat() | ||
}; | ||
} else { | ||
@@ -237,11 +277,16 @@ var r = _this2._grants[role]; | ||
/** | ||
* Removes all the given role(s) and their granted permissions, at once. | ||
* @chainable | ||
* | ||
* @param {String|Array} roles - An array of roles to be removed. | ||
* Also accepts a string that can be used to remove a single role. | ||
* | ||
* @returns {AccessControl} - `AccessControl` instance for chaining. | ||
*/ }, { key: 'removeRoles', value: function removeRoles( | ||
roles) {var _this3 = this; | ||
* Removes all the given role(s) and their granted permissions, at once. | ||
* @chainable | ||
* | ||
* @param {String|Array} roles - An array of roles to be removed. | ||
* Also accepts a string that can be used to remove a single role. | ||
* | ||
* @returns {AccessControl} - `AccessControl` instance for chaining. | ||
*/ | ||
}, { | ||
key: 'removeRoles', | ||
value: function removeRoles(roles) { | ||
var _this3 = this; | ||
var rolesToRemove = _helper2.default.asArray(roles); | ||
@@ -261,16 +306,19 @@ rolesToRemove.forEach(function (role) { | ||
/** | ||
* Removes all the given resources for all roles, at once. | ||
* Pass the `roles` argument to remove access to resources for those | ||
* roles only. | ||
* @chainable | ||
* | ||
* @param {String|Array} resources - A single or array of resources to | ||
* be removed. | ||
* @param {String|Array} [roles] - A single or array of roles to | ||
* be removed. If omitted, permissions for all roles to all given | ||
* resources will be removed. | ||
* | ||
* @returns {AccessControl} - `AccessControl` instance for chaining. | ||
*/ }, { key: 'removeResources', value: function removeResources( | ||
resources, roles) { | ||
* Removes all the given resources for all roles, at once. | ||
* Pass the `roles` argument to remove access to resources for those | ||
* roles only. | ||
* @chainable | ||
* | ||
* @param {String|Array} resources - A single or array of resources to | ||
* be removed. | ||
* @param {String|Array} [roles] - A single or array of roles to | ||
* be removed. If omitted, permissions for all roles to all given | ||
* resources will be removed. | ||
* | ||
* @returns {AccessControl} - `AccessControl` instance for chaining. | ||
*/ | ||
}, { | ||
key: 'removeResources', | ||
value: function removeResources(resources, roles) { | ||
// _removePermission has a third argument `actionPossession`. if | ||
@@ -283,7 +331,10 @@ // omitted (like below), removes the parent resource object. | ||
/** | ||
* Gets all the unique roles that have at least one grant. | ||
* | ||
* @returns {Array} | ||
*/ }, { key: 'getRoles', value: function getRoles() | ||
{ | ||
* Gets all the unique roles that have at least one grant. | ||
* | ||
* @returns {Array} | ||
*/ | ||
}, { | ||
key: 'getRoles', | ||
value: function getRoles() { | ||
return Object.keys(this._grants); | ||
@@ -293,8 +344,11 @@ } | ||
/** | ||
* Gets all the unique resources that are granted access for at | ||
* least one role. | ||
* | ||
* @returns {Array} | ||
*/ }, { key: 'getResources', value: function getResources() | ||
{ | ||
* Gets all the unique resources that are granted access for at | ||
* least one role. | ||
* | ||
* @returns {Array} | ||
*/ | ||
}, { | ||
key: 'getResources', | ||
value: function getResources() { | ||
// using an object for unique count | ||
@@ -309,7 +363,10 @@ var resources = {}; | ||
/** | ||
* Checks whether any permissions are granted to the given role. | ||
* | ||
* @returns {Boolean} | ||
*/ }, { key: 'hasRole', value: function hasRole( | ||
role) { | ||
* Checks whether any permissions are granted to the given role. | ||
* | ||
* @returns {Boolean} | ||
*/ | ||
}, { | ||
key: 'hasRole', | ||
value: function hasRole(role) { | ||
return this._grants.hasOwnProperty(role); | ||
@@ -319,7 +376,10 @@ } | ||
/** | ||
* Checks whether any permissions are granted for the given resource. | ||
* | ||
* @returns {Boolean} | ||
*/ }, { key: 'hasResource', value: function hasResource( | ||
resource) { | ||
* Checks whether any permissions are granted for the given resource. | ||
* | ||
* @returns {Boolean} | ||
*/ | ||
}, { | ||
key: 'hasResource', | ||
value: function hasResource(resource) { | ||
if (typeof resource !== 'string' || resource === '') { | ||
@@ -333,36 +393,39 @@ return false; | ||
/** | ||
* Deep clones the given data object(s) while filtering its properties | ||
* by the given attribute (glob) notations. Includes all matched | ||
* properties and removes the rest. | ||
* | ||
* @param {Object|Array} data - A single or array of data objects | ||
* to be filtered. | ||
* @param {Array|String} attributes - The attribute glob notation(s) | ||
* to be processed. You can use wildcard stars (*) and negate | ||
* the notation by prepending a bang (!). A negated notation | ||
* will be excluded. Order of the globs do not matter, they will | ||
* be logically sorted. Loose globs will be processed first and | ||
* verbose globs or normal notations will be processed last. | ||
* e.g. `[ "car.model", "*", "!car.*" ]` | ||
* will be sorted as: | ||
* `[ "*", "!car.*", "car.model" ]`. | ||
* Passing no parameters or passing an empty string (`""` or `[""]`) | ||
* will empty the source object. | ||
* | ||
* @returns {Object|Array} - Returns the filtered data object or array | ||
* of data objects. | ||
* | ||
* @example | ||
* var assets = { notebook: "Mac", car: { brand: "Ford", model: "Mustang", year: 1970, color: "red" } }; | ||
* | ||
* var filtered = AccessControl.filter(assets, [ "*", "!car.*", "car.model" ]); | ||
* console.log(assets); // { notebook: "Mac", car: { model: "Mustang" } } | ||
* | ||
* filtered = AccessControl.filter(assets, "*"); // or AccessControl.filter(assets, ["*"]); | ||
* console.log(assets); // { notebook: "Mac", car: { model: "Mustang" } } | ||
* | ||
* filtered = AccessControl.filter(assets); // or AccessControl.filter(assets, ""); | ||
* console.log(assets); // {} | ||
*/ }, { key: 'filter', value: function filter( | ||
data, attributes) { | ||
* Deep clones the given data object(s) while filtering its properties | ||
* by the given attribute (glob) notations. Includes all matched | ||
* properties and removes the rest. | ||
* | ||
* @param {Object|Array} data - A single or array of data objects | ||
* to be filtered. | ||
* @param {Array|String} attributes - The attribute glob notation(s) | ||
* to be processed. You can use wildcard stars (*) and negate | ||
* the notation by prepending a bang (!). A negated notation | ||
* will be excluded. Order of the globs do not matter, they will | ||
* be logically sorted. Loose globs will be processed first and | ||
* verbose globs or normal notations will be processed last. | ||
* e.g. `[ "car.model", "*", "!car.*" ]` | ||
* will be sorted as: | ||
* `[ "*", "!car.*", "car.model" ]`. | ||
* Passing no parameters or passing an empty string (`""` or `[""]`) | ||
* will empty the source object. | ||
* | ||
* @returns {Object|Array} - Returns the filtered data object or array | ||
* of data objects. | ||
* | ||
* @example | ||
* var assets = { notebook: "Mac", car: { brand: "Ford", model: "Mustang", year: 1970, color: "red" } }; | ||
* | ||
* var filtered = AccessControl.filter(assets, [ "*", "!car.*", "car.model" ]); | ||
* console.log(assets); // { notebook: "Mac", car: { model: "Mustang" } } | ||
* | ||
* filtered = AccessControl.filter(assets, "*"); // or AccessControl.filter(assets, ["*"]); | ||
* console.log(assets); // { notebook: "Mac", car: { model: "Mustang" } } | ||
* | ||
* filtered = AccessControl.filter(assets); // or AccessControl.filter(assets, ""); | ||
* console.log(assets); // {} | ||
*/ | ||
}, { | ||
key: 'filter', | ||
value: function filter(data, attributes) { | ||
_helper2.default.filterAll(data, attributes); | ||
@@ -372,30 +435,33 @@ } | ||
/** | ||
* Gets an instance of `Access` (inner) object. This is used to check | ||
* whether the defined access is allowed for the given role(s) and resource. | ||
* This object provides chainable methods to build and define the access | ||
* to be checked. | ||
* @alias AccessControl#access | ||
* @chainable | ||
* | ||
* @param {String|Array|Object} rolesOrAccess - A single role (as a string), | ||
* a list of roles (as an array) or an object that fully or partially | ||
* defines the access to be checked. | ||
* | ||
* @returns {AccessControl~Access} - The returned object provides chainable | ||
* methods to build and define the access permissions to be checked. | ||
* | ||
* @example | ||
* var ac = new AccessControl(grants); | ||
* | ||
* ac.can('admin').createAny('profile'); | ||
* // equivalent to: | ||
* ac.can().role('admin').createAny('profile'); | ||
* // equivalent to: | ||
* ac.can().role('admin').resource('profile').createAny(); | ||
* | ||
* // To check for multiple roles: | ||
* ac.can(['admin', 'user']).createOwn('profile'); | ||
* // Note: when multiple roles checked, acquired attributes are unioned (merged). | ||
*/ }, { key: 'can', value: function can( | ||
rolesOrAccess) { | ||
* Gets an instance of `Access` (inner) object. This is used to check | ||
* whether the defined access is allowed for the given role(s) and resource. | ||
* This object provides chainable methods to build and define the access | ||
* to be checked. | ||
* @alias AccessControl#access | ||
* @chainable | ||
* | ||
* @param {String|Array|Object} rolesOrAccess - A single role (as a string), | ||
* a list of roles (as an array) or an object that fully or partially | ||
* defines the access to be checked. | ||
* | ||
* @returns {AccessControl~Access} - The returned object provides chainable | ||
* methods to build and define the access permissions to be checked. | ||
* | ||
* @example | ||
* var ac = new AccessControl(grants); | ||
* | ||
* ac.can('admin').createAny('profile'); | ||
* // equivalent to: | ||
* ac.can().role('admin').createAny('profile'); | ||
* // equivalent to: | ||
* ac.can().role('admin').resource('profile').createAny(); | ||
* | ||
* // To check for multiple roles: | ||
* ac.can(['admin', 'user']).createOwn('profile'); | ||
* // Note: when multiple roles checked, acquired attributes are unioned (merged). | ||
*/ | ||
}, { | ||
key: 'can', | ||
value: function can(rolesOrAccess) { | ||
return new this._factory.Access(rolesOrAccess); | ||
@@ -405,6 +471,9 @@ } | ||
/** | ||
* Alias of `can()`. | ||
* @private | ||
*/ }, { key: 'access', value: function access( | ||
rolesOrAccess) { | ||
* Alias of `can()`. | ||
* @private | ||
*/ | ||
}, { | ||
key: 'access', | ||
value: function access(rolesOrAccess) { | ||
return this.can(rolesOrAccess); | ||
@@ -414,42 +483,45 @@ } | ||
/** | ||
* Gets an instance of `Permission` (inner) object that checks and defines | ||
* the granted access permissions for the target resource and role. | ||
* Normally you would use `AccessControl#can()` method to check for | ||
* permissions but this is useful if you need to check at once by passing | ||
* a grant object; instead of chaining methods | ||
* (as in `.can(role).action(resource)`). | ||
* | ||
* Returned object has the following members: | ||
* | ||
* @property {Boolean} granted | ||
* Whether the specified resource permissions are granted for | ||
* the given role. | ||
* @property {Array} attributes | ||
* The defined attributes for the specified resource and | ||
* permissions. This will return an empty array if `granted` is | ||
* `false`. | ||
* @property {Function} filter | ||
* Method that filters the properties of the given data object | ||
* or array of objects, by granted permission attributes. Accepts | ||
* a single argument; an object or array of objects to be | ||
* filtered by the resulting attributes. This is equivalent to | ||
* `AccessControl#filter(object, attributes)` method only with | ||
* one difference that you don't need to pass the attributes | ||
* argument. | ||
* | ||
* @returns {AccessControl~Permission} - An object that provides properties | ||
* and methods that defines the granted access permissions. | ||
* | ||
* @example | ||
* var ac = new AccessControl(grants); | ||
* var permission = ac.permission({ | ||
* role: "user", | ||
* action: "update:own", | ||
* resource: "profile" | ||
* }); | ||
* permission.granted; // Boolean | ||
* permission.attributes; // Array e.g. [ 'username', 'password', 'company.*'] | ||
* permission.filter(object); // { username, password, company: { name, address, ... } } | ||
*/ }, { key: 'permission', value: function permission( | ||
rolesOrPerm) { | ||
* Gets an instance of `Permission` (inner) object that checks and defines | ||
* the granted access permissions for the target resource and role. | ||
* Normally you would use `AccessControl#can()` method to check for | ||
* permissions but this is useful if you need to check at once by passing | ||
* a grant object; instead of chaining methods | ||
* (as in `.can(role).action(resource)`). | ||
* | ||
* Returned object has the following members: | ||
* | ||
* @property {Boolean} granted | ||
* Whether the specified resource permissions are granted for | ||
* the given role. | ||
* @property {Array} attributes | ||
* The defined attributes for the specified resource and | ||
* permissions. This will return an empty array if `granted` is | ||
* `false`. | ||
* @property {Function} filter | ||
* Method that filters the properties of the given data object | ||
* or array of objects, by granted permission attributes. Accepts | ||
* a single argument; an object or array of objects to be | ||
* filtered by the resulting attributes. This is equivalent to | ||
* `AccessControl#filter(object, attributes)` method only with | ||
* one difference that you don't need to pass the attributes | ||
* argument. | ||
* | ||
* @returns {AccessControl~Permission} - An object that provides properties | ||
* and methods that defines the granted access permissions. | ||
* | ||
* @example | ||
* var ac = new AccessControl(grants); | ||
* var permission = ac.permission({ | ||
* role: "user", | ||
* action: "update:own", | ||
* resource: "profile" | ||
* }); | ||
* permission.granted; // Boolean | ||
* permission.attributes; // Array e.g. [ 'username', 'password', 'company.*'] | ||
* permission.filter(object); // { username, password, company: { name, address, ... } } | ||
*/ | ||
}, { | ||
key: 'permission', | ||
value: function permission(rolesOrPerm) { | ||
return new this._factory.Permission(rolesOrPerm); | ||
@@ -459,52 +531,55 @@ } | ||
/** | ||
* Gets an instance of `Grant` (inner) object. This is used to grant access | ||
* to specified resource(s) for the given role(s). | ||
* @alias AccessControl#allow | ||
* @chainable | ||
* | ||
* @param {String|Array|Object} rolesOrGrant - A single role (as a string), | ||
* a list of roles (as an array) or an object that fully or partially | ||
* defines the access to be granted. | ||
* | ||
* @return {AccessControl~Access} - The returned object provides chainable | ||
* properties to build and define the access to be granted. See the | ||
* examples for details. | ||
* | ||
* @example | ||
* var ac = new AccessControl(), | ||
* attributes = ['*']; | ||
* | ||
* ac.grant('admin').createAny('profile', attributes); | ||
* // equivalent to: | ||
* ac.grant().role('admin').createAny('profile', attributes); | ||
* // equivalent to: | ||
* ac.grant().role('admin').resource('profile').createAny(null, attributes); | ||
* // equivalent to: | ||
* ac.grant({ | ||
* role: 'admin', | ||
* resource: 'profile', | ||
* }).createAny(null, attributes); | ||
* // equivalent to: | ||
* ac.grant({ | ||
* role: 'admin', | ||
* resource: 'profile', | ||
* action: 'create:any', | ||
* attributes: attributes | ||
* }); | ||
* // equivalent to: | ||
* ac.grant({ | ||
* role: 'admin', | ||
* resource: 'profile', | ||
* action: 'create', | ||
* possession: 'any', // omitting this will default to 'any' | ||
* attributes: attributes | ||
* }); | ||
* | ||
* // To grant same resource and attributes for multiple roles: | ||
* ac.grant(['admin', 'user']).createOwn('profile', attributes); | ||
* | ||
* // Note: when attributes is omitted, it will default to `['*']` | ||
* // which means all attributes (of the resource) are allowed. | ||
*/ }, { key: 'grant', value: function grant( | ||
rolesOrGrant) { | ||
* Gets an instance of `Grant` (inner) object. This is used to grant access | ||
* to specified resource(s) for the given role(s). | ||
* @alias AccessControl#allow | ||
* @chainable | ||
* | ||
* @param {String|Array|Object} rolesOrGrant - A single role (as a string), | ||
* a list of roles (as an array) or an object that fully or partially | ||
* defines the access to be granted. | ||
* | ||
* @return {AccessControl~Access} - The returned object provides chainable | ||
* properties to build and define the access to be granted. See the | ||
* examples for details. | ||
* | ||
* @example | ||
* var ac = new AccessControl(), | ||
* attributes = ['*']; | ||
* | ||
* ac.grant('admin').createAny('profile', attributes); | ||
* // equivalent to: | ||
* ac.grant().role('admin').createAny('profile', attributes); | ||
* // equivalent to: | ||
* ac.grant().role('admin').resource('profile').createAny(null, attributes); | ||
* // equivalent to: | ||
* ac.grant({ | ||
* role: 'admin', | ||
* resource: 'profile', | ||
* }).createAny(null, attributes); | ||
* // equivalent to: | ||
* ac.grant({ | ||
* role: 'admin', | ||
* resource: 'profile', | ||
* action: 'create:any', | ||
* attributes: attributes | ||
* }); | ||
* // equivalent to: | ||
* ac.grant({ | ||
* role: 'admin', | ||
* resource: 'profile', | ||
* action: 'create', | ||
* possession: 'any', // omitting this will default to 'any' | ||
* attributes: attributes | ||
* }); | ||
* | ||
* // To grant same resource and attributes for multiple roles: | ||
* ac.grant(['admin', 'user']).createOwn('profile', attributes); | ||
* | ||
* // Note: when attributes is omitted, it will default to `['*']` | ||
* // which means all attributes (of the resource) are allowed. | ||
*/ | ||
}, { | ||
key: 'grant', | ||
value: function grant(rolesOrGrant) { | ||
return new this._factory.Grant(rolesOrGrant); | ||
@@ -514,6 +589,9 @@ } | ||
/** | ||
* Alias of `grant()`. | ||
* @private | ||
*/ }, { key: 'allow', value: function allow( | ||
rolesOrGrant) { | ||
* Alias of `grant()`. | ||
* @private | ||
*/ | ||
}, { | ||
key: 'allow', | ||
value: function allow(rolesOrGrant) { | ||
return this.grant(rolesOrGrant); | ||
@@ -523,47 +601,50 @@ } | ||
/** | ||
* Gets an instance of `Deny` (inner) object. This is used to deny access | ||
* to specified resource(s) for the given role(s). Denying will only remove | ||
* a previously created grant. So if not granted before, you don't need | ||
* to deny an access. | ||
* @alias AccessControl#reject | ||
* @chainable | ||
* | ||
* @param {String|Array|Object} rolesOrGrant - A single role (as a string), | ||
* a list of roles (as an array) or an object that fully or partially | ||
* defines the access to be granted. | ||
* | ||
* @return {AccessControl~Access} - The returned object provides chainable | ||
* properties to build and define the access to be granted. | ||
* | ||
* @example | ||
* var ac = new AccessControl(); | ||
* | ||
* ac.deny('admin').createAny('profile'); | ||
* // equivalent to: | ||
* ac.deny().role('admin').createAny('profile'); | ||
* // equivalent to: | ||
* ac.deny().role('admin').resource('profile').createAny(); | ||
* // equivalent to: | ||
* ac.deny({ | ||
* role: 'admin', | ||
* resource: 'profile', | ||
* }).createAny(); | ||
* // equivalent to: | ||
* ac.deny({ | ||
* role: 'admin', | ||
* resource: 'profile', | ||
* action: 'create:any' | ||
* }); | ||
* // equivalent to: | ||
* ac.deny({ | ||
* role: 'admin', | ||
* resource: 'profile', | ||
* action: 'create', | ||
* possession: 'any' // omitting this will default to 'any' | ||
* }); | ||
* | ||
* // To deny same resource for multiple roles: | ||
* ac.deny(['admin', 'user']).createOwn('profile'); | ||
*/ }, { key: 'deny', value: function deny( | ||
rolesOrDeny) { | ||
* Gets an instance of `Deny` (inner) object. This is used to deny access | ||
* to specified resource(s) for the given role(s). Denying will only remove | ||
* a previously created grant. So if not granted before, you don't need | ||
* to deny an access. | ||
* @alias AccessControl#reject | ||
* @chainable | ||
* | ||
* @param {String|Array|Object} rolesOrGrant - A single role (as a string), | ||
* a list of roles (as an array) or an object that fully or partially | ||
* defines the access to be granted. | ||
* | ||
* @return {AccessControl~Access} - The returned object provides chainable | ||
* properties to build and define the access to be granted. | ||
* | ||
* @example | ||
* var ac = new AccessControl(); | ||
* | ||
* ac.deny('admin').createAny('profile'); | ||
* // equivalent to: | ||
* ac.deny().role('admin').createAny('profile'); | ||
* // equivalent to: | ||
* ac.deny().role('admin').resource('profile').createAny(); | ||
* // equivalent to: | ||
* ac.deny({ | ||
* role: 'admin', | ||
* resource: 'profile', | ||
* }).createAny(); | ||
* // equivalent to: | ||
* ac.deny({ | ||
* role: 'admin', | ||
* resource: 'profile', | ||
* action: 'create:any' | ||
* }); | ||
* // equivalent to: | ||
* ac.deny({ | ||
* role: 'admin', | ||
* resource: 'profile', | ||
* action: 'create', | ||
* possession: 'any' // omitting this will default to 'any' | ||
* }); | ||
* | ||
* // To deny same resource for multiple roles: | ||
* ac.deny(['admin', 'user']).createOwn('profile'); | ||
*/ | ||
}, { | ||
key: 'deny', | ||
value: function deny(rolesOrDeny) { | ||
return new this._factory.Deny(rolesOrDeny); | ||
@@ -573,6 +654,9 @@ } | ||
/** | ||
* Alias of `deny()`. | ||
* @private | ||
*/ }, { key: 'reject', value: function reject( | ||
rolesOrDeny) { | ||
* Alias of `deny()`. | ||
* @private | ||
*/ | ||
}, { | ||
key: 'reject', | ||
value: function reject(rolesOrDeny) { | ||
return this.deny(rolesOrDeny); | ||
@@ -587,19 +671,37 @@ } | ||
* @private | ||
*/ }, { key: '_each', value: function _each( | ||
callback) {var _this4 = this; | ||
_helper2.default.eachKey(this._grants, function (role) {return callback(role, _this4._grants[role]);}); | ||
*/ | ||
}, { | ||
key: '_each', | ||
value: function _each(callback) { | ||
var _this4 = this; | ||
_helper2.default.eachKey(this._grants, function (role) { | ||
return callback(role, _this4._grants[role]); | ||
}); | ||
} | ||
/** | ||
* @private | ||
*/ }, { key: '_eachRole', value: function _eachRole( | ||
callback) { | ||
_helper2.default.eachKey(this._grants, function (role) {return callback(role);}); | ||
* @private | ||
*/ | ||
}, { | ||
key: '_eachRole', | ||
value: function _eachRole(callback) { | ||
_helper2.default.eachKey(this._grants, function (role) { | ||
return callback(role); | ||
}); | ||
} | ||
/** | ||
* @private | ||
*/ }, { key: '_eachRoleResource', value: function _eachRoleResource( | ||
callback) {var _this5 = this; | ||
var resources = void 0,permissions = void 0; | ||
* @private | ||
*/ | ||
}, { | ||
key: '_eachRoleResource', | ||
value: function _eachRoleResource(callback) { | ||
var _this5 = this; | ||
var resources = void 0, | ||
permissions = void 0; | ||
this._eachRole(function (role) { | ||
@@ -616,6 +718,14 @@ resources = _this5._grants[role]; | ||
// means "all attributes allowed". | ||
}, { key: '_grantAccess', value: function _grantAccess(grant) {var _this6 = this; | ||
}, { | ||
key: '_grantAccess', | ||
value: function _grantAccess(grant) { | ||
var _this6 = this; | ||
grant = _helper2.default.normalizeAccessObject(grant); | ||
// console.log(grant); | ||
var grantItem = void 0,resource = void 0,re = void 0,ap = void 0; | ||
var grantItem = void 0, | ||
resource = void 0, | ||
re = void 0, | ||
ap = void 0; | ||
// grant.role also accepts an array, so treat it like it. | ||
@@ -641,5 +751,10 @@ grant.role.forEach(function (role) { | ||
/** | ||
* @private | ||
*/ }, { key: '_removePermission', value: function _removePermission( | ||
resources, roles, actionPossession) {var _this7 = this; | ||
* @private | ||
*/ | ||
}, { | ||
key: '_removePermission', | ||
value: function _removePermission(resources, roles, actionPossession) { | ||
var _this7 = this; | ||
resources = _helper2.default.asArray(resources); | ||
@@ -663,12 +778,18 @@ if (roles) roles = _helper2.default.asArray(roles); | ||
/** | ||
* Removes the permission ("action:possession" property which represents | ||
* the permission) from the corresponding resource object (in grants). | ||
* @private | ||
*/ }, { key: '_denyAccess', value: function _denyAccess( | ||
deny) { | ||
* Removes the permission ("action:possession" property which represents | ||
* the permission) from the corresponding resource object (in grants). | ||
* @private | ||
*/ | ||
}, { | ||
key: '_denyAccess', | ||
value: function _denyAccess(deny) { | ||
deny = _helper2.default.normalizeAccessObject(deny); | ||
var ap = deny.action + ':' + deny.possession; | ||
this._removePermission(deny.resource, deny.role, ap); | ||
} }]);return AccessControl;}(); | ||
} | ||
}]); | ||
return AccessControl; | ||
}(); | ||
@@ -678,3 +799,3 @@ // ------------------------------- | ||
// ------------------------------- | ||
exports.default = | ||
AccessControl; | ||
exports.default = AccessControl; |
@@ -1,69 +0,78 @@ | ||
'use strict';Object.defineProperty(exports, "__esModule", { value: true }); | ||
'use strict'; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
/** | ||
* Enumerates the possible actions of a role. | ||
* An action defines the type of an operation that will be | ||
* executed on a "resource" by a "role". | ||
* This is known as CRUD (CREATE, READ, UPDATE, DELETE). | ||
* @enum {String} | ||
* @memberof! AccessControl | ||
*/ | ||
* Enumerates the possible actions of a role. | ||
* An action defines the type of an operation that will be | ||
* executed on a "resource" by a "role". | ||
* This is known as CRUD (CREATE, READ, UPDATE, DELETE). | ||
* @enum {String} | ||
* @memberof! AccessControl | ||
*/ | ||
var Action = { | ||
/** | ||
* Specifies a CREATE action to be performed on a resource. | ||
* For example, an HTTP POST request or an INSERT database operation. | ||
* @type {String} | ||
*/ | ||
* Specifies a CREATE action to be performed on a resource. | ||
* For example, an HTTP POST request or an INSERT database operation. | ||
* @type {String} | ||
*/ | ||
CREATE: 'create', | ||
/** | ||
* Specifies a READ action to be performed on a resource. | ||
* For example, an HTTP GET request or an database SELECT operation. | ||
* @type {String} | ||
*/ | ||
* Specifies a READ action to be performed on a resource. | ||
* For example, an HTTP GET request or an database SELECT operation. | ||
* @type {String} | ||
*/ | ||
READ: 'read', | ||
/** | ||
* Specifies an UPDATE action to be performed on a resource. | ||
* For example, an HTTP PUT or POST request or an database UPDATE operation. | ||
* @type {String} | ||
*/ | ||
* Specifies an UPDATE action to be performed on a resource. | ||
* For example, an HTTP PUT or POST request or an database UPDATE operation. | ||
* @type {String} | ||
*/ | ||
UPDATE: 'update', | ||
/** | ||
* Specifies a DELETE action to be performed on a resource. | ||
* For example, an HTTP DELETE request or a database DELETE operation. | ||
* @type {String} | ||
*/ | ||
DELETE: 'delete' }; | ||
* Specifies a DELETE action to be performed on a resource. | ||
* For example, an HTTP DELETE request or a database DELETE operation. | ||
* @type {String} | ||
*/ | ||
DELETE: 'delete' | ||
}; | ||
/** | ||
* @private | ||
*/ | ||
var actions = Object.keys(Action).map(function (item) {return item.toLowerCase();}); | ||
* @private | ||
*/ | ||
var actions = Object.keys(Action).map(function (item) { | ||
return item.toLowerCase(); | ||
}); | ||
/** | ||
* Enumerates the possible possessions of a resource, for an action. | ||
* A possession defines whether the access is granted/denied for ANY or OWN resource(s). | ||
* @enum {String} | ||
* @memberof! AccessControl | ||
*/ | ||
* Enumerates the possible possessions of a resource, for an action. | ||
* A possession defines whether the access is granted/denied for ANY or OWN resource(s). | ||
* @enum {String} | ||
* @memberof! AccessControl | ||
*/ | ||
var Possession = { | ||
/** | ||
* Indicates that the action is (or not) to be performed on **own** | ||
* resource(s) of the current subject. | ||
* @type {String} | ||
*/ | ||
* Indicates that the action is (or not) to be performed on <b>own</b> | ||
* resource(s) of the current subject. | ||
* @type {String} | ||
*/ | ||
OWN: 'own', | ||
/** | ||
* Indicates that the action is (or not) to be performed on **any** | ||
* resource(s); including *own* resource(s) of the current subject. | ||
* @type {String} | ||
*/ | ||
ANY: 'any' }; | ||
* Indicates that the action is (or not) to be performed on <b>any</b> | ||
* resource(s); including <i>own</i> resource(s) of the current subject. | ||
* @type {String} | ||
*/ | ||
ANY: 'any' | ||
}; | ||
/** | ||
* @private | ||
*/ | ||
var possessions = Object.keys(Possession).map(function (item) {return item.toLowerCase();});exports.default = | ||
* @private | ||
*/ | ||
var possessions = Object.keys(Possession).map(function (item) { | ||
return item.toLowerCase(); | ||
}); | ||
Object.freeze({ | ||
exports.default = Object.freeze({ | ||
Action: Action, | ||
@@ -73,2 +82,3 @@ Possession: Possession, | ||
actions: actions, | ||
possessions: possessions }); | ||
possessions: possessions | ||
}); |
@@ -1,9 +0,30 @@ | ||
'use strict';Object.defineProperty(exports, "__esModule", { value: true });var _createClass = function () {function defineProperties(target, props) {for (var i = 0; i < props.length; i++) {var descriptor = props[i];descriptor.enumerable = descriptor.enumerable || false;descriptor.configurable = true;if ("value" in descriptor) descriptor.writable = true;Object.defineProperty(target, descriptor.key, descriptor);}}return function (Constructor, protoProps, staticProps) {if (protoProps) defineProperties(Constructor.prototype, protoProps);if (staticProps) defineProperties(Constructor, staticProps);return Constructor;};}(); // dep modules | ||
'use strict'; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); // dep modules | ||
// own modules | ||
var _notation = require('notation');var _notation2 = _interopRequireDefault(_notation);var _enums = require('./enums');var _enums2 = _interopRequireDefault(_enums); | ||
var _helper = require('./lib/helper');var _helper2 = _interopRequireDefault(_helper);function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };}function _classCallCheck(instance, Constructor) {if (!(instance instanceof Constructor)) {throw new TypeError("Cannot call a class as a function");}}exports.default = | ||
function (ac) { | ||
var _notation = require('notation'); | ||
var _notation2 = _interopRequireDefault(_notation); | ||
var _enums = require('./enums'); | ||
var _enums2 = _interopRequireDefault(_enums); | ||
var _helper = require('./lib/helper'); | ||
var _helper2 = _interopRequireDefault(_helper); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
exports.default = function (ac) { | ||
// ------------------------------- | ||
@@ -29,18 +50,12 @@ // CLASS: Permission | ||
var Permission = function () { | ||
function Permission(perm) { | ||
_classCallCheck(this, Permission); | ||
function Permission(perm) {_classCallCheck(this, Permission); | ||
this._attributes = this._getUnionAttrsOfRoles(perm); | ||
}_createClass(Permission, [{ key: 'filter', | ||
} | ||
_createClass(Permission, [{ | ||
key: 'filter', | ||
// equivalent to AccessControl.filter(data, attributes); | ||
@@ -52,6 +67,9 @@ value: function filter(data) { | ||
/** | ||
* Gets roles and extended roles in a flat array. | ||
* @private | ||
*/ }, { key: '_getFlatRoles', value: function _getFlatRoles( | ||
roles) { | ||
* Gets roles and extended roles in a flat array. | ||
* @private | ||
*/ | ||
}, { | ||
key: '_getFlatRoles', | ||
value: function _getFlatRoles(roles) { | ||
roles = _helper2.default.asArray(roles); | ||
@@ -69,9 +87,12 @@ var arr = roles.concat(); | ||
/** | ||
* When more than one role is passed, we union the permitted attributes | ||
* for all given roles; so we can check whether "at least one of these | ||
* roles" have the permission to execute this action. | ||
* e.g. `can(['admin', 'user']).createAny('video')` | ||
* @private | ||
*/ }, { key: '_getUnionAttrsOfRoles', value: function _getUnionAttrsOfRoles( | ||
access) { | ||
* When more than one role is passed, we union the permitted attributes | ||
* for all given roles; so we can check whether "at least one of these | ||
* roles" have the permission to execute this action. | ||
* e.g. `can(['admin', 'user']).createAny('video')` | ||
* @private | ||
*/ | ||
}, { | ||
key: '_getUnionAttrsOfRoles', | ||
value: function _getUnionAttrsOfRoles(access) { | ||
if (!ac._grants) { | ||
@@ -83,4 +104,6 @@ throw new Error('AccessControl: Grants are not set.'); | ||
var grantItem = void 0,_resource = void 0, | ||
attrsList = [], | ||
var grantItem = void 0, | ||
_resource = void 0, | ||
attrsList = [], | ||
// get roles and extended roles in a flat array | ||
@@ -98,7 +121,3 @@ roles = this._getFlatRoles(access.role); | ||
// `granted=true` for "own", if "own" is not defined. | ||
attrsList.push( | ||
_resource[access.action + ':' + access.possession] || | ||
_resource[access.action + ':any'] || | ||
[]); | ||
attrsList.push(_resource[access.action + ':' + access.possession] || _resource[access.action + ':any'] || []); | ||
// console.log(_resource, 'for:', action + '.' + possession); | ||
@@ -112,3 +131,3 @@ } | ||
var attrs = [], | ||
len = attrsList.length; | ||
len = attrsList.length; | ||
if (len > 0) { | ||
@@ -123,5 +142,21 @@ attrs = attrsList[0]; | ||
return attrs; | ||
} }, { key: 'attributes', get: function get() {return this._attributes;} }, { key: 'granted', get: function get() {// check for a non-negated attribute | ||
return this.attributes.some(function (attr) {return attr.slice(0, 1) !== '!';});} }]);return Permission;}(); | ||
} | ||
}, { | ||
key: 'attributes', | ||
get: function get() { | ||
return this._attributes; | ||
} | ||
}, { | ||
key: 'granted', | ||
get: function get() { | ||
// check for a non-negated attribute | ||
return this.attributes.some(function (attr) { | ||
return attr.slice(0, 1) !== '!'; | ||
}); | ||
} | ||
}]); | ||
return Permission; | ||
}(); | ||
// ------------------------------- | ||
@@ -132,5 +167,8 @@ // CLASS: Access | ||
// See AccessControl#can | ||
var Access = function () { | ||
function Access(rolesOrAccess) { | ||
_classCallCheck(this, Access); | ||
function Access(rolesOrAccess) {_classCallCheck(this, Access); | ||
// if this is a (permission) object, we directly build attributes from | ||
@@ -144,17 +182,23 @@ // grants. | ||
this._access = { | ||
role: rolesOrAccess }; | ||
role: rolesOrAccess | ||
}; | ||
} | ||
}_createClass(Access, [{ key: 'role', value: function role( | ||
} | ||
roles) { | ||
_createClass(Access, [{ | ||
key: 'role', | ||
value: function role(roles) { | ||
this._access.role = roles; | ||
return this; | ||
} }, { key: 'resource', value: function resource( | ||
_resource2) { | ||
} | ||
}, { | ||
key: 'resource', | ||
value: function resource(_resource2) { | ||
this._access.resource = _resource2; | ||
return this; | ||
} }]);return Access;}(); | ||
} | ||
}]); | ||
return Access; | ||
}(); | ||
@@ -166,2 +210,4 @@ // ------------------------------- | ||
// See AccessControl#grant | ||
var Grant = function () { | ||
@@ -173,3 +219,5 @@ | ||
// default to "any". | ||
function Grant(rolesOrGrant) {_classCallCheck(this, Grant); | ||
function Grant(rolesOrGrant) { | ||
_classCallCheck(this, Grant); | ||
// if this is a (access grant) object, we directly add it to grants | ||
@@ -188,23 +236,28 @@ if (_helper2.default.type(rolesOrGrant) === 'object') { | ||
this._grant = { | ||
role: rolesOrGrant }; | ||
role: rolesOrGrant | ||
}; | ||
} | ||
}_createClass(Grant, [{ key: 'role', value: function role( | ||
} | ||
roles) { | ||
_createClass(Grant, [{ | ||
key: 'role', | ||
value: function role(roles) { | ||
this._grant.role = roles; | ||
return this; | ||
} }, { key: 'resource', value: function resource( | ||
_resource3) { | ||
} | ||
}, { | ||
key: 'resource', | ||
value: function resource(_resource3) { | ||
this._grant.resource = _resource3; | ||
return this; | ||
} }, { key: 'attributes', value: function attributes( | ||
_attributes) { | ||
} | ||
}, { | ||
key: 'attributes', | ||
value: function attributes(_attributes) { | ||
this._grant.attributes = _attributes; | ||
return this; | ||
} }, { key: 'extend', value: function extend( | ||
roles) { | ||
} | ||
}, { | ||
key: 'extend', | ||
value: function extend(roles) { | ||
ac.extendRole(this._grant.role, roles); | ||
@@ -215,9 +268,12 @@ return this; | ||
/** | ||
* Shorthand to switch to a new `Grant` instance with a different role | ||
* within the method chain. | ||
* @example | ||
* ac.grant('user').createOwn('video') | ||
* .grant('admin').updateAny('video'); | ||
*/ }, { key: 'grant', value: function grant( | ||
rolesOrGrant) { | ||
* Shorthand to switch to a new `Grant` instance with a different role | ||
* within the method chain. | ||
* @example | ||
* ac.grant('user').createOwn('video') | ||
* .grant('admin').updateAny('video'); | ||
*/ | ||
}, { | ||
key: 'grant', | ||
value: function grant(rolesOrGrant) { | ||
if (!rolesOrGrant) rolesOrGrant = this._grant.role; | ||
@@ -228,13 +284,19 @@ return new Grant(rolesOrGrant); | ||
/** | ||
* Shorthand to switch to a new `Deny` instance with a different | ||
* (or same) role within the method chain. | ||
* @example | ||
* ac.grant('user').createOwn('video') | ||
* .grant('admin').updateAny('video'); | ||
*/ }, { key: 'deny', value: function deny( | ||
rolesOrDeny) { | ||
* Shorthand to switch to a new `Deny` instance with a different | ||
* (or same) role within the method chain. | ||
* @example | ||
* ac.grant('user').createOwn('video') | ||
* .grant('admin').updateAny('video'); | ||
*/ | ||
}, { | ||
key: 'deny', | ||
value: function deny(rolesOrDeny) { | ||
if (!rolesOrDeny) rolesOrDeny = this._grant.role; | ||
return new Deny(rolesOrDeny); // eslint-disable-line | ||
} }]);return Grant;}(); | ||
} | ||
}]); | ||
return Grant; | ||
}(); | ||
@@ -246,6 +308,10 @@ // ------------------------------- | ||
// See AccessControl#deny | ||
var Deny = function () { | ||
// See AccessControl.Deny | ||
function Deny(rolesOrDeny) {_classCallCheck(this, Deny); | ||
function Deny(rolesOrDeny) { | ||
_classCallCheck(this, Deny); | ||
// if this is a (access grant) object, we directly add it to grants | ||
@@ -261,12 +327,16 @@ if (_helper2.default.type(rolesOrDeny) === 'object') { | ||
this._deny = { | ||
role: rolesOrDeny }; | ||
role: rolesOrDeny | ||
}; | ||
} | ||
} | ||
} | ||
}_createClass(Deny, [{ key: 'role', value: function role( | ||
roles) { | ||
_createClass(Deny, [{ | ||
key: 'role', | ||
value: function role(roles) { | ||
this._deny.role = roles; | ||
return this; | ||
} }, { key: 'resource', value: function resource( | ||
_resource4) { | ||
} | ||
}, { | ||
key: 'resource', | ||
value: function resource(_resource4) { | ||
this._deny.resource = _resource4; | ||
@@ -277,9 +347,12 @@ return this; | ||
/** | ||
* Shorthand to switch to a new `Deny` instance with a different role | ||
* within the method chain. | ||
* @example | ||
* ac.grant('user').createOwn('video') | ||
* .grant('admin').updateAny('video'); | ||
*/ }, { key: 'deny', value: function deny( | ||
rolesOrDeny) { | ||
* Shorthand to switch to a new `Deny` instance with a different role | ||
* within the method chain. | ||
* @example | ||
* ac.grant('user').createOwn('video') | ||
* .grant('admin').updateAny('video'); | ||
*/ | ||
}, { | ||
key: 'deny', | ||
value: function deny(rolesOrDeny) { | ||
if (!rolesOrDeny) rolesOrDeny = this._deny.role; | ||
@@ -290,13 +363,19 @@ return new Deny(rolesOrDeny); | ||
/** | ||
* Shorthand to switch to a new `Grant` instance with a different | ||
* (or same) role within the method chain. | ||
* @example | ||
* ac.grant('user').createOwn('video') | ||
* .grant('admin').updateAny('video'); | ||
*/ }, { key: 'grant', value: function grant( | ||
rolesOrGrant) { | ||
* Shorthand to switch to a new `Grant` instance with a different | ||
* (or same) role within the method chain. | ||
* @example | ||
* ac.grant('user').createOwn('video') | ||
* .grant('admin').updateAny('video'); | ||
*/ | ||
}, { | ||
key: 'grant', | ||
value: function grant(rolesOrGrant) { | ||
if (!rolesOrGrant) rolesOrGrant = this._deny.role; | ||
return new Grant(rolesOrGrant); | ||
} }]);return Deny;}(); | ||
} | ||
}]); | ||
return Deny; | ||
}(); | ||
@@ -317,4 +396,6 @@ // ------------------------------- | ||
var method = void 0; | ||
_enums2.default.actions.forEach(function (action) {// create|read|update|delete | ||
_enums2.default.possessions.forEach(function (possession) {// any|own | ||
_enums2.default.actions.forEach(function (action) { | ||
// create|read|update|delete | ||
_enums2.default.possessions.forEach(function (possession) { | ||
// any|own | ||
method = _helper2.default.getMethodName(action, possession); | ||
@@ -391,5 +472,4 @@ // Access.prototype.<action+Possession> | ||
Grant: Grant, | ||
Deny: Deny }; | ||
Deny: Deny | ||
}; | ||
}; |
@@ -1,16 +0,25 @@ | ||
'use strict';Object.defineProperty(exports, "__esModule", { value: true }); | ||
var _notation = require('notation');var _notation2 = _interopRequireDefault(_notation); | ||
'use strict'; | ||
var _enums = require('../enums');var _enums2 = _interopRequireDefault(_enums);function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };} // dep modules | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
var _notation = require('notation'); | ||
var _notation2 = _interopRequireDefault(_notation); | ||
var _enums = require('../enums'); | ||
var _enums2 = _interopRequireDefault(_enums); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
// dep modules | ||
var helper = { | ||
type: function type(o) { | ||
return Object.prototype.toString.call(o).match(/\s(\w+)/i)[1].toLowerCase(); | ||
}, | ||
hasDefined: function hasDefined(o, propName) { | ||
return o.hasOwnProperty(propName) && o[propName] !== undefined; | ||
}, | ||
asArray: function asArray(value, delim) { | ||
@@ -24,3 +33,2 @@ if (!value) return; | ||
}, | ||
uniqConcat: function uniqConcat(arrA, arrB) { | ||
@@ -32,7 +40,7 @@ arrB.forEach(function (b) { | ||
}, | ||
subtractArray: function subtractArray(arrA, arrB) { | ||
return arrA.filter(function (a) {return arrB.indexOf(a) === -1;}); | ||
return arrA.filter(function (a) { | ||
return arrB.indexOf(a) === -1; | ||
}); | ||
}, | ||
eachKey: function eachKey(o, callback) { | ||
@@ -42,13 +50,12 @@ return Object.keys(o).forEach(callback); | ||
// "create" + "own" = "createOwn" | ||
getMethodName: function getMethodName(action, possession) { | ||
return action.toLowerCase() + | ||
possession.charAt(0).toUpperCase() + | ||
possession.slice(1).toLowerCase(); | ||
return action.toLowerCase() + possession.charAt(0).toUpperCase() + possession.slice(1).toLowerCase(); | ||
}, | ||
// Converts the given role(s) to an array, checks the role(s) and resource. | ||
normalizeRoleAndResource: function normalizeRoleAndResource(o) { | ||
var valid = (typeof o.role === 'string' || Array.isArray(o.role)) && | ||
o.role.length > 0; | ||
var valid = (typeof o.role === 'string' || Array.isArray(o.role)) && o.role.length > 0; | ||
if (!valid) { | ||
@@ -68,2 +75,3 @@ throw new Error('AccessControl: Invalid role(s): ' + o.role); | ||
// Normalizes base properties of an access object such as role, resource, | ||
@@ -84,4 +92,4 @@ // action and possession. This method also validates these properties and | ||
var ap = String(o.action || '').split(':'), | ||
a = ap[0].toLowerCase(), | ||
p = (o.possession || ap[1] || 'any').toLowerCase(); | ||
a = ap[0].toLowerCase(), | ||
p = (o.possession || ap[1] || 'any').toLowerCase(); | ||
if (_enums2.default.actions.indexOf(a) < 0) { | ||
@@ -97,3 +105,2 @@ throw new Error('AccessControl: Invalid action: ' + o.action); | ||
}, | ||
filter: function filter(object, attributes) { | ||
@@ -104,5 +111,4 @@ if (!Array.isArray(attributes) || attributes.length === 0) { | ||
var notation = new _notation2.default(object); | ||
return notation.filter(attributes).value(); | ||
return notation.filter(attributes).value; | ||
}, | ||
filterAll: function filterAll(arrOrObj, attributes) { | ||
@@ -115,6 +121,5 @@ if (!Array.isArray(arrOrObj)) { | ||
}); | ||
} }; // own modules | ||
exports.default = | ||
helper; | ||
} | ||
}; | ||
// own modules | ||
exports.default = helper; |
{ | ||
"name": "accesscontrol", | ||
"version": "1.0.0", | ||
"version": "1.0.1", | ||
"description": "Role and Attribute based Access Control for Node.js", | ||
@@ -9,2 +9,7 @@ "main": "index.js", | ||
}, | ||
"files": [ | ||
"index.js", | ||
"build", | ||
"LICENSE" | ||
], | ||
"scripts": { | ||
@@ -11,0 +16,0 @@ "test": "echo \"Error: no test specified\" && exit 1" |
# AccessControl | ||
[![version](http://img.shields.io/npm/v/accesscontrol.svg)](https://www.npmjs.com/package/accesscontrol) | ||
![dependencies](https://david-dm.org/onury/accesscontrol.svg) | ||
![license](http://img.shields.io/npm/l/accesscontrol.svg) | ||
@@ -159,3 +162,3 @@ > © 2016, Onur Yıldırım (@onury). MIT License. | ||
``` | ||
See [express.js example](express-js-example). | ||
See [express.js example](#expressjs-example). | ||
@@ -212,4 +215,12 @@ #### Defining All Grants at Once | ||
## Documentation | ||
You can read the full [**API reference** here][docs]. | ||
## Change-Log | ||
**v1.0.1** (2016-11-09) | ||
- Bug-Fix: Permission filter would throw an error due to syntax. Fixes [issue #1](https://github.com/onury/accesscontrol/issues/1). | ||
- (Dev) added filter test. | ||
**v1.0.0** (2016-09-10) | ||
@@ -222,3 +233,3 @@ - initial release. | ||
[docs]:http://onury.github.io/accesscontrol/?api=ac | ||
[rbac]:https://en.wikipedia.org/wiki/Role-based_access_control | ||
@@ -225,0 +236,0 @@ [abac]:https://en.wikipedia.org/wiki/Attribute-Based_Access_Control |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
236
61328
8
1275
1