dynamic-acl
v2.0.6
Published
Dynamic Access Control List for Node.js to fully control your Roles, Resources, Privileges and Conditions using Promises
Downloads
7
Readme
node-dynamic-acl
Dynamic Access Control List for Node.js to fully control your Roles, Resources, Privileges and Conditions
#Install
$ npm install dynamic-acl
#Quick Start
var Acl = require('../dist').Acl;
var Role = require('../dist').Role;
var Resource = require('../dist').Resource;
var anonymous = {
roleId: 'visitor'
};
var bob = {
firstname: 'Bob',
lastname: 'Marley',
roleId: 'user'
};
var me = {
firtname: 'Timmmmy',
lastname: 'Timmmmy',
roleId: 'admin'
};
var page1 = {
id: 'page 1',
title: 'Go further with node',
resourceId: 'page'
};
var book = {
id: 'book 1',
title: 'Go further with JS',
resourceId: 'book'
};
var getUserRoleId = (user) => new Promise(resolve => resolve(user.roleId));
var getResourceId = (resource) => new Promise(resolve => resolve(resource.resourceId));
var userCanMarkPage = (user, page) => new Promise((resolve,reject) => {
if (user.firstname == 'Timmmmy')
return resolve();
return reject();
});
var acl = new Acl(getUserRoleId, getResourceId);
acl.addRole('visitor') // equivalent to acl.addRole(new Role('visitor', [], acl))
.addRole(new Role('user', ['visitor'], acl))
.addRole('admin', ['user']) //equivalent to acl.addRole(new Role('admin', ['user'], acl))
.addResource(new Resource('page', ['read', 'mark', 'change title']))
.addResource(new Resource('book'))
.build();
acl.allow('visitor', 'page', 'read')
.allow('user', 'page')
.allow('user', 'page', 'mark', userCanMarkPage)
.deny('user', 'page', 'change title')
.allow('admin', 'page', 'change title')
.allow('admin', 'book');
//console.log('---built permissions---');
//console.log('---visitor---');
//console.log(acl.getPermissions('visitor'));
//console.log('---user---');
//console.log(acl.getPermissions('user'));
//console.log('---admin---');
//console.log(acl.getPermissions('admin'));
//console.log('---anonymous permissions check---');
acl.isAllowed(anonymous, page1).then(
() => {
// anonymous should not be allowed
console.error('This should not be printed in console');
},
() => {
// anonymous is not allowed
console.log('anonymous isAllowed page1:* -> false');
}
);
acl.isAllowed(anonymous, page1, 'read').then(
// anonymous is allowed
() => {console.log('anonymous isAllowed page1:read -> true')},
() => {console.error('This should not be printed in console')}
);
acl.isAllowed(anonymous, page1, 'mark').then(
() => {console.error('This should not be printed in console')},
// anonymous is not allowed
() => {console.log('anonymous isAllowed page1:mark -> false')}
);
acl.isAllowed(anonymous, page1, 'change title').then(
() => {console.error('This should not be printed in console')},
// anonymous is not allowed
() => {console.log('anonymous isAllowed page1:change title -> false')}
);
acl.isAllowed(anonymous, book).then(
() => {console.error('This should not be printed in console')},
// anonymous is not allowed
() => {console.log('anonymous isAllowed book:* -> false')}
);
acl.isAllowed(anonymous, book, 'sell').then(
() => {console.error('This should not be printed in console')},
// anonymous is not allowed
() => {console.log('anonymous isAllowed book:sell -> false')}
);
//console.log('---user permissions check---');
acl.isAllowed(bob, page1).then(
() => {console.log('bob isAllowed page1:* -> true')},
() => {console.error('This should not be printed in console')}
);
acl.isAllowed(bob, page1, 'read').then(
() => {console.log('bob isAllowed page1:read -> true')},
() => {console.error('This should not be printed in console')}
);
acl.isAllowed(bob, page1, 'mark').then(
() => {console.error('This should not be printed in console')},
() => {console.log('bob isAllowed page1:mark -> false')}
);
acl.isAllowed(bob, page1, 'change title').then(
() => {console.error('This should not be printed in console')},
() => {console.log('bob isAllowed page1:change title -> false')}
);
acl.isAllowed(bob, book, 'book:*').then(
() => {console.error('This should not be printed in console')},
() => {console.log('bob isAllowed book:* -> false')}
);
acl.isAllowed(bob, book, 'book:sell').then(
() => {console.error('This should not be printed in console')},
() => {console.log('bob isAllowed book:sell -> false')}//privilege was not declared previously -> inherit from book:*
);
//console.log('---admin permissions check---');
acl.isAllowed(me, page1).then(
() => {console.log('me isAllowed page1:* -> true')},
() => {console.error('This should not be printed in console')}
);
acl.isAllowed(me, page1, 'read').then(
() => {console.log('me isAllowed page1:read -> true')},
() => {console.error('This should not be printed in console')}
);
acl.isAllowed(me, page1, 'mark').then(
() => {console.log('me isAllowed page1:mark -> true')},
() => {console.error('This should not be printed in console')}
);
acl.isAllowed(me, page1, 'change title').then(
() => {console.log('me isAllowed page1:change title -> true')},
() => {console.error('This should not be printed in console')}
);
acl.isAllowed(me, book).then(
() => {console.log('me isAllowed book:* -> true')},
() => {console.error('This should not be printed in console')}
);
acl.isAllowed(me, book, 'sell').then(
() => {console.log('me isAllowed book:sell -> true')},//privilege was not declared previously -> inherit from book:*
() => {console.error('This should not be printed in console')}
);
#API Reference
Acl
This class holds all information about Roles, Resources and Permissions
Kind: global class
- Acl
- new Acl(roleIdFetchFunc, resourceIdFetchFunc)
- .setRoleIdFetchFunc(func) ⇒ Acl
- .setResourceIdFetchFunc(func) ⇒ Acl
- .addRole(role, Parents) ⇒ Acl
- .removeRole(role) ⇒ Acl
- .getRole(id) ⇒ Role
- .addResource(resource) ⇒ Acl
- .removeResource(resource) ⇒ Acl
- .getResource(id) ⇒ Resource | null
- .build() ⇒ Acl
- .allow(roleId, resourceId, privilege, condition) ⇒ Acl
- .deny(roleId, resourceId, privilege, condition) ⇒ Acl
- ._allowOrDeny(allow, roleId, resourceId, privilege, condition)
- .isAllowed(user, resource, privilege) ⇒ Promise
- .isRoleAllowed(roleId, resourceId, privilege) ⇒ Promise
- .isAnyParentAllowed(roleId, resourceId, privilege) ⇒ Promise
- .getPermissions(roleId) ⇒ Array.<Object>
new Acl(roleIdFetchFunc, resourceIdFetchFunc)
Constructor
| Param | Type | Description | | --- | --- | --- | | roleIdFetchFunc | fetchRoleIdFunc | function that will let Acl fetch Role id (default will return empty string) | | resourceIdFetchFunc | fetchResourceIdFunc | function that will let Acl fetch Resource id (default will return empty string) |
Example
var myAcl = new Acl(function(user){
return Promise.resolve(user.getRole());
}, function(resource){
return Promise.resolve(resource.getResourceId());
});
acl.setRoleIdFetchFunc(func) ⇒ Acl
Sets how Acl should retrieve Role Id
Kind: instance method of Acl
Returns: Acl - this instance for chaining
| Param | Type | Description | | --- | --- | --- | | func | fetchRoleIdFunc | that will let Acl fetch Role Id from an object that may have a role |
acl.setResourceIdFetchFunc(func) ⇒ Acl
Sets how Acl should retrieve Resource Id
Kind: instance method of Acl
Returns: Acl - this instance for chaining
| Param | Type | Description | | --- | --- | --- | | func | fetchResourceIdFunc | that will let Acl fetch Resource Id from an object that may be a resource |
acl.addRole(role, Parents) ⇒ Acl
Add a new Role to Access Control List
Kind: instance method of Acl
Returns: Acl - this instanc@e for chaining
Throws:
- Error if role is not an instance of Role or a string
| Param | Type | Description | | --- | --- | --- | | role | Role | string | instance to add | | Parents | Array.<string> | Array.<Role> | default is empty array |
Example
acl.addRole('anonyme');
acl.addRole('user', ['anonyme']);
acl.addRole(new Role('admin', ['user'], acl));
acl.addRole('super', [new Role('normal', [], acl)]);
acl.removeRole(role) ⇒ Acl
Deletes role from the list of declared roles
Kind: instance method of Acl
Returns: Acl - this instance for chaining
| Param | Type | | --- | --- | | role | Role | string |
Example
acl.remove('anonymous');
acl.getRole(id) ⇒ Role
Retrieve an instance of Role identified by id. It must be added before calling this function
Kind: instance method of Acl
Returns: Role - a Role instance if it was previously added or null if not exists
| Param | Type | Description | | --- | --- | --- | | id | string | of Role to retrieve |
acl.addResource(resource) ⇒ Acl
Add a new resource to Access Control List
Kind: instance method of Acl
Returns: Acl - this instance for chaining
Throws:
- Error if resource is not an instance of Acl
| Param | Type | Description | | --- | --- | --- | | resource | Resource | to add to Access Control List |
Example
acl.addResource(new Resource('page'));
acl.addResource(new Resource('book', ['read', 'buy']);
acl.removeResource(resource) ⇒ Acl
Removes a resource from Access Control List
Kind: instance method of Acl
Returns: Acl - this instance for chaining
Throws:
- Error if resource is not an instance of Resource or of type string
| Param | Type | Description | | --- | --- | --- | | resource | Resource | string | to remove |
Example
acl.removeResource('page');
acl.removeResource(bookResourceInstance);
acl.getResource(id) ⇒ Resource | null
Get resource instance by its Id if it was previously added to Access Control List
Kind: instance method of Acl
Returns: Resource | null - Resource instance if it exists. will return null otherwise
| Param | Type | Description | | --- | --- | --- | | id | string | Resource | of resource to get |
Example
acl.getResource('page');
acl.build() ⇒ Acl
Build all permissions based on added Role and Resource. Permissions are initialized to allow = false and condition = null
Kind: instance method of Acl
Returns: Acl - this instance for chaining
acl.allow(roleId, resourceId, privilege, condition) ⇒ Acl
Allow User with Role Id to access Privileged Resource (which have Resource Id) under condition
Kind: instance method of Acl
Returns: Acl - this instance for chaining
| Param | Type | Default | Description | | --- | --- | --- | --- | | roleId | string | Role | | Role Id or Role instance | | resourceId | string | Resource | | Resource Id or Resource instance | | privilege | string | Array.<string> | "" | Privilege (default is '' all) | | condition | permissionConditionFunc | | Conditional permission function (default is null) |
Example
acl.allow('user', 'article', 'write')
.allow('user', 'article', ['read', 'comment']);
.allow('user', 'article', 'modify', function(user, blog){
return user.id == article.author_id;
});
acl.deny(roleId, resourceId, privilege, condition) ⇒ Acl
Deny User with Role Id to access Privileged Resource (which have Resource Id) under condition
Kind: instance method of Acl
Returns: Acl - this instance for chaining
| Param | Type | Default | Description | | --- | --- | --- | --- | | roleId | string | Role | | Role Id or Role instance | | resourceId | string | Resource | | Resource Id or Resource instance | | privilege | string | Array.<string> | "" | Privilege (default is '' all) | | condition | permissionConditionFunc | | Conditional permission function (default is null) |
Example
acl.deny('anonymous', 'article', 'write')
.deny('anonymous', 'article', ['modify', 'comment'])
.deny('anonymous', 'article', 'read', function(user, article){
return article.is_public;
});
acl._allowOrDeny(allow, roleId, resourceId, privilege, condition)
Allow User with Role Id to access Privileged Resource (which have Resource Id) under condition
Kind: instance method of Acl
| Param | Type | Default | Description | | --- | --- | --- | --- | | allow | boolean | | true = allowed, false = denied | | roleId | string | Role | | Role Id or Role instance | | resourceId | string | Resource | | Resource Id or Resource instance | | privilege | string | "" | Privilege (default is '' all) | | condition | permissionConditionFunc | | Conditional permission function (default is null) |
acl.isAllowed(user, resource, privilege) ⇒ Promise
Checks if user is allowed to access resource with a given privilege. If yes, it checks condition
Kind: instance method of Acl
| Param | Type | Default | | --- | --- | --- | | user | * | | | resource | * | | | privilege | string | "*" |
Example
acl.isAllowed(userObject, resourceObject, 'read');
acl.isAllowed(userObject, resourceObject);
acl.isRoleAllowed(roleId, resourceId, privilege) ⇒ Promise
Checks if roleId has access to resourceId with privilege. If not, it will check if one of the related parents has access to resource id
Kind: instance method of Acl
| Param | Type | Default | | --- | --- | --- | | roleId | string | | | resourceId | string | | | privilege | string | "*" |
Example
acl.isRoleAllowed('user', 'book', 'read');
acl.isRoleAllow('user', 'page');
acl.isAnyParentAllowed(roleId, resourceId, privilege) ⇒ Promise
Checks if any role's parents is allowed to access resourceId with privileges
Kind: instance method of Acl
| Param | Type | | --- | --- | | roleId | string | | resourceId | string | | privilege | string |
acl.getPermissions(roleId) ⇒ Array.<Object>
Returns an object representing roleId permissions
Kind: instance method of Acl
Returns: Array.<Object> - Permissions for each resource
| Param | Type | | --- | --- | | roleId | string | Role |
Example
acl.getPermissions('user');
<a name="Role"></a>
Role
Role class
Kind: global class
- Role
- new Role(id, parents, acl)
- .setAcl(acl)
- .getAcl() ⇒ Acl | *
- .setId(id) ⇒ Role
- .getId() ⇒ string
- .setParents(parents) ⇒ Role
- .getParents() ⇒ Array | Array.<Role>
- .getParent(role) ⇒ Role | null
- .addParent(role) ⇒ Role
- .addParents(roles) ⇒ Role
- .removeParent({Role|string) ⇒ Role
- .removeParents(roles) ⇒ Role
- .toString() ⇒ string
new Role(id, parents, acl)
Creates a new role and attach it to Acl
Throws:
- Error if acl is not an instance of {Acl} or given parents were not declared before
| Param | Type | Default | Description | | --- | --- | --- | --- | | id | string | | role's id | | parents | Array.<string> | Array.<Role> | | list of parents | | acl | Acl | | ACL to which this role will be attached |
role.setAcl(acl)
Sets the ACL to which this role will be attached
Kind: instance method of Role
| Param | Type | | --- | --- | | acl | Acl |
role.getAcl() ⇒ Acl | *
Returns the ACL to which this role is attached
Kind: instance method of Role
role.setId(id) ⇒ Role
Sets the role id of this instance
Kind: instance method of Role
Returns: Role - - This object
Throws:
- Error - if id is not a string
| Param | Type | Description | | --- | --- | --- | | id | string | Role identification |
role.getId() ⇒ string
Returns this Role id
Kind: instance method of Role
Returns: string - id - Role id
role.setParents(parents) ⇒ Role
Sets role parents.
Kind: instance method of Role
Returns: Role - this instance for chaining
Throws:
- Error if one of the given parents was not declared before
| Param | Type | Description | | --- | --- | --- | | parents | Array.<string> | Array.<Role> | null | Role parents: must be declared as individual roles before |
role.getParents() ⇒ Array | Array.<Role>
Returns parents roles of this instance
Kind: instance method of Role
role.getParent(role) ⇒ Role | null
Get a parent from this role
Kind: instance method of Role
Returns: Role | null - null if parent role was not found
| Param | Type | Description | | --- | --- | --- | | role | Role | string | id or role instance to retrieve |
role.addParent(role) ⇒ Role
Add parent to this role. If it already exists in parents list, it will be replaced
Kind: instance method of Role
Returns: Role - this instance for chaining
Throws:
- Error if no Acl was attached to this role or if parent was not declared previously
| Param | Type | Description | | --- | --- | --- | | role | Role | string | Parent Role instance of its id |
role.addParents(roles) ⇒ Role
Add an array of parents role to this instance
Kind: instance method of Role
Returns: Role - this instance for chaining
Throws:
- Error if no Acl was attached to this role or if one parent was not declared previously
| Param | Type | Description | | --- | --- | --- | | roles | Array.<Role> | Array.<string> | to add as parents to this instance |
role.removeParent({Role|string) ⇒ Role
Remove a parent from the list of this role's parents
Kind: instance method of Role
Returns: Role - this instance for chaining
| Param | Description | | --- | --- | | {Role|string | role Parent role isntance or its role id |
role.removeParents(roles) ⇒ Role
Remove a role from parent list
Kind: instance method of Role
Returns: Role - this instance for chaining
| Param | Type | Description | | --- | --- | --- | | roles | Array.<string> | Array.<Role> | to remove from parents list |
role.toString() ⇒ string
Returns
Kind: instance method of Role
Returns: string - - role Id
Resource
Kind: global class
Trows: Error if privileges is not an Array of strings
new Resource(id, privileges)
Constructor
| Param | Type | Description | | --- | --- | --- | | id | string | of this Resource | | privileges | Array.<string> | access privileges for this resource |
resource.setId(id) ⇒ Resource
Sets this resource Id
Kind: instance method of Resource
Returns: Resource - instance for chaining
Throws:
- Error if id is not a string
| Param | Type | | --- | --- | | id | string |
resource.getId() ⇒ string
Retrieve resource id
Kind: instance method of Resource
Returns: string - id of this resource
resource.getPrivileges() ⇒ Array.<string>
Retrieve access privileges for this resource
Kind: instance method of Resource
Returns: Array.<string> - Array of access privileges
resource.setPrivileges(privileges) ⇒ Resource
Sets access privileges for this resource
Kind: instance method of Resource
Throws:
- Error if privileges is not an array of strings
| Param | Type | Description | | --- | --- | --- | | privileges | Array.<string> | to set |
resource.addPrivilege(privilege) ⇒ Resource
Add an access privilege to this resource
Kind: instance method of Resource
Throw: Error - if privilege is not a string
| Param | Type | | --- | --- | | privilege | string |
resource.removePrivilege(privilege) ⇒ Resource
Removes access privilege from this resource
Kind: instance method of Resource
Returns: Resource - - this instance
| Param | Type | Description | | --- | --- | --- | | privilege | string | access privilege to remove |