diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index d63ab9a..eed613e 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -9,7 +9,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest]
- node: ['12', '14', '16']
+ node: ['16', '18', '20']
steps:
- uses: actions/checkout@v2
@@ -30,8 +30,8 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest]
- node: ['12', '14', '16']
- redis-version: [4, 5, 6]
+ node: ['16', '18', '20']
+ redis-version: [5, 6, 7]
steps:
- uses: actions/checkout@v2
@@ -57,8 +57,8 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest]
- node: ['12', '14', '16']
- mongodb-version: [4.0, 5.0]
+ node: ['16', '18', '20']
+ mongodb-version: [6, 7]
steps:
- uses: actions/checkout@v2
@@ -74,9 +74,9 @@ jobs:
- run: npm install
- - run: npm install mongodb@4
+ - run: npm install mongodb@6
- run: npm run test_mongo
- - run: npm install mongodb@3
+ - run: npm install mongodb@5
- run: npm run test_mongo
test_mongo_single:
@@ -85,8 +85,8 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest]
- node: ['12', '14', '16']
- mongodb-version: [4.0, 5.0]
+ node: ['16', '18', '20']
+ mongodb-version: [6, 7]
steps:
- uses: actions/checkout@v2
@@ -102,7 +102,7 @@ jobs:
- run: npm install
- - run: npm install mongodb@4
+ - run: npm install mongodb@6
- run: npm run test_mongo_single
- - run: npm install mongodb@3
+ - run: npm install mongodb@5
- run: npm run test_mongo_single
diff --git a/.nvmrc b/.nvmrc
new file mode 100644
index 0000000..b6a7d89
--- /dev/null
+++ b/.nvmrc
@@ -0,0 +1 @@
+16
diff --git a/README.md b/README.md
index 1a64605..e20cf02 100644
--- a/README.md
+++ b/README.md
@@ -16,43 +16,37 @@ A Redis, MongoDB and In-Memory based backends are provided built-in in the modul
### Breaking changes comparing to the original `acl`
-* The backend constructors take options object instead of multiple argument.
+- The backend constructors take options object instead of multiple argument.
Original `acl`:
+
```js
-new ACL.mongodbBackend(db, prefix, useSingle, useRawCollectionNames)
-new ACL.redisBackend(redis, prefix)
+new ACL.mongodbBackend(db, prefix, useSingle, useRawCollectionNames);
+new ACL.redisBackend(redis, prefix);
```
New `acl2`:
+
```js
new ACL.mongodbBackend({ client, db, prefix = "acl_", useSingle, useRawCollectionNames })
new ACL.redisBackend({ redis, prefix = "acl_" })
```
-* The new default `"acl_"` prefix for both Redis and MongoDB.
-
-* The `mongodb` dependency upgraded from v2 to the latest v3 - v4.
-
-* Both `mongodb` and `redis` dependencies moved to `devDependencies`. You have to install them to your project separately.
-
-* The minimal supported nodejs version was `0.10`, but became the current LTS `12`.
+- The new default `"acl_"` prefix for both Redis and MongoDB.
-* The first published version of `acl2` is `1.0` to be more SemVer compliant.
+- Maintained and modern code infrastructure.
### Other notable changes comparing to the original `acl`
-* ES6
-* ESLint
-* Prettier
-* Internally use more promises, fewer callbacks for better stack traces
-* Upgraded all possible dependencies
-* Made unit test debuggable, split them by backend type
-* MongoDB backend accepts either `client` or `db` [objects](https://github.com/mongodb/node-mongodb-native/blob/3.0/CHANGES_3.0.0.md)
-* Removed all possible warnings
-* Run CI tests using multiple MongoDB versions.
-
-###
+- ES6
+- ESLint
+- Prettier
+- Promises only, no callbacks
+- Upgraded all possible dependencies
+- Made unit test debuggable, split them by backend type
+- MongoDB backend accepts either `client` or `db` [objects](https://github.com/mongodb/node-mongodb-native/blob/3.0/CHANGES_3.0.0.md)
+- Removed all possible warnings
+- Run CI tests using multiple MongoDB versions.
## Features
@@ -71,7 +65,7 @@ Using npm:
npm install acl2
```
-Optionally:
+Optionally:
```shell script
npm install mongodb
@@ -104,10 +98,10 @@ npm install redis
Create your acl module by requiring it and instantiating it with a valid backend instance:
```javascript
-var ACL = require("acl2");
+const ACL = require("acl2");
// Using Redis backend
-acl = new ACL(new ACL.redisBackend({ client: redisClient }));
+acl = new ACL(new ACL.redisBackend({ redis: redisClient }));
// Or Using the memory backend
acl = new ACL(new ACL.memoryBackend());
@@ -116,50 +110,49 @@ acl = new ACL(new ACL.memoryBackend());
acl = new ACL(new ACL.mongodbBackend({ client: mongoClient }));
```
-See below for full list of backend constructor arguments.
+See below for full list of backend constructor arguments.
-All the following functions return a promise or optionally take a callback with
-an err parameter as last parameter. We omit them in the examples for simplicity.
+All the following functions return a promise.
Create roles implicitly by giving them permissions:
```javascript
// guest is allowed to view blogs
-acl.allow("guest", "blogs", "view");
+await acl.allow("guest", "blogs", "view");
// allow function accepts arrays as any parameter
-acl.allow("member", "blogs", ["edit", "view", "delete"]);
+await acl.allow("member", "blogs", ["edit", "view", "delete"]);
```
Users are likewise created implicitly by assigning them roles:
```javascript
-acl.addUserRoles("joed", "guest");
+await acl.addUserRoles("joed", "guest");
```
Hierarchies of roles can be created by assigning parents to roles:
```javascript
-acl.addRoleParents("baz", ["foo", "bar"]);
+await acl.addRoleParents("baz", ["foo", "bar"]);
```
Note that the order in which you call all the functions is irrelevant (you can add parents first and assign permissions to roles later)
```javascript
-acl.allow("foo", ["blogs", "forums", "news"], ["view", "delete"]);
+await acl.allow("foo", ["blogs", "forums", "news"], ["view", "delete"]);
```
Use the wildcard to give all permissions:
```javascript
-acl.allow("admin", ["blogs", "forums"], "*");
+await acl.allow("admin", ["blogs", "forums"], "*");
```
Sometimes is necessary to set permissions on many different roles and resources. This would
lead to unnecessary nested callbacks for handling errors. Instead use the following:
```javascript
-acl.allow([
+await acl.allow([
{
roles: ["guest", "member"],
allows: [
@@ -180,17 +173,16 @@ acl.allow([
You can check if a user has permissions to access a given resource with _isAllowed_:
```javascript
-acl.isAllowed("joed", "blogs", "view", function (err, res) {
- if (res) {
- console.log("User joed is allowed to view blogs");
- }
-});
+const res = await acl.isAllowed("joed", "blogs", "view");
+if (res) {
+ console.log("User joed is allowed to view blogs");
+}
```
Of course arrays are also accepted in this function:
```javascript
-acl.isAllowed("jsmith", "blogs", ["edit", "view", "delete"]);
+await acl.isAllowed("jsmith", "blogs", ["edit", "view", "delete"]);
```
Note that all permissions must be fulfilled in order to get _true_.
@@ -198,12 +190,8 @@ Note that all permissions must be fulfilled in order to get _true_.
Sometimes is necessary to know what permissions a given user has over certain resources:
```javascript
-acl.allowedPermissions("james", ["blogs", "forums"], function (
- err,
- permissions
-) {
- console.log(permissions);
-});
+const permissions = await acl.allowedPermissions("james", ["blogs", "forums"]);
+console.log(permissions);
```
It will return an array of resource:[permissions] like this:
@@ -227,7 +215,7 @@ app.put('/blogs/:id', acl.middleware(), function(req, res, next){…}
The middleware will protect the resource named by _req.url_, pick the user from _req.session.userId_ and check the permission for _req.method_, so the above would be equivalent to something like this:
```javascript
-acl.isAllowed(req.session.userId, "/blogs/12345", "put");
+await acl.isAllowed(req.session.userId, "/blogs/12345", "put");
```
The middleware accepts 3 optional arguments, that are useful in some situations. For example, sometimes we
@@ -249,85 +237,80 @@ app.put('/blogs/:id/comments/:commentId', acl.middleware(3, 'joed', 'post'), fun
-### addUserRoles( userId, roles, function(err) )
+### addUserRoles( userId, roles )
Adds roles to a given user id.
**Arguments**
```javascript
- userId {String|Number} User id.
+ userId {String} User id.
roles {String|Array} Role(s) to add to the user id.
- callback {Function} Callback called when finished.
```
---
-### removeUserRoles( userId, roles, function(err) )
+### removeUserRoles( userId, roles )
Remove roles from a given user.
**Arguments**
```javascript
- userId {String|Number} User id.
+ userId {String} User id.
roles {String|Array} Role(s) to remove to the user id.
- callback {Function} Callback called when finished.
```
---
-### userRoles( userId, function(err, roles) )
+### userRoles( userId )
Return all the roles from a given user.
**Arguments**
```javascript
- userId {String|Number} User id.
- callback {Function} Callback called when finished.
+ userId {String} User id.
```
---
-### roleUsers( rolename, function(err, users) )
+### roleUsers( roleName )
Return all users who has a given role.
**Arguments**
```javascript
- rolename {String|Number} User id.
- callback {Function} Callback called when finished.
+ roleName {String} User id.
```
---
-### hasRole( userId, rolename, function(err, hasRole) )
+### hasRole( userId, rolroleNameename )
Return boolean whether user has the role
**Arguments**
```javascript
- userId {String|Number} User id.
- rolename {String|Number} role name.
- callback {Function} Callback called when finished.
+ userId {String} User id.
+ roleName {String} role name.
```
---
-### addRoleParents( role, parents, function(err) )
+### addRoleParents( role, parents )
Adds a parent or parent list to role.
@@ -336,14 +319,13 @@ Adds a parent or parent list to role.
```javascript
role {String} Child role.
parents {String|Array} Parent role(s) to be added.
- callback {Function} Callback called when finished.
```
---
-### removeRoleParents( role, parents, function(err) )
+### removeRoleParents( role, parents )
Removes a parent or parent list from role.
@@ -354,14 +336,13 @@ If `parents` is not specified, removes all parents.
```javascript
role {String} Child role.
parents {String|Array} Parent role(s) to be removed [optional].
- callback {Function} Callback called when finished [optional].
```
---
-### removeRole( role, function(err) )
+### removeRole( role )
Removes a role from the system.
@@ -369,13 +350,13 @@ Removes a role from the system.
```javascript
role {String} Role to be removed
- callback {Function} Callback called when finished.
```
---
-### removeResource( resource, function(err) )
+
+### removeResource( resource )
Removes a resource from the system
@@ -383,14 +364,13 @@ Removes a resource from the system
```javascript
resource {String} Resource to be removed
- callback {Function} Callback called when finished.
```
---
-### allow( roles, resources, permissions, function(err) )
+### allow( roles, resources, permissions )
Adds the given permissions to the given roles over the given resources.
@@ -400,25 +380,22 @@ Adds the given permissions to the given roles over the given resources.
roles {String|Array} role(s) to add permissions to.
resources {String|Array} resource(s) to add permisisons to.
permissions {String|Array} permission(s) to add to the roles over the resources.
- callback {Function} Callback called when finished.
```
-### allow( permissionsArray, function(err) )
+### allow( permissionsArray )
**Arguments**
```javascript
permissionsArray {Array} Array with objects expressing what permissions to give.
[{roles:{String|Array}, allows:[{resources:{String|Array}, permissions:{String|Array}]]
-
- callback {Function} Callback called when finished.
```
---
-### removeAllow( role, resources, permissions, function(err) )
+### removeAllow( role, resources )
Remove permissions from the given roles owned by the given role.
@@ -430,14 +407,13 @@ Note: we loose atomicity when removing empty role_resources.
role {String}
resources {String|Array}
permissions {String|Array}
- callback {Function}
```
---
-### allowedPermissions( userId, resources, function(err, obj) )
+### allowedPermissions( userId, resources )
Returns all the allowable permissions a given user have to
access the given resources.
@@ -448,16 +424,15 @@ resource name to a list of permissions for that resource.
**Arguments**
```javascript
- userId {String|Number} User id.
+ userId {String} User id.
resources {String|Array} resource(s) to ask permissions for.
- callback {Function} Callback called when finished.
```
---
-### isAllowed( userId, resource, permissions, function(err, allowed) )
+### isAllowed( userId, resource, permissions )
Checks if the given user is allowed to access the resource for the given
permissions (note: it must fulfill all the permissions).
@@ -465,17 +440,16 @@ permissions (note: it must fulfill all the permissions).
**Arguments**
```javascript
- userId {String|Number} User id.
+ userId {String} User id.
resource {String} resource to ask permissions for.
permissions {String|Array} asked permissions.
- callback {Function} Callback called with the result.
```
---
-### areAnyRolesAllowed( roles, resource, permissions, function(err, allowed) )
+### areAnyRolesAllowed( roles, resource, permissions )
Returns true if any of the given roles have the right permissions.
@@ -485,14 +459,13 @@ Returns true if any of the given roles have the right permissions.
roles {String|Array} Role(s) to check the permissions for.
resource {String} resource to ask permissions for.
permissions {String|Array} asked permissions.
- callback {Function} Callback called with the result.
```
---
-### whatResources(role, function(err, {resourceName: [permissions]})
+### whatResources(role) : {resourceName: [permissions]}
Returns what resources a given role has permissions over.
@@ -500,10 +473,9 @@ Returns what resources a given role has permissions over.
```javascript
role {String|Array} Roles
- callback {Function} Callback called with the result.
```
-whatResources(role, permissions, function(err, resources) )
+whatResources(role, permissions) : resources
Returns what resources a role has the given permissions over.
@@ -512,7 +484,6 @@ Returns what resources a role has the given permissions over.
```javascript
role {String|Array} Roles
permissions {String|Array} Permissions
- callback {Function} Callback called with the result.
```
---
@@ -529,7 +500,7 @@ To create a custom getter for userId, pass a function(req, res) which returns th
```javascript
numPathComponents {Number} number of components in the url to be considered part of the resource name.
- userId {String|Number|Function} the user id for the acl system (defaults to req.session.userId)
+ userId {String} the user id for the acl system (defaults to req.session.userId)
permissions {String|Array} the permission(s) to check for (defaults to req.method.toLowerCase())
```
@@ -544,7 +515,7 @@ Creates a MongoDB backend instance.
**Arguments**
```javascript
- client {Object} MongoClient instance. If missing, the `db` will be used.
+ client {Object} MongoClient instance. If missing, the `db` will be used.
db {Object} Database instance. If missing, the `client` will be used.
prefix {String} Optional collection prefix. Default is "acl_".
useSingle {Boolean} Create one collection for all resources (defaults to false)
@@ -553,7 +524,9 @@ Creates a MongoDB backend instance.
Example:
```javascript
-const client = await require("mongodb").connect("mongodb://127.0.0.1:27017/acl_test");
+const client = await require("mongodb").connect(
+ "mongodb://127.0.0.1:27017/acl_test"
+);
const ACL = require("acl2");
const acl = new ACL(new ACL.mongodbBackend({ client, useSingle: true }));
```
@@ -565,16 +538,18 @@ Creates a Redis backend instance.
**Arguments**
```javascript
- client {Object} Redis client instance.
+ client {Object} Redis client instance.
prefix {String} Optional prefix. Default is "acl_".
```
Example:
```javascript
-var client = require("redis").createClient(6379, "127.0.0.1", { no_ready_check: true });
+const client = await require("redis").createClient(6379, "127.0.0.1").connect();
const ACL = require("acl2");
-const acl = new ACL(new acl.redisBackend({ client, prefix: "my_acl_prefix_" }));
+const acl = new ACL(
+ new acl.redisBackend({ redis: client, prefix: "my_acl_prefix_" })
+);
```
## Tests
@@ -592,4 +567,4 @@ npm run test_memory
npm run test_redis
npm run test_mongo
npm run test_mongo_single
-```
+```
diff --git a/lib/acl.js b/lib/acl.js
index 753f60f..3a422c0 100644
--- a/lib/acl.js
+++ b/lib/acl.js
@@ -1,4 +1,4 @@
-/**
+/*
ACL System inspired on Zend_ACL.
All functions accept strings, objects or arrays unless specified otherwise.
@@ -29,16 +29,13 @@
a resource, then he can get exclusive write operation on the locked resource.
This lock should expire if the resource has not been accessed in some time.
*/
-"use strict";
-
-var _ = require("lodash"),
+const _ = require("lodash"),
util = require("util"),
- bluebird = require("bluebird"),
contract = require("./contract");
contract.debug = true;
-var Acl = function (backend, logger, options) {
+const Acl = function (backend, logger, options) {
contract(arguments).params("object").params("object", "object").params("object", "object", "object").end();
options = _.extend(
@@ -58,302 +55,236 @@ var Acl = function (backend, logger, options) {
this.logger = logger;
this.backend = backend;
this.options = options;
-
- // Promisify async methods
- backend.endAsync = bluebird.promisify(backend.end);
- backend.getAsync = bluebird.promisify(backend.get);
- backend.cleanAsync = bluebird.promisify(backend.clean);
- backend.unionAsync = bluebird.promisify(backend.union);
- if (backend.unions) {
- backend.unionsAsync = bluebird.promisify(backend.unions);
- }
};
/**
- addUserRoles( userId, roles, function(err) )
+ addUserRoles( userId, roles )
Adds roles to a given user id.
- @param {String|Number} User id.
- @param {String|Array} Role(s) to add to the user id.
- @param {Function} Callback called when finished.
+ @param {String} userId
+ @param {String|Array} roles to add to the user id.
@return {Promise} Promise resolved when finished
*/
-Acl.prototype.addUserRoles = function (userId, roles, cb) {
- contract(arguments)
- .params("string|number", "string|array", "function")
- .params("string|number", "string|array")
- .end();
+Acl.prototype.addUserRoles = async function (userId, roles) {
+ contract(arguments).params("string", "string|array").end();
- var transaction = this.backend.begin();
- this.backend.add(transaction, this.options.buckets.meta, "users", userId);
- this.backend.add(transaction, this.options.buckets.users, userId, roles);
+ const transaction = await this.backend.begin();
+ await this.backend.add(transaction, this.options.buckets.meta, "users", userId);
+ await this.backend.add(transaction, this.options.buckets.users, userId, roles);
if (Array.isArray(roles)) {
for (const role of roles) {
- this.backend.add(transaction, this.options.buckets.roles, role, userId);
+ await this.backend.add(transaction, this.options.buckets.roles, role, userId);
}
} else {
- this.backend.add(transaction, this.options.buckets.roles, roles, userId);
+ await this.backend.add(transaction, this.options.buckets.roles, roles, userId);
}
- return this.backend.endAsync(transaction).nodeify(cb);
+ return await this.backend.end(transaction);
};
/**
- removeUserRoles( userId, roles, function(err) )
+ removeUserRoles( userId, roles )
Remove roles from a given user.
- @param {String|Number} User id.
- @param {String|Array} Role(s) to remove to the user id.
- @param {Function} Callback called when finished.
+ @param {String} userId
+ @param {String|Array} roles to remove to the user id.
@return {Promise} Promise resolved when finished
*/
-Acl.prototype.removeUserRoles = function (userId, roles, cb) {
- contract(arguments)
- .params("string|number", "string|array", "function")
- .params("string|number", "string|array")
- .end();
+Acl.prototype.removeUserRoles = async function (userId, roles) {
+ contract(arguments).params("string", "string|array").end();
- var transaction = this.backend.begin();
- this.backend.remove(transaction, this.options.buckets.users, userId, roles);
+ const transaction = await this.backend.begin();
+ await this.backend.remove(transaction, this.options.buckets.users, userId, roles);
if (Array.isArray(roles)) {
for (const role of roles) {
- this.backend.remove(transaction, this.options.buckets.roles, role, userId);
+ await this.backend.remove(transaction, this.options.buckets.roles, role, userId);
}
} else {
- this.backend.remove(transaction, this.options.buckets.roles, roles, userId);
+ await this.backend.remove(transaction, this.options.buckets.roles, roles, userId);
}
- return this.backend.endAsync(transaction).nodeify(cb);
+ return await this.backend.end(transaction);
};
/**
- userRoles( userId, function(err, roles) )
+ userRoles( userId )
Return all the roles from a given user.
- @param {String|Number} User id.
- @param {Function} Callback called when finished.
+ @param {String} userId
@return {Promise} Promise resolved with an array of user roles
*/
-Acl.prototype.userRoles = function (userId, cb) {
- return this.backend.getAsync(this.options.buckets.users, userId).nodeify(cb);
+Acl.prototype.userRoles = async function (userId) {
+ return await this.backend.get(this.options.buckets.users, userId);
};
/**
- roleUsers( roleName, function(err, users) )
+ roleUsers( roleName ) : users
Return all users who has a given role.
- @param {String|Number} rolename.
- @param {Function} Callback called when finished.
+ @param {String} roleName
@return {Promise} Promise resolved with an array of users
*/
-Acl.prototype.roleUsers = function (roleName, cb) {
- return this.backend.getAsync(this.options.buckets.roles, roleName).nodeify(cb);
+Acl.prototype.roleUsers = function (roleName) {
+ return this.backend.get(this.options.buckets.roles, roleName);
};
/**
- hasRole( userId, rolename, function(err, is_in_role) )
+ hasRole( userId, roleName ) : is_in_role
Return boolean whether user is in the role
- @param {String|Number} User id.
- @param {String|Number} rolename.
- @param {Function} Callback called when finished.
+ @param {String} userId
+ @param {String} roleName
@return {Promise} Promise resolved with boolean of whether user is in role
*/
-Acl.prototype.hasRole = function (userId, rolename, cb) {
- return this.userRoles(userId)
- .then((roles) => roles.indexOf(rolename) != -1)
- .nodeify(cb);
+Acl.prototype.hasRole = async function (userId, roleName) {
+ let roles = await this.userRoles(userId);
+ return roles.indexOf(roleName) !== -1;
};
/**
- addRoleParents( role, parents, function(err) )
+ addRoleParents( role, parents )
Adds a parent or parent list to role.
- @param {String} Child role.
- @param {String|Array} Parent role(s) to be added.
- @param {Function} Callback called when finished.
+ @param {String} role Child role.
+ @param {String|Array} parents Parent role(s) to be added.
@return {Promise} Promise resolved when finished
*/
-Acl.prototype.addRoleParents = function (role, parents, cb) {
- contract(arguments)
- .params("string|number", "string|array", "function")
- .params("string|number", "string|array")
- .end();
+Acl.prototype.addRoleParents = async function (role, parents) {
+ contract(arguments).params("string", "string|array").end();
- var transaction = this.backend.begin();
- this.backend.add(transaction, this.options.buckets.meta, "roles", role);
- this.backend.add(transaction, this.options.buckets.parents, role, parents);
- return this.backend.endAsync(transaction).nodeify(cb);
+ const transaction = await this.backend.begin();
+ await this.backend.add(transaction, this.options.buckets.meta, "roles", role);
+ await this.backend.add(transaction, this.options.buckets.parents, role, parents);
+ return await this.backend.end(transaction);
};
/**
- removeRoleParents( role, parents, function(err) )
+ removeRoleParents( role, parents )
Removes a parent or parent list from role.
If `parents` is not specified, removes all parents.
- @param {String} Child role.
- @param {String|Array} Parent role(s) to be removed [optional].
- @param {Function} Callback called when finished [optional].
+ @param {String} role Child role.
+ @param {String|Array} parents Parent role(s) to be removed [optional].
@return {Promise} Promise resolved when finished.
*/
-Acl.prototype.removeRoleParents = function (role, parents, cb) {
- contract(arguments)
- .params("string", "string|array", "function")
- .params("string", "string|array")
- .params("string", "function")
- .params("string")
- .end();
-
- if (!cb && _.isFunction(parents)) {
- cb = parents;
- parents = null;
- }
+Acl.prototype.removeRoleParents = async function (role, parents) {
+ contract(arguments).params("string", "string|array").params("string").end();
- var transaction = this.backend.begin();
+ const transaction = await this.backend.begin();
if (parents) {
- this.backend.remove(transaction, this.options.buckets.parents, role, parents);
+ await this.backend.remove(transaction, this.options.buckets.parents, role, parents);
} else {
- this.backend.del(transaction, this.options.buckets.parents, role);
+ await this.backend.del(transaction, this.options.buckets.parents, role);
}
- return this.backend.endAsync(transaction).nodeify(cb);
+ return await this.backend.end(transaction);
};
/**
- removeRole( role, function(err) )
+ removeRole( role )
Removes a role from the system.
- @param {String} Role to be removed
- @param {Function} Callback called when finished.
+ @param {String} role Role to be removed
*/
-Acl.prototype.removeRole = function (role, cb) {
- contract(arguments).params("string", "function").params("string").end();
+Acl.prototype.removeRole = async function (role) {
+ contract(arguments).params("string").end();
// Note that this is not fully transactional.
- return this.backend
- .getAsync(this.options.buckets.resources, role)
- .then((resources) => {
- var transaction = this.backend.begin();
-
- for (const resource of resources) {
- var bucket = allowsBucket(resource);
- this.backend.del(transaction, bucket, role);
- }
-
- this.backend.del(transaction, this.options.buckets.resources, role);
- this.backend.del(transaction, this.options.buckets.parents, role);
- this.backend.del(transaction, this.options.buckets.roles, role);
- this.backend.remove(transaction, this.options.buckets.meta, "roles", role);
-
- // `users` collection keeps the removed role
- // because we don't know what users have `role` assigned.
- return this.backend.endAsync(transaction);
- })
- .nodeify(cb);
+ let resources = await this.backend.get(this.options.buckets.resources, role);
+ const transaction = await this.backend.begin();
+ for (const resource of resources) {
+ const bucket = allowsBucket(resource);
+ await this.backend.del(transaction, bucket, role);
+ }
+ await this.backend.del(transaction, this.options.buckets.resources, role);
+ await this.backend.del(transaction, this.options.buckets.parents, role);
+ await this.backend.del(transaction, this.options.buckets.roles, role);
+ await this.backend.remove(transaction, this.options.buckets.meta, "roles", role);
+ return await this.backend.end(transaction);
};
/**
- removeResource( resource, function(err) )
+ removeResource( resource )
Removes a resource from the system
- @param {String} Resource to be removed
- @param {Function} Callback called when finished.
+ @param {String} resource Resource to be removed
@return {Promise} Promise resolved when finished
*/
-Acl.prototype.removeResource = function (resource, cb) {
- contract(arguments).params("string", "function").params("string").end();
-
- return this.backend
- .getAsync(this.options.buckets.meta, "roles")
- .then((roles) => {
- var transaction = this.backend.begin();
- this.backend.del(transaction, allowsBucket(resource), roles);
- for (const role of roles) {
- this.backend.remove(transaction, this.options.buckets.resources, role, resource);
- }
- return this.backend.endAsync(transaction);
- })
- .nodeify(cb);
+Acl.prototype.removeResource = async function (resource) {
+ contract(arguments).params("string").end();
+
+ let roles = await this.backend.get(this.options.buckets.meta, "roles");
+ const transaction = await this.backend.begin();
+ await this.backend.del(transaction, allowsBucket(resource), roles);
+ for (const role of roles) {
+ await this.backend.remove(transaction, this.options.buckets.resources, role, resource);
+ }
+ return await this.backend.end(transaction);
};
/**
- allow( roles, resources, permissions, function(err) )
+ allow( roles, resources, permissions )
Adds the given permissions to the given roles over the given resources.
- @param {String|Array} role(s) to add permissions to.
- @param {String|Array} resource(s) to add permisisons to.
- @param {String|Array} permission(s) to add to the roles over the resources.
- @param {Function} Callback called when finished.
+ @param {String|Array} roles role(s) to add permissions to.
+ @param {String|Array} resources resource(s) to add permisisons to.
+ @param {String|Array} permissions permission(s) to add to the roles over the resources.
- allow( permissionsArray, function(err) )
+ allow( permissionsArray )
- @param {Array} Array with objects expressing what permissions to give.
+ @param {Array} roles Array with objects expressing what permissions to give.
[{roles:{String|Array}, allows:[{resources:{String|Array}, permissions:{String|Array}]]
- @param {Function} Callback called when finished.
@return {Promise} Promise resolved when finished
*/
-Acl.prototype.allow = function (roles, resources, permissions, cb) {
- contract(arguments)
- .params("string|array", "string|array", "string|array", "function")
- .params("string|array", "string|array", "string|array")
- .params("array", "function")
- .params("array")
- .end();
+Acl.prototype.allow = async function (roles, resources, permissions) {
+ contract(arguments).params("string|array", "string|array", "string|array").params("array").end();
- if (arguments.length === 1 || (arguments.length === 2 && _.isObject(roles) && _.isFunction(resources))) {
- return this._allowEx(roles).nodeify(resources);
+ if (arguments.length === 1 || (arguments.length === 2 && _.isObject(roles))) {
+ return await this._allowEx(roles);
} else {
roles = makeArray(roles);
resources = makeArray(resources);
- var transaction = this.backend.begin();
+ const transaction = await this.backend.begin();
- this.backend.add(transaction, this.options.buckets.meta, "roles", roles);
+ await this.backend.add(transaction, this.options.buckets.meta, "roles", roles);
for (const resource of resources) {
for (const role of roles) {
- this.backend.add(transaction, allowsBucket(resource), role, permissions);
+ await this.backend.add(transaction, allowsBucket(resource), role, permissions);
}
}
for (const role of roles) {
- this.backend.add(transaction, this.options.buckets.resources, role, resources);
+ await this.backend.add(transaction, this.options.buckets.resources, role, resources);
}
- return this.backend.endAsync(transaction).nodeify(cb);
+ return await this.backend.end(transaction);
}
};
-Acl.prototype.removeAllow = function (role, resources, permissions, cb) {
- contract(arguments)
- .params("string", "string|array", "string|array", "function")
- .params("string", "string|array", "string|array")
- .params("string", "string|array", "function")
- .params("string", "string|array")
- .end();
+Acl.prototype.removeAllow = function (role, resources, permissions) {
+ contract(arguments).params("string", "string|array", "string|array").params("string", "string|array").end();
resources = makeArray(resources);
- if (cb || (permissions && !_.isFunction(permissions))) {
+ if (permissions) {
permissions = makeArray(permissions);
- } else {
- cb = permissions;
- permissions = null;
}
- return this.removePermissions(role, resources, permissions, cb);
+ return this.removePermissions(role, resources, permissions);
};
/**
@@ -363,46 +294,41 @@ Acl.prototype.removeAllow = function (role, resources, permissions, cb) {
Note: we loose atomicity when removing empty role_resources.
- @param {String}
- @param {String|Array}
- @param {String|Array}
+ @param {String} role
+ @param {String|Array} resources
+ @param {String|Array} permissions
*/
-Acl.prototype.removePermissions = function (role, resources, permissions, cb) {
- var transaction = this.backend.begin();
+Acl.prototype.removePermissions = async function (role, resources, permissions) {
+ const transaction = await this.backend.begin();
for (const resource of resources) {
- var bucket = allowsBucket(resource);
+ const bucket = allowsBucket(resource);
if (permissions) {
- this.backend.remove(transaction, bucket, role, permissions);
+ await this.backend.remove(transaction, bucket, role, permissions);
} else {
- this.backend.del(transaction, bucket, role);
- this.backend.remove(transaction, this.options.buckets.resources, role, resource);
+ await this.backend.del(transaction, bucket, role);
+ await this.backend.remove(transaction, this.options.buckets.resources, role, resource);
}
}
// Remove resource from role if no rights for that role exists.
// Not fully atomic...
- return this.backend
- .endAsync(transaction)
- .then(() => {
- var transaction = this.backend.begin();
- return bluebird
- .all(
- resources.map((resource) => {
- var bucket = allowsBucket(resource);
- return this.backend.getAsync(bucket, role).then((permissions) => {
- if (permissions.length == 0) {
- this.backend.remove(transaction, this.options.buckets.resources, role, resource);
- }
- });
- })
- )
- .then(() => this.backend.endAsync(transaction));
+ await this.backend.end(transaction);
+
+ const transaction2 = await this.backend.begin();
+ await Promise.all(
+ resources.map(async (resource) => {
+ const bucket = allowsBucket(resource);
+ let permissions1 = await this.backend.get(bucket, role);
+ if (permissions1.length === 0) {
+ await this.backend.remove(transaction2, this.options.buckets.resources, role, resource);
+ }
})
- .nodeify(cb);
+ );
+ return await this.backend.end(transaction2);
};
/**
- allowedPermissions( userId, resources, function(err, obj) )
+ allowedPermissions( userId, resources ) : obj
Returns all the allowable permissions a given user have to
access the given resources.
@@ -410,42 +336,32 @@ Acl.prototype.removePermissions = function (role, resources, permissions, cb) {
It returns an array of objects where every object maps a
resource name to a list of permissions for that resource.
- @param {String|Number} User id.
- @param {String|Array} resource(s) to ask permissions for.
- @param {Function} Callback called when finished.
+ @param {String} userId
+ @param {String|Array} resources resource(s) to ask permissions for.
*/
-Acl.prototype.allowedPermissions = function (userId, resources, cb) {
- if (!userId) return cb(null, {});
+Acl.prototype.allowedPermissions = async function (userId, resources) {
+ if (!userId) return {};
- contract(arguments)
- .params("string|number", "string|array", "function")
- .params("string|number", "string|array")
- .end();
+ contract(arguments).params("string", "string|array").end();
- if (this.backend.unionsAsync) {
- return this.optimizedAllowedPermissions(userId, resources, cb);
+ if (this.backend.unions) {
+ return this.optimizedAllowedPermissions(userId, resources);
}
resources = makeArray(resources);
- return this.userRoles(userId)
- .then((roles) => {
- var result = {};
- return bluebird
- .all(
- resources.map((resource) =>
- this._resourcePermissions(roles, resource).then((permissions) => {
- result[resource] = permissions;
- })
- )
- )
- .then(() => result);
+ const roles = await this.userRoles(userId);
+ const result = {};
+ await Promise.all(
+ resources.map(async (resource) => {
+ result[resource] = await this._resourcePermissions(roles, resource);
})
- .nodeify(cb);
+ );
+ return result;
};
/**
- optimizedAllowedPermissions( userId, resources, function(err, obj) )
+ optimizedAllowedPermissions( userId, resources ): obj
Returns all the allowable permissions a given user have to
access the given resources.
@@ -455,182 +371,122 @@ Acl.prototype.allowedPermissions = function (userId, resources, cb) {
This is the same as allowedPermissions, it just takes advantage of the unions
function if available to reduce the number of backend queries.
- @param {String|Number} User id.
- @param {String|Array} resource(s) to ask permissions for.
- @param {Function} Callback called when finished.
+ @param {String} userId
+ @param {String|Array} resources resource(s) to ask permissions for.
*/
-Acl.prototype.optimizedAllowedPermissions = function (userId, resources, cb) {
- if (!userId) {
- return cb(null, {});
- }
+Acl.prototype.optimizedAllowedPermissions = async function (userId, resources) {
+ if (!userId) return {};
- contract(arguments)
- .params("string|number", "string|array", "function|undefined")
- .params("string|number", "string|array")
- .end();
+ contract(arguments).params("string", "string|array").end();
resources = makeArray(resources);
+ let response;
+ const roles = await this._allUserRoles(userId);
+ const buckets = resources.map(allowsBucket);
+ if (roles.length === 0) {
+ const emptyResult = {};
+ for (const bucket of buckets) {
+ emptyResult[bucket] = [];
+ }
+ response = emptyResult;
+ } else {
+ response = await this.backend.unions(buckets, roles);
+ }
- return this._allUserRoles(userId)
- .then((roles) => {
- var buckets = resources.map(allowsBucket);
- if (roles.length === 0) {
- var emptyResult = {};
- for (const bucket of buckets) {
- emptyResult[bucket] = [];
- }
- return bluebird.resolve(emptyResult);
- }
-
- return this.backend.unionsAsync(buckets, roles);
- })
- .then((response) => {
- var result = {};
- for (const bucket of Object.keys(response)) {
- result[keyFromAllowsBucket(bucket)] = response[bucket];
- }
+ const result = {};
+ for (const bucket of Object.keys(response)) {
+ result[keyFromAllowsBucket(bucket)] = response[bucket];
+ }
- return result;
- })
- .nodeify(cb);
+ return result;
};
/**
- isAllowed( userId, resource, permissions, function(err, allowed) )
+ isAllowed( userId, resource, permissions )
Checks if the given user is allowed to access the resource for the given
permissions (note: it must fulfill all the permissions).
- @param {String|Number} User id.
- @param {String|Array} resource(s) to ask permissions for.
- @param {String|Array} asked permissions.
- @param {Function} Callback called wish the result.
+ @param {String} userId
+ @param {String|Array} resource resource(s) to ask permissions for.
+ @param {String|Array} permissions asked permissions.
*/
-Acl.prototype.isAllowed = function (userId, resource, permissions, cb) {
- contract(arguments)
- .params("string|number", "string", "string|array", "function")
- .params("string|number", "string", "string|array")
- .end();
+Acl.prototype.isAllowed = async function (userId, resource, permissions) {
+ contract(arguments).params("string", "string", "string|array").end();
- return this.backend
- .getAsync(this.options.buckets.users, userId)
- .then((roles) => {
- if (roles.length) {
- return this.areAnyRolesAllowed(roles, resource, permissions);
- } else {
- return false;
- }
- })
- .nodeify(cb);
+ let roles = await this.backend.get(this.options.buckets.users, userId);
+ if (roles.length) {
+ return this.areAnyRolesAllowed(roles, resource, permissions);
+ } else {
+ return false;
+ }
};
/**
- areAnyRolesAllowed( roles, resource, permissions, function(err, allowed) )
+ areAnyRolesAllowed( roles, resource, permissions ) : allowed
Returns true if any of the given roles have the right permissions.
- @param {String|Array} Role(s) to check the permissions for.
- @param {String} resource(s) to ask permissions for.
- @param {String|Array} asked permissions.
- @param {Function} Callback called with the result.
+ @param {String|Array} roles to check the permissions for.
+ @param {String} resource resource(s) to ask permissions for.
+ @param {String|Array} permissions asked permissions.
*/
-Acl.prototype.areAnyRolesAllowed = function (roles, resource, permissions, cb) {
- contract(arguments)
- .params("string|array", "string", "string|array", "function")
- .params("string|array", "string", "string|array")
- .end();
+Acl.prototype.areAnyRolesAllowed = async function (roles, resource, permissions) {
+ contract(arguments).params("string|array", "string", "string|array").end();
roles = makeArray(roles);
permissions = makeArray(permissions);
if (roles.length === 0) {
- return bluebird.resolve(false).nodeify(cb);
+ return false;
} else {
- return this._checkPermissions(roles, resource, permissions).nodeify(cb);
+ return await this._checkPermissions(roles, resource, permissions);
}
};
/**
- whatResources(role, function(err, {resourceName: [permissions]})
+ whatResources(role) : {resourceName: [permissions]}
Returns what resources a given role or roles have permissions over.
- whatResources(role, permissions, function(err, resources) )
+ whatResources(role, permissions) : resources
Returns what resources a role has the given permissions over.
- @param {String|Array} Roles
- @param {String|Array} Permissions
- @param {Function} Callback called wish the result.
+ @param {String|Array} roles
+ @param {String|Array} permissions
*/
-Acl.prototype.whatResources = function (roles, permissions, cb) {
- contract(arguments)
- .params("string|array")
- .params("string|array", "string|array")
- .params("string|array", "function")
- .params("string|array", "string|array", "function")
- .end();
+Acl.prototype.whatResources = function (roles, permissions) {
+ contract(arguments).params("string|array").params("string|array", "string|array").end();
roles = makeArray(roles);
- if (_.isFunction(permissions)) {
- cb = permissions;
- permissions = undefined;
- } else if (permissions) {
- permissions = makeArray(permissions);
- }
-
- return this.permittedResources(roles, permissions, cb);
-};
+ permissions = !permissions ? undefined : makeArray(permissions);
-Acl.prototype.permittedResources = function (roles, permissions, cb) {
- var result = _.isUndefined(permissions) ? {} : [];
- return this._rolesResources(roles)
- .then((resources) =>
- bluebird
- .all(
- resources.map((resource) =>
- this._resourcePermissions(roles, resource).then((p) => {
- if (permissions) {
- var commonPermissions = _.intersection(permissions, p);
- if (commonPermissions.length > 0) {
- result.push(resource);
- }
- } else {
- result[resource] = p;
- }
- })
- )
- )
- .then(() => result)
- )
- .nodeify(cb);
+ return this.permittedResources(roles, permissions);
};
-/**
- clean ()
-
- Cleans all the keys with the given prefix from redis.
+Acl.prototype.permittedResources = async function (roles, permissions) {
+ const result = _.isUndefined(permissions) ? {} : [];
+ let resources = await this._rolesResources(roles);
+ await Promise.all(
+ resources.map(async (resource) => {
+ let p = await this._resourcePermissions(roles, resource);
+ if (permissions) {
+ const commonPermissions = _.intersection(permissions, p);
+ if (commonPermissions.length > 0) {
+ result.push(resource);
+ }
+ } else {
+ result[resource] = p;
+ }
+ })
+ );
- Note: this operation is not reversible!.
-*/
-/*
-Acl.prototype.clean = function(callback){
- var acl = this;
- this.redis.keys(this.prefix+'*', function(err, keys){
- if(keys.length){
- acl.redis.del(keys, function(err){
- callback(err);
- });
- }else{
- callback();
- }
- });
+ return result;
};
-*/
/**
Express Middleware
-
*/
Acl.prototype.middleware = function (numPathComponents, userId, actions) {
contract(arguments)
@@ -640,7 +496,7 @@ Acl.prototype.middleware = function (numPathComponents, userId, actions) {
.params("number", "string|number|function", "string|array")
.end();
- var acl = this;
+ const acl = this;
function HttpError(errorCode, msg) {
this.errorCode = errorCode;
@@ -652,7 +508,7 @@ Acl.prototype.middleware = function (numPathComponents, userId, actions) {
}
return function (req, res, next) {
- var _userId = userId,
+ let _userId = userId,
_actions = actions,
resource,
url;
@@ -694,22 +550,23 @@ Acl.prototype.middleware = function (numPathComponents, userId, actions) {
acl.logger ? acl.logger.debug("Requesting " + _actions + " on " + resource + " by user " + _userId) : null;
- acl.isAllowed(_userId, resource, _actions, (err, allowed) => {
- if (err) {
- next(new Error("Error checking permissions to access resource"));
- } else if (allowed === false) {
- if (acl.logger) {
- acl.logger.debug("Not allowed " + _actions + " on " + resource + " by user " + _userId);
- acl.allowedPermissions(_userId, resource, (err, obj) => {
+ acl.isAllowed(_userId, resource, _actions)
+ .then(async (allowed) => {
+ if (allowed === false) {
+ if (acl.logger) {
+ acl.logger.debug("Not allowed " + _actions + " on " + resource + " by user " + _userId);
+ const obj = acl.allowedPermissions(_userId, resource);
acl.logger.debug("Allowed permissions: " + util.inspect(obj));
- });
+ }
+ next(new HttpError(403, "Insufficient permissions to access resource"));
+ } else {
+ acl.logger
+ ? acl.logger.debug("Allowed " + _actions + " on " + resource + " by user " + _userId)
+ : null;
+ next();
}
- next(new HttpError(403, "Insufficient permissions to access resource"));
- } else {
- acl.logger ? acl.logger.debug("Allowed " + _actions + " on " + resource + " by user " + _userId) : null;
- next();
- }
- });
+ })
+ .catch(() => next(new Error("Error checking permissions to access resource")));
};
};
@@ -719,7 +576,7 @@ Acl.prototype.middleware = function (numPathComponents, userId, actions) {
@param {String} [contentType] (html|json) defaults to plain text
*/
Acl.prototype.middleware.errorHandler = function (contentType) {
- var method = "end";
+ let method = "end";
if (contentType) {
switch (contentType) {
@@ -750,9 +607,9 @@ Acl.prototype.middleware.errorHandler = function (contentType) {
Acl.prototype._allowEx = function (objs) {
objs = makeArray(objs);
- var demuxed = [];
+ const demuxed = [];
for (const obj of objs) {
- var roles = obj.roles;
+ const roles = obj.roles;
for (const allow of obj.allows) {
demuxed.push({
roles: roles,
@@ -762,137 +619,98 @@ Acl.prototype._allowEx = function (objs) {
}
}
- return bluebird.reduce(demuxed, (values, obj) => this.allow(obj.roles, obj.resources, obj.permissions), null);
+ return Promise.all(demuxed.map((obj) => this.allow(obj.roles, obj.resources, obj.permissions)));
};
//
// Returns the parents of the given roles
//
Acl.prototype._rolesParents = function (roles) {
- return this.backend.unionAsync(this.options.buckets.parents, roles);
+ return this.backend.union(this.options.buckets.parents, roles);
};
//
// Return all roles in the hierarchy including the given roles.
//
-/*
-Acl.prototype._allRoles = function(roleNames, cb){
- var _this = this, roles;
-
- _this._rolesParents(roleNames, function(err, parents){
- roles = _.union(roleNames, parents);
- async.whilst(
- function (){
- return parents.length >0;
- },
- function (cb) {
- _this._rolesParents(parents, function(err, result){
- if(!err){
- roles = _.union(roles, parents);
- parents = result;
- }
- cb(err);
- });
- },
- function(err){
- cb(err, roles);
- }
- );
- });
-};
-*/
-//
-// Return all roles in the hierarchy including the given roles.
-//
-Acl.prototype._allRoles = function (roleNames) {
- return this._rolesParents(roleNames).then((parents) => {
- if (parents.length > 0) {
- return this._allRoles(parents).then((parentRoles) => _.union(roleNames, parentRoles));
- } else {
- return roleNames;
- }
- });
+Acl.prototype._allRoles = async function (roleNames) {
+ let parents = await this._rolesParents(roleNames);
+ if (parents.length > 0) {
+ let parentRoles = await this._allRoles(parents);
+ return _.union(roleNames, parentRoles);
+ }
+
+ return roleNames;
};
//
// Return all roles in the hierarchy of the given user.
//
-Acl.prototype._allUserRoles = function (userId) {
- return this.userRoles(userId).then((roles) => {
- if (roles && roles.length > 0) {
- return this._allRoles(roles);
- } else {
- return [];
- }
- });
+Acl.prototype._allUserRoles = async function (userId) {
+ let roles = await this.userRoles(userId);
+ if (roles && roles.length > 0) {
+ return this._allRoles(roles);
+ }
+
+ return [];
};
//
// Returns an array with resources for the given roles.
//
-Acl.prototype._rolesResources = function (roles) {
+Acl.prototype._rolesResources = async function (roles) {
roles = makeArray(roles);
- return this._allRoles(roles).then((allRoles) => {
- var result = [];
-
- // check if bluebird.map simplifies this code
- return bluebird
- .all(
- allRoles.map((role) =>
- this.backend.getAsync(this.options.buckets.resources, role).then((resources) => {
- result = result.concat(resources);
- })
- )
- )
- .then(() => result);
- });
+ let allRoles = await this._allRoles(roles);
+ let result = [];
+ await Promise.all(
+ allRoles.map((role) =>
+ this.backend.get(this.options.buckets.resources, role).then((resources) => {
+ result = result.concat(resources);
+ })
+ )
+ );
+ return result;
};
//
// Returns the permissions for the given resource and set of roles
//
-Acl.prototype._resourcePermissions = function (roles, resource) {
+Acl.prototype._resourcePermissions = async function (roles, resource) {
if (roles.length === 0) {
- return bluebird.resolve([]);
- } else {
- return this.backend.unionAsync(allowsBucket(resource), roles).then((resourcePermissions) =>
- this._rolesParents(roles).then((parents) => {
- if (parents && parents.length) {
- return this._resourcePermissions(parents, resource).then((morePermissions) =>
- _.union(resourcePermissions, morePermissions)
- );
- } else {
- return resourcePermissions;
- }
- })
- );
+ return [];
}
+
+ const resourcePermissions = await this.backend.union(allowsBucket(resource), roles);
+
+ const parents = await this._rolesParents(roles);
+ if (parents && parents.length) {
+ const morePermissions = await this._resourcePermissions(parents, resource);
+ return _.union(resourcePermissions, morePermissions);
+ }
+
+ return resourcePermissions;
};
//
// NOTE: This function will not handle circular dependencies and result in a crash.
//
-Acl.prototype._checkPermissions = function (roles, resource, permissions) {
- return this.backend.unionAsync(allowsBucket(resource), roles).then((resourcePermissions) => {
- if (resourcePermissions.indexOf("*") !== -1) {
- return true;
- } else {
- permissions = permissions.filter((p) => resourcePermissions.indexOf(p) === -1);
+Acl.prototype._checkPermissions = async function (roles, resource, permissions) {
+ let resourcePermissions = await this.backend.union(allowsBucket(resource), roles);
+ if (resourcePermissions.indexOf("*") !== -1) {
+ return true;
+ }
- if (permissions.length === 0) {
- return true;
- } else {
- return this.backend.unionAsync(this.options.buckets.parents, roles).then((parents) => {
- if (parents && parents.length) {
- return this._checkPermissions(parents, resource, permissions);
- } else {
- return false;
- }
- });
- }
- }
- });
+ permissions = permissions.filter((p) => resourcePermissions.indexOf(p) === -1);
+ if (permissions.length === 0) {
+ return true;
+ }
+
+ let parents = await this.backend.union(this.options.buckets.parents, roles);
+ if (parents && parents.length) {
+ return await this._checkPermissions(parents, resource, permissions);
+ }
+
+ return false;
};
//-----------------------------------------------------------------------------
diff --git a/lib/backend.js b/lib/backend.js
index 25674d4..e6740ad 100644
--- a/lib/backend.js
+++ b/lib/backend.js
@@ -6,72 +6,69 @@
Implement this API for providing a backend for the acl module.
*/
-var contract = require("./contract");
+const contract = require("./contract");
-var Backend = {
+const Backend = {
/**
Begins a transaction.
*/
- begin() {
+ async begin() {
// returns a transaction object
},
/**
Ends a transaction (and executes it)
*/
- end(transaction, cb) {
- contract(arguments).params("object", "function").end();
+ async end(transaction) {
// Execute transaction
},
/**
Cleans the whole storage.
*/
- clean(cb) {
- contract(arguments).params("function").end();
- },
+ async clean() {},
/**
Gets the contents at the bucket's key.
*/
- get(bucket, key, cb) {
- contract(arguments).params("string", "string|number", "function").end();
+ async get(bucket, key) {
+ contract(arguments).params("string", "string").end();
},
/**
Gets the union of contents of the specified keys in each of the specified buckets and returns
a mapping of bucket to union.
*/
- unions(bucket, keys, cb) {
- contract(arguments).params("array", "array", "function").end();
+ async unions(bucket, keys) {
+ contract(arguments).params("array", "array").end();
},
/**
Returns the union of the values in the given keys.
*/
- union(bucket, keys, cb) {
- contract(arguments).params("string", "array", "function").end();
+ async union(bucket, keys) {
+ contract(arguments).params("string", "array").end();
},
/**
Adds values to a given key inside a bucket.
*/
- add(transaction, bucket, key, values) {
- contract(arguments).params("object", "string", "string|number", "string|array|number").end();
+ async add(transaction, bucket, key, values) {
+ contract(arguments).params("object", "string", "string", "string|array").end();
},
/**
Delete the given key(s) at the bucket
*/
- del(transaction, bucket, keys) {
+ async del(transaction, bucket, keys) {
contract(arguments).params("object", "string", "string|array").end();
},
/**
Removes values from a given key inside a bucket.
*/
- remove(transaction, bucket, key, values) {
- contract(arguments).params("object", "string", "string|number", "string|array|number").end();
+ async remove(transaction, bucket, key, values) {
+ contract(arguments).params("object", "string", "string", "string|array`").end();
},
};
diff --git a/lib/contract.js b/lib/contract.js
index 7b74a6d..f6a6439 100644
--- a/lib/contract.js
+++ b/lib/contract.js
@@ -1,4 +1,4 @@
-/**
+/*
Design by Contract module (c) OptimalBits 2011.
Roadmap:
@@ -13,17 +13,16 @@
.end()
*/
-"use strict";
-var noop = {};
-var _ = require("lodash");
+const noop = {};
+const _ = require("lodash");
noop.params = function () {
return this;
};
noop.end = function () {};
-var contract = function (args) {
+const contract = function (args) {
if (contract.debug === true) {
contract.fulfilled = false;
contract.args = _.toArray(args);
@@ -50,12 +49,12 @@ contract.end = function () {
}
};
-var typeOf = function (obj) {
+const typeOf = function (obj) {
return Array.isArray(obj) ? "array" : typeof obj;
};
-var checkParams = function (args, contract) {
- var fulfilled, types, type, i, j;
+const checkParams = function (args, contract) {
+ let fulfilled, types, type, i, j;
if (args.length !== contract.length) {
return false;
@@ -84,13 +83,13 @@ var checkParams = function (args, contract) {
}
};
-var printParamsError = function (args, checkedParams) {
- var msg = "Parameter mismatch.\nInput:\n( ",
+const printParamsError = function (args, checkedParams) {
+ let msg = "Parameter mismatch.\nInput:\n( ",
type,
i;
_.each(args, function (input, key) {
type = typeOf(input);
- if (key != 0) {
+ if (key !== 0) {
msg += ", ";
}
msg += input + ": " + type;
@@ -105,10 +104,10 @@ var printParamsError = function (args, checkedParams) {
console.log(msg);
};
-var argsToString = function (args) {
- var res = "";
+const argsToString = function (args) {
+ let res = "";
_.each(args, function (arg, key) {
- if (key != 0) {
+ if (key !== 0) {
res += ", ";
}
res += arg;
diff --git a/lib/memory-backend.js b/lib/memory-backend.js
index bb83839..e1109e4 100644
--- a/lib/memory-backend.js
+++ b/lib/memory-backend.js
@@ -1,11 +1,10 @@
-/**
+/*
Memory Backend.
In-memory implementation of the storage.
*/
-"use strict";
-var contract = require("./contract"),
+const contract = require("./contract"),
_ = require("lodash");
function MemoryBackend() {
@@ -13,9 +12,7 @@ function MemoryBackend() {
}
MemoryBackend.prototype = {
- close(cb) {
- cb();
- },
+ async close() {},
/**
Begins a transaction.
@@ -28,45 +25,40 @@ MemoryBackend.prototype = {
/**
Ends a transaction (and executes it)
*/
- end(transaction, cb) {
- contract(arguments).params("array", "function").end();
-
+ async end(transaction) {
// Execute transaction
- for (var i = 0, len = transaction.length; i < len; i++) {
- transaction[i]();
+ for (let i = 0, len = transaction.length; i < len; i++) {
+ await transaction[i]();
}
- cb();
},
/**
Cleans the whole storage.
*/
- clean(cb) {
- contract(arguments).params("function").end();
+ async clean() {
this._buckets = {};
- cb();
},
/**
Gets the contents at the bucket's key.
*/
- get(bucket, key, cb) {
- contract(arguments).params("string", "string|number", "function").end();
+ async get(bucket, key) {
+ contract(arguments).params("string", "string").end();
if (this._buckets[bucket]) {
- cb(null, this._buckets[bucket][key] || []);
+ return this._buckets[bucket][key] || [];
} else {
- cb(null, []);
+ return [];
}
},
/**
Gets the union of the keys in each of the specified buckets
*/
- unions(buckets, keys, cb) {
- contract(arguments).params("array", "array", "function").end();
+ async unions(buckets, keys) {
+ contract(arguments).params("array", "array").end();
- var results = {};
+ const results = {};
for (const bucket of buckets) {
if (this._buckets[bucket]) {
@@ -76,17 +68,16 @@ MemoryBackend.prototype = {
}
}
- cb(null, results);
+ return results;
},
/**
Returns the union of the values in the given keys.
*/
- union(bucket, keys, cb) {
- contract(arguments).params("string", "array", "function").end();
+ async union(bucket, keys) {
+ contract(arguments).params("string", "array").end();
- var match;
- var re;
+ let match, re;
if (!this._buckets[bucket]) {
Object.keys(this._buckets).some(function (b) {
re = new RegExp("^" + b + "$");
@@ -97,15 +88,15 @@ MemoryBackend.prototype = {
}
if (this._buckets[bucket]) {
- var keyArrays = [];
- for (var i = 0, len = keys.length; i < len; i++) {
+ const keyArrays = [];
+ for (let i = 0, len = keys.length; i < len; i++) {
if (this._buckets[bucket][keys[i]]) {
keyArrays.push.apply(keyArrays, this._buckets[bucket][keys[i]]);
}
}
- cb(undefined, _.union(keyArrays));
+ return _.union(keyArrays);
} else {
- cb(undefined, []);
+ return [];
}
},
@@ -113,7 +104,7 @@ MemoryBackend.prototype = {
Adds values to a given key inside a bucket.
*/
add(transaction, bucket, key, values) {
- contract(arguments).params("array", "string", "string|number", "string|array|number").end();
+ contract(arguments).params("array", "string", "string", "string|array").end();
values = makeArray(values);
@@ -139,7 +130,7 @@ MemoryBackend.prototype = {
transaction.push(() => {
if (this._buckets[bucket]) {
- for (var i = 0, len = keys.length; i < len; i++) {
+ for (let i = 0, len = keys.length; i < len; i++) {
delete this._buckets[bucket][keys[i]];
}
}
@@ -150,12 +141,12 @@ MemoryBackend.prototype = {
Removes values from a given key inside a bucket.
*/
remove(transaction, bucket, key, values) {
- contract(arguments).params("array", "string", "string|number", "string|array|number").end();
+ contract(arguments).params("array", "string", "string", "string|array").end();
values = makeArray(values);
transaction.push(() => {
- var old;
- if (this._buckets[bucket] && (old = this._buckets[bucket][key])) {
+ if (this._buckets[bucket] && this._buckets[bucket][key]) {
+ let old = this._buckets[bucket][key];
this._buckets[bucket][key] = _.difference(old, values);
}
});
diff --git a/lib/mongodb-backend.js b/lib/mongodb-backend.js
index 5440dda..2d43eb5 100644
--- a/lib/mongodb-backend.js
+++ b/lib/mongodb-backend.js
@@ -1,16 +1,14 @@
-/**
+/*
MongoDB Backend.
Implementation of the storage backend using MongoDB
*/
-"use strict";
-var contract = require("./contract");
-var async = require("async");
-var _ = require("lodash");
+const contract = require("./contract");
+const _ = require("lodash");
// Name of the collection where meta and allowsXXX are stored.
// If prefix is specified, it will be prepended to this name, like acl_resources
-var aclCollectionName = "resources";
+const aclCollectionName = "resources";
function MongoDBBackend({ client, db, prefix, useSingle, useRawCollectionNames }) {
this.client = client;
@@ -21,15 +19,14 @@ function MongoDBBackend({ client, db, prefix, useSingle, useRawCollectionNames }
}
MongoDBBackend.prototype = {
- close(cb) {
- if (this.client) this.client.close(cb);
- else cb();
+ async close() {
+ if (this.client) await this.client.close();
},
/**
Begins a transaction.
*/
- begin() {
+ async begin() {
// returns a transaction object(just an array of functions will do here.)
return [];
},
@@ -37,173 +34,142 @@ MongoDBBackend.prototype = {
/**
Ends a transaction (and executes it)
*/
- end(transaction, cb) {
- contract(arguments).params("array", "function").end();
- async.series(transaction, function (err) {
- cb(err instanceof Error ? err : undefined);
- });
+ async end(transaction) {
+ const promises = transaction.map((fn) => fn());
+ await Promise.all(promises);
},
/**
Cleans the whole storage.
*/
- clean(cb) {
- contract(arguments).params("function").end();
- this.db.collections(function (err, collections) {
- if (err instanceof Error) return cb(err);
- async.forEach(
- collections,
- function (coll, innercb) {
- coll.drop(function () {
- innercb();
- }); // ignores errors
- },
- cb
- );
- });
+ async clean() {
+ const collections = await this.db.collections();
+ const promises = collections.map((coll) => coll.drop());
+ await Promise.all(promises);
},
/**
Gets the contents at the bucket's key.
*/
- get(bucket, key, cb) {
- contract(arguments).params("string", "string|number", "function").end();
+ async get(bucket, key) {
key = encodeText(key);
- var searchParams = this.useSingle ? { _bucketname: bucket, key: key } : { key: key };
- var collName = this.useSingle ? aclCollectionName : bucket;
+ const searchParams = this.useSingle ? { _bucketname: bucket, key: key } : { key: key };
+ const collName = this.useSingle ? aclCollectionName : bucket;
let collection = this.db.collection(this.prefix + this.removeUnsupportedChar(collName));
- if (!collection) return cb(new Error(`Cannot find the collection ${collName}`));
+ if (!collection) throw new Error(`Cannot find the collection ${collName}`);
// Excluding bucket field from search result
- collection.findOne(searchParams, { projection: { _bucketname: 0 } }, function (err, doc) {
- if (err) return cb(err);
- if (!_.isObject(doc)) return cb(undefined, []);
- doc = fixKeys(doc);
- cb(undefined, _.without(_.keys(doc), "key", "_id", "_bucketname"));
- });
+ let doc = await collection.findOne(searchParams, { projection: { _bucketname: 0 } });
+ if (!_.isObject(doc)) return [];
+ doc = fixKeys(doc);
+ return _.without(_.keys(doc), "key", "_id", "_bucketname");
},
/**
Returns the union of the values in the given keys.
*/
- union(bucket, keys, cb) {
- contract(arguments).params("string", "array", "function").end();
+ async union(bucket, keys) {
+ contract(arguments).params("string", "array").end();
+
keys = encodeAll(keys);
- var searchParams = this.useSingle ? { _bucketname: bucket, key: { $in: keys } } : { key: { $in: keys } };
- var collName = this.useSingle ? aclCollectionName : bucket;
+ const searchParams = this.useSingle ? { _bucketname: bucket, key: { $in: keys } } : { key: { $in: keys } };
+ const collName = this.useSingle ? aclCollectionName : bucket;
let collection = this.db.collection(this.prefix + this.removeUnsupportedChar(collName));
- if (!collection) return cb(new Error(`Cannot find the collection ${collName}`));
+ if (!collection) throw new Error(`Cannot find the collection ${collName}`);
- collection.find(searchParams, { projection: { _bucketname: 0 } }).toArray(function (err, docs) {
- if (err instanceof Error) return cb(err);
- if (!docs.length) return cb(undefined, []);
+ let docs = await collection.find(searchParams, { projection: { _bucketname: 0 } }).toArray();
+ if (!docs.length) return [];
- var keyArrays = [];
- docs = fixAllKeys(docs);
- for (const doc of docs) {
- keyArrays.push(...Object.keys(doc));
- }
- cb(undefined, _.without(_.union(keyArrays), "key", "_id", "_bucketname"));
- });
+ const keyArrays = [];
+ docs = fixAllKeys(docs);
+ for (const doc of docs) {
+ keyArrays.push(...Object.keys(doc));
+ }
+ return _.without(_.union(keyArrays), "key", "_id", "_bucketname");
},
/**
Adds values to a given key inside a bucket.
*/
- add(transaction, bucket, key, values) {
- contract(arguments).params("array", "string", "string|number", "string|array|number").end();
+ async add(transaction, bucket, key, values) {
+ contract(arguments).params("array", "string", "string", "string|array").end();
- if (key == "key") throw new Error("Key name 'key' is not allowed.");
+ if (key === "key") throw new Error("Key name 'key' is not allowed.");
key = encodeText(key);
- var collectionIndex = this.useSingle ? { _bucketname: 1, key: 1 } : { key: 1 };
- var updateParams = this.useSingle ? { _bucketname: bucket, key: key } : { key: key };
- var collName = this.useSingle ? aclCollectionName : bucket;
- transaction.push((cb) => {
+ const collectionIndex = this.useSingle ? { _bucketname: 1, key: 1 } : { key: 1 };
+ const updateParams = this.useSingle ? { _bucketname: bucket, key: key } : { key: key };
+ const collName = this.useSingle ? aclCollectionName : bucket;
+ transaction.push(async () => {
values = makeArray(values);
let collection = this.db.collection(this.prefix + this.removeUnsupportedChar(collName));
- if (!collection) return cb(new Error(`Cannot find the collection ${collName}`));
+ if (!collection) throw new Error(`Cannot find the collection ${collName}`);
// build doc from array values
- var doc = {};
+ const doc = {};
for (const value of values) {
doc[value] = true;
}
// update documents
- collection.updateMany(updateParams, { $set: doc }, { safe: true, upsert: true }, (err) => {
- if (err instanceof Error) return cb(err);
- cb(undefined);
- });
+ await collection.updateMany(updateParams, { $set: doc }, { safe: true, upsert: true });
});
- transaction.push((cb) => {
+ transaction.push(async () => {
let collection = this.db.collection(this.prefix + this.removeUnsupportedChar(collName));
- if (!collection) return cb(new Error(`Cannot find the collection ${collName}`));
+ if (!collection) throw new Error(`Cannot find the collection ${collName}`);
- collection.createIndex(collectionIndex, (err) => {
- if (err instanceof Error) {
- return cb(err);
- } else {
- cb(undefined);
- }
- });
+ await collection.createIndex(collectionIndex);
});
},
/**
Delete the given key(s) at the bucket
*/
- del(transaction, bucket, keys) {
+ async del(transaction, bucket, keys) {
contract(arguments).params("array", "string", "string|array").end();
keys = makeArray(keys);
- var updateParams = this.useSingle ? { _bucketname: bucket, key: { $in: keys } } : { key: { $in: keys } };
- var collName = this.useSingle ? aclCollectionName : bucket;
+ const updateParams = this.useSingle ? { _bucketname: bucket, key: { $in: keys } } : { key: { $in: keys } };
+ const collName = this.useSingle ? aclCollectionName : bucket;
- transaction.push((cb) => {
+ transaction.push(async () => {
let collection = this.db.collection(this.prefix + this.removeUnsupportedChar(collName));
- if (!collection) return cb(new Error(`Cannot find the collection ${collName}`));
+ if (!collection) throw new Error(`Cannot find the collection ${collName}`);
- collection.deleteMany(updateParams, { safe: true }, (err) => {
- if (err instanceof Error) return cb(err);
- cb(undefined);
- });
+ await collection.deleteMany(updateParams, { safe: true });
});
},
/**
Removes values from a given key inside a bucket.
*/
- remove(transaction, bucket, key, values) {
- contract(arguments).params("array", "string", "string|number", "string|array|number").end();
+ async remove(transaction, bucket, key, values) {
+ contract(arguments).params("array", "string", "string", "string|array").end();
key = encodeText(key);
- var updateParams = this.useSingle ? { _bucketname: bucket, key: key } : { key: key };
- var collName = this.useSingle ? aclCollectionName : bucket;
+ const updateParams = this.useSingle ? { _bucketname: bucket, key: key } : { key: key };
+ const collName = this.useSingle ? aclCollectionName : bucket;
values = makeArray(values);
- transaction.push((cb) => {
+ transaction.push(async () => {
let collection = this.db.collection(this.prefix + this.removeUnsupportedChar(collName));
- if (!collection) return cb(new Error(`Cannot find the collection ${collName}`));
+ if (!collection) throw new Error(`Cannot find the collection ${collName}`);
// build doc from array values
- var doc = {};
+ const doc = {};
for (const value of values) {
doc[value] = true;
}
// update documents
- collection.updateMany(updateParams, { $unset: doc }, { safe: true, upsert: true }, (err) => {
- if (err instanceof Error) return cb(err);
- cb(undefined);
- });
+ await collection.updateMany(updateParams, { $unset: doc }, { safe: true, upsert: true });
});
},
@@ -217,7 +183,7 @@ MongoDBBackend.prototype = {
};
function encodeText(text) {
- if (typeof text == "string" || text instanceof String) {
+ if (typeof text === "string" || text instanceof String) {
text = encodeURIComponent(text);
text = text.replace(/\./g, "%2E");
}
@@ -225,7 +191,7 @@ function encodeText(text) {
}
function decodeText(text) {
- if (typeof text == "string" || text instanceof String) {
+ if (typeof text === "string" || text instanceof String) {
text = decodeURIComponent(text);
}
return text;
diff --git a/lib/redis-backend.js b/lib/redis-backend.js
index 7e7a99d..2f73881 100644
--- a/lib/redis-backend.js
+++ b/lib/redis-backend.js
@@ -1,11 +1,10 @@
-/**
+/*
Redis Backend.
Implementation of the storage backend using Redis
*/
-"use strict";
-var contract = require("./contract");
+const contract = require("./contract");
function noop() {}
@@ -15,139 +14,126 @@ function RedisBackend({ redis, prefix }) {
}
RedisBackend.prototype = {
- close(cb) {
- this.redis.end();
- cb();
+ async close() {
+ await this.redis.quit();
},
/**
Begins a transaction
*/
- begin() {
- return this.redis.multi();
+ async begin() {
+ return await this.redis.multi();
},
/**
Ends a transaction (and executes it)
*/
- end(transaction, cb) {
- contract(arguments).params("object", "function").end();
- transaction.exec(function () {
- cb();
- });
+ async end(transaction) {
+ await transaction.exec();
},
/**
Cleans the whole storage.
*/
- clean(cb) {
- contract(arguments).params("function").end();
- this.redis.keys(this.prefix + "*", (err, keys) => {
- if (keys.length) {
- this.redis.del(keys, function () {
- cb();
- });
- } else {
- cb();
- }
- });
+ async clean() {
+ const keys = await this.redis.keys(this.prefix + "*");
+ if (keys && keys.length) this.redis.del(keys);
},
/**
Gets the contents at the bucket's key.
*/
- get(bucket, key, cb) {
- contract(arguments).params("string", "string|number", "function").end();
+ async get(bucket, key) {
+ contract(arguments).params("string", "string").end();
key = this.bucketKey(bucket, key);
- this.redis.smembers(key, cb);
+ return await this.redis.sMembers(key);
},
/**
Gets an object mapping each passed bucket to the union of the specified keys inside that bucket.
*/
- unions(buckets, keys, cb) {
- contract(arguments).params("array", "array", "function").end();
+ async unions(buckets, keys) {
+ contract(arguments).params("array", "array").end();
- var redisKeys = {};
- var batch = this.redis.batch();
+ const redisKeys = {};
+ const multi = this.redis.multi();
for (const bucket of buckets) {
redisKeys[bucket] = this.bucketKey(bucket, keys);
- batch.sunion(redisKeys[bucket], noop);
+ multi.sUnion(redisKeys[bucket], noop);
}
- batch.exec(function (err, replies) {
- if (!Array.isArray(replies)) {
- return {};
- }
+ const replies = await multi.exec();
+ if (!Array.isArray(replies)) {
+ return {};
+ }
- var result = {};
- for (let index = 0; index < replies.length; index++) {
- let reply = replies[index];
- if (reply instanceof Error) cb(reply);
+ const result = {};
+ for (let index = 0; index < replies.length; index++) {
+ let reply = replies[index];
+ if (reply instanceof Error) throw reply;
- result[buckets[index]] = reply;
- }
- cb(err, result);
- });
+ result[buckets[index]] = reply;
+ }
+ return result;
},
/**
Returns the union of the values in the given keys.
*/
- union(bucket, keys, cb) {
- contract(arguments).params("string", "array", "function").end();
+ async union(bucket, keys) {
+ contract(arguments).params("string", "array").end();
keys = this.bucketKey(bucket, keys);
- this.redis.sunion(keys, cb);
+ return await this.redis.sUnion(keys);
},
/**
Adds values to a given key inside a bucket.
*/
- add(transaction, bucket, key, values) {
- contract(arguments).params("object", "string", "string|number", "string|array|number").end();
+ async add(transaction, bucket, key, values) {
+ contract(arguments).params("object", "string", "string", "string|array").end();
key = this.bucketKey(bucket, key);
if (Array.isArray(values)) {
for (const value of values) {
- transaction.sadd(key, value);
+ transaction.sAdd(key, value);
}
} else {
- transaction.sadd(key, values);
+ transaction.sAdd(key, values);
}
},
/**
Delete the given key(s) at the bucket
*/
- del(transaction, bucket, keys) {
+ async del(transaction, bucket, keys) {
contract(arguments).params("object", "string", "string|array").end();
keys = Array.isArray(keys) ? keys : [keys];
keys = keys.map((key) => this.bucketKey(bucket, key));
- transaction.del(keys);
+ await transaction.del(keys);
},
/**
Removes values from a given key inside a bucket.
*/
- remove(transaction, bucket, key, values) {
- contract(arguments).params("object", "string", "string|number", "string|array|number").end();
+ async remove(transaction, bucket, key, values) {
+ contract(arguments).params("object", "string", "string", "string|array").end();
key = this.bucketKey(bucket, key);
if (Array.isArray(values)) {
for (const value of values) {
- transaction.srem(key, value);
+ transaction.sRem(key, value);
}
} else {
- transaction.srem(key, values);
+ transaction.sRem(key, values);
}
},
diff --git a/package.json b/package.json
index 5026241..e04b4cf 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "acl2",
- "version": "3.0.1",
+ "version": "4.0.0",
"description": "An Access Control List module based on memory, Redis, or MongoDB with Express middleware support",
"keywords": [
"middleware",
@@ -9,28 +9,26 @@
"node"
],
"repository": "git://github.com/flash-oss/node_acl.git",
- "author": "Manuel Astudillo ",
+ "author": "https://github.com/koresar",
"homepage": "https://github.com/flash-oss/node_acl",
"license": "MIT",
"engines": {
- "node": ">= 12.9"
+ "node": ">= 16"
},
"main": "./index.js",
"dependencies": {
- "async": "^3.2.3",
- "bluebird": "^3.0.2",
"lodash": "^4.17.3"
},
"devDependencies": {
- "chai": "^4.2.0",
- "eslint": "^7.7.0",
- "mocha": "^8.1.1",
- "mongodb": "3 - 4",
+ "eslint": "^8.56.0",
+ "mocha": "^10.2.0",
+ "mongodb": "5 - 6",
"nyc": "^15.1.0",
"prettier": "^2.1.0",
- "redis": "^2.2.5"
+ "redis": "^4.6.12"
},
"scripts": {
+ "lint": "eslint ./",
"test": "npm run test_memory && npm run test_redis && npm run test_mongo && npm run test_mongo_single",
"test_memory": "ACL_BACKEND=memory mocha",
"test_redis": "ACL_BACKEND=redis mocha",
@@ -44,7 +42,7 @@
],
"eslintConfig": {
"parserOptions": {
- "ecmaVersion": 2019
+ "ecmaVersion": 2023
},
"env": {
"es6": true,
diff --git a/test/backendtests.js b/test/backendtests.js
index 8f46e18..75a3cb2 100644
--- a/test/backendtests.js
+++ b/test/backendtests.js
@@ -1,78 +1,66 @@
-var chai = require("chai");
-var expect = chai.expect;
+const assert = require("node:assert/strict");
-var testData = {
+const testData = {
key1: ["1", "2", "3"],
key2: ["3", "2", "4"],
key3: ["3", "4", "5"],
};
-var buckets = ["bucket1", "bucket2"];
+const buckets = ["bucket1", "bucket2"];
describe("unions", function () {
let backend;
- before(function (done) {
- require("./create-backend")()
- .then((b) => {
- backend = b;
+ before(async function () {
+ backend = await require("./create-backend")();
+ if (!backend.unions) {
+ this.skip();
+ }
- if (!backend.unions) {
- this.skip();
- }
-
- backend.clean(function () {
- var transaction = backend.begin();
- for (const key of Object.keys(testData)) {
- for (const bucket of buckets) {
- backend.add(transaction, bucket, key, testData[key]);
- }
- }
- backend.end(transaction, done);
- });
- })
- .catch(done);
+ await backend.clean();
+ const transaction = await backend.begin();
+ for (const key of Object.keys(testData)) {
+ for (const bucket of buckets) {
+ await backend.add(transaction, bucket, key, testData[key]);
+ }
+ }
+ await backend.end(transaction);
});
- after(function (done) {
- if (!backend) return done();
- backend.clean((err) => {
- if (err) return done(err);
- backend.close(done);
- });
+ after(async function () {
+ if (!backend) return;
+ await backend.clean();
+ await backend.close();
});
- it("should respond with an appropriate map", function (done) {
- var expected = {
+ it("should respond with an appropriate map", async function () {
+ const expected = {
bucket1: ["1", "2", "3", "4", "5"],
bucket2: ["1", "2", "3", "4", "5"],
};
- backend.unions(buckets, Object.keys(testData), function (err, result) {
- expect(err).to.be.null;
- expect(result).to.be.eql(expected);
- done();
- });
+
+ const result = await backend.unions(buckets, Object.keys(testData));
+
+ assert.deepEqual(result, expected);
});
- it("should get only the specified keys", function (done) {
- var expected = {
+ it("should get only the specified keys", async function () {
+ const expected = {
bucket1: ["1", "2", "3"],
bucket2: ["1", "2", "3"],
};
- backend.unions(buckets, ["key1"], function (err, result) {
- expect(err).to.be.null;
- expect(result).to.be.eql(expected);
- done();
- });
+
+ const result = await backend.unions(buckets, ["key1"]);
+
+ assert.deepEqual(result, expected);
});
- it("should only get the specified buckets", function (done) {
- var expected = {
+ it("should only get the specified buckets", async function () {
+ const expected = {
bucket1: ["1", "2", "3"],
};
- backend.unions(["bucket1"], ["key1"], function (err, result) {
- expect(err).to.be.null;
- expect(result).to.be.eql(expected);
- done();
- });
+
+ const result = await backend.unions(["bucket1"], ["key1"]);
+
+ assert.deepEqual(result, expected);
});
});
diff --git a/test/create-backend.js b/test/create-backend.js
index 72d9b2d..8e63c42 100644
--- a/test/create-backend.js
+++ b/test/create-backend.js
@@ -12,16 +12,14 @@ module.exports = async function createBackend(backendType) {
password: null,
};
- const redis = require("redis").createClient(options.port, options.host, {
- no_ready_check: true,
- });
+ const redis = await require("redis").createClient(options.port, options.host).connect();
return new Acl.redisBackend({ redis });
}
if (backendType === "mongo") {
const { MongoClient } = await require("mongodb");
- const client = await MongoClient.connect("mongodb://localhost:27017/acl_test?useUnifiedTopology=true");
+ const client = await MongoClient.connect("mongodb://localhost:27017/acl_test");
await client.db("acl_test").dropDatabase();
return new Acl.mongodbBackend({ client, prefix: "acl_" });
@@ -29,11 +27,11 @@ module.exports = async function createBackend(backendType) {
if (backendType === "mongo_single") {
const { MongoClient } = await require("mongodb");
- const client = await MongoClient.connect("mongodb://localhost:27017/acl_test?useUnifiedTopology=true");
+ const client = await MongoClient.connect("mongodb://localhost:27017/acl_test");
await client.db("acl_test").dropDatabase();
return new Acl.mongodbBackend({ client, prefix: "acl_", useSingle: true });
}
- throw new Error("Please assign ACL_BACKEND env var to one of: memory, redis, mongo, mongo_single");
+ throw new Error("Please assign ACL_BACKEND env const to one of: memory, redis, mongo, mongo_single");
};
diff --git a/test/tests.js b/test/tests.js
index fb5076e..2ff37b1 100644
--- a/test/tests.js
+++ b/test/tests.js
@@ -1,6 +1,6 @@
-var Acl = require("../"),
- assert = require("chai").assert,
- expect = require("chai").expect;
+const Acl = require("../");
+const assert = require("node:assert/strict");
+const _ = require("lodash");
describe("acl", () => {
let backend;
@@ -9,28 +9,26 @@ describe("acl", () => {
backend = await require("./create-backend")();
});
- after(function (done) {
- if (!backend) return done();
- backend.clean((err) => {
- if (err) return done(err);
- backend.close(done);
- });
+ after(async function () {
+ if (!backend) return;
+ await backend.clean();
+ await backend.close();
});
describe("constructor", function () {
it("should use default `buckets` names", function () {
- var acl = new Acl(backend);
+ const acl = new Acl(backend);
- expect(acl.options.buckets.meta).to.equal("meta");
- expect(acl.options.buckets.parents).to.equal("parents");
- expect(acl.options.buckets.permissions).to.equal("permissions");
- expect(acl.options.buckets.resources).to.equal("resources");
- expect(acl.options.buckets.roles).to.equal("roles");
- expect(acl.options.buckets.users).to.equal("users");
+ assert.equal(acl.options.buckets.meta, "meta");
+ assert.equal(acl.options.buckets.parents, "parents");
+ assert.equal(acl.options.buckets.permissions, "permissions");
+ assert.equal(acl.options.buckets.resources, "resources");
+ assert.equal(acl.options.buckets.roles, "roles");
+ assert.equal(acl.options.buckets.users, "users");
});
it("should use given `buckets` names", function () {
- var acl = new Acl(backend, null, {
+ const acl = new Acl(backend, null, {
buckets: {
meta: "Meta",
parents: "Parents",
@@ -41,1158 +39,822 @@ describe("acl", () => {
},
});
- expect(acl.options.buckets.meta).to.equal("Meta");
- expect(acl.options.buckets.parents).to.equal("Parents");
- expect(acl.options.buckets.permissions).to.equal("Permissions");
- expect(acl.options.buckets.resources).to.equal("Resources");
- expect(acl.options.buckets.roles).to.equal("Roles");
- expect(acl.options.buckets.users).to.equal("Users");
+ assert.equal(acl.options.buckets.meta, "Meta");
+ assert.equal(acl.options.buckets.parents, "Parents");
+ assert.equal(acl.options.buckets.permissions, "Permissions");
+ assert.equal(acl.options.buckets.resources, "Resources");
+ assert.equal(acl.options.buckets.roles, "Roles");
+ assert.equal(acl.options.buckets.users, "Users");
});
});
describe("allow", function () {
this.timeout(10000);
- it("guest to view blogs", function (done) {
- var acl = new Acl(backend);
+ it("guest to view blogs", async function () {
+ const acl = new Acl(backend);
- acl.allow("guest", "blogs", "view", function (err) {
- assert.ifError(err);
- done();
- });
+ await acl.allow("guest", "blogs", "view");
});
- it("guest to view forums", function (done) {
- var acl = new Acl(backend);
+ it("guest to view forums", async function () {
+ const acl = new Acl(backend);
- acl.allow("guest", "forums", "view", function (err) {
- assert.ifError(err);
- done();
- });
+ await acl.allow("guest", "forums", "view");
});
- it("member to view/edit/delete blogs", function (done) {
- var acl = new Acl(backend);
+ it("member to view/edit/delete blogs", async function () {
+ const acl = new Acl(backend);
- acl.allow("member", "blogs", ["edit", "view", "delete"], function (err) {
- assert.ifError(err);
- done();
- });
+ await acl.allow("member", "blogs", ["edit", "view", "delete"]);
});
});
describe("Add user roles", function () {
- it("joed => guest, jsmith => member, harry => admin, test@test.com => member", function (done) {
- var acl = new Acl(backend);
-
- acl.addUserRoles("joed", "guest", function (err) {
- assert.ifError(err);
+ it("joed => guest, jsmith => member, harry => admin, test@test.com => member", async function () {
+ const acl = new Acl(backend);
- acl.addUserRoles("jsmith", "member", function (err) {
- assert.ifError(err);
-
- acl.addUserRoles("harry", "admin", function (err) {
- assert.ifError(err);
-
- acl.addUserRoles("test@test.com", "member", function (err) {
- assert.ifError(err);
- done();
- });
- });
- });
- });
+ await acl.addUserRoles("joed", "guest");
+ await acl.addUserRoles("jsmith", "member");
+ await acl.addUserRoles("harry", "admin");
+ await acl.addUserRoles("test@test.com", "member");
});
- it("0 => guest, 1 => member, 2 => admin", function (done) {
- var acl = new Acl(backend);
-
- acl.addUserRoles(0, "guest", function (err) {
- assert.ifError(err);
-
- acl.addUserRoles(1, "member", function (err) {
- assert.ifError(err);
+ it("0 => guest, 1 => member, 2 => admin", async function () {
+ const acl = new Acl(backend);
- acl.addUserRoles(2, "admin", function (err) {
- assert.ifError(err);
- done();
- });
- });
- });
+ await acl.addUserRoles("0", "guest");
+ await acl.addUserRoles("1", "member");
+ await acl.addUserRoles("2", "admin");
});
});
describe("read User Roles", function () {
- it("run userRoles function", function (done) {
- var acl = new Acl(backend);
- acl.addUserRoles("harry", "admin", function (err) {
- if (err) return done(err);
-
- acl.userRoles("harry", function (err, roles) {
- if (err) return done(err);
-
- assert.deepEqual(roles, ["admin"]);
- acl.hasRole("harry", "admin", function (err, is_in_role) {
- if (err) return done(err);
-
- assert.ok(is_in_role);
- acl.hasRole("harry", "no role", function (err, is_in_role) {
- if (err) return done(err);
-
- assert.notOk(is_in_role);
- done();
- });
- });
- });
- });
+ it("run userRoles function", async function () {
+ const acl = new Acl(backend);
+ await acl.addUserRoles("harry", "admin");
+
+ const roles = await acl.userRoles("harry");
+ assert.deepEqual(roles, ["admin"]);
+
+ let is_in_role = await acl.hasRole("harry", "admin");
+ assert.ok(is_in_role);
+
+ is_in_role = await acl.hasRole("harry", "no role");
+ assert.ok(!is_in_role);
});
});
describe("read Role Users", function () {
- it("run roleUsers function", function (done) {
- var acl = new Acl(backend);
- acl.addUserRoles("harry", "admin", function (err) {
- if (err) return done(err);
-
- acl.roleUsers("admin", function (err, users) {
- if (err) return done(err);
- assert.include(users, "harry");
- assert.isFalse("invalid User" in users);
- done();
- });
- });
+ it("run roleUsers function", async function () {
+ const acl = new Acl(backend);
+ await acl.addUserRoles("harry", "admin");
+
+ const users = await acl.roleUsers("admin");
+
+ assert(users.includes("harry"));
+ assert(!("invalid User" in users));
});
});
describe("allow", function () {
- it("admin view/add/edit/delete users", function (done) {
- var acl = new Acl(backend);
+ it("admin view/add/edit/delete users", async function () {
+ const acl = new Acl(backend);
- acl.allow("admin", "users", ["add", "edit", "view", "delete"], function (err) {
- assert.ifError(err);
- done();
- });
+ await acl.allow("admin", "users", ["add", "edit", "view", "delete"]);
});
- it("foo view/edit blogs", function (done) {
- var acl = new Acl(backend);
+ it("foo view/edit blogs", async function () {
+ const acl = new Acl(backend);
- acl.allow("foo", "blogs", ["edit", "view"], function (err) {
- assert.ifError(err);
- done();
- });
+ await acl.allow("foo", "blogs", ["edit", "view"]);
});
- it("bar to view/delete blogs", function (done) {
- var acl = new Acl(backend);
+ it("bar to view/delete blogs", async function () {
+ const acl = new Acl(backend);
- acl.allow("bar", "blogs", ["view", "delete"], function (err) {
- assert.ifError(err);
- done();
- });
+ await acl.allow("bar", "blogs", ["view", "delete"]);
});
});
describe("add role parents", function () {
- it("add them", function (done) {
- var acl = new Acl(backend);
+ it("add them", async function () {
+ const acl = new Acl(backend);
- acl.addRoleParents("baz", ["foo", "bar"], function (err) {
- assert.ifError(err);
- done();
- });
+ await acl.addRoleParents("baz", ["foo", "bar"]);
});
});
describe("add user roles", function () {
- it("add them", function (done) {
- var acl = new Acl(backend);
+ it("add them", async function () {
+ const acl = new Acl(backend);
- acl.addUserRoles("james", "baz", function (err) {
- assert.ifError(err);
- done();
- });
+ await acl.addUserRoles("james", "baz");
});
- it("add them (numeric userId)", function (done) {
- var acl = new Acl(backend);
- acl.addUserRoles(3, "baz", function (err) {
- assert.ifError(err);
- done();
- });
+ it("add them (numeric userId)", async function () {
+ const acl = new Acl(backend);
+
+ await acl.addUserRoles("3", "baz");
});
});
describe("allow admin to do anything", function () {
- it("add them", function (done) {
- var acl = new Acl(backend);
+ it("add them", async function () {
+ const acl = new Acl(backend);
- acl.allow("admin", ["blogs", "forums"], "*", function (err) {
- assert.ifError(err);
- done();
- });
+ await acl.allow("admin", ["blogs", "forums"], "*");
});
});
describe("Arguments in one array", function () {
- it("give role fumanchu an array of resources and permissions", function (done) {
- var acl = new Acl(backend);
-
- acl.allow(
- [
- {
- roles: "fumanchu",
- allows: [
- { resources: "blogs", permissions: "get" },
- {
- resources: ["forums", "news"],
- permissions: ["get", "put", "delete"],
- },
- {
- resources: ["/path/file/file1.txt", "/path/file/file2.txt"],
- permissions: ["get", "put", "delete"],
- },
- ],
- },
- ],
- function (err) {
- assert.ifError(err);
- done();
- }
- );
+ it("give role fumanchu an array of resources and permissions", async function () {
+ const acl = new Acl(backend);
+
+ await acl.allow([
+ {
+ roles: "fumanchu",
+ allows: [
+ { resources: "blogs", permissions: "get" },
+ {
+ resources: ["forums", "news"],
+ permissions: ["get", "put", "delete"],
+ },
+ {
+ resources: ["/path/file/file1.txt", "/path/file/file2.txt"],
+ permissions: ["get", "put", "delete"],
+ },
+ ],
+ },
+ ]);
});
});
describe("Add fumanchu role to suzanne", function () {
- it("do it", function (done) {
- var acl = new Acl(backend);
- acl.addUserRoles("suzanne", "fumanchu", function (err) {
- assert.ifError(err);
- done();
- });
+ it("do it", async function () {
+ const acl = new Acl(backend);
+ await acl.addUserRoles("suzanne", "fumanchu");
});
- it("do it (numeric userId)", function (done) {
- var acl = new Acl(backend);
- acl.addUserRoles(4, "fumanchu", function (err) {
- assert.ifError(err);
- done();
- });
+
+ it("do it (numeric userId)", async function () {
+ const acl = new Acl(backend);
+ await acl.addUserRoles("4", "fumanchu");
});
});
describe("Allowance queries", function () {
describe("isAllowed", function () {
- it("Can joed view blogs?", function (done) {
- var acl = new Acl(backend);
-
- acl.isAllowed("joed", "blogs", "view", function (err, allow) {
- assert.ifError(err);
- assert(allow);
- done();
- });
+ it("Can joed view blogs?", async function () {
+ const acl = new Acl(backend);
+
+ assert(await acl.isAllowed("joed", "blogs", "view"));
});
- it("Can userId=0 view blogs?", function (done) {
- var acl = new Acl(backend);
+ it("Can userId=0 view blogs?", async function () {
+ const acl = new Acl(backend);
- acl.isAllowed(0, "blogs", "view", function (err, allow) {
- assert.ifError(err);
- assert(allow);
- done();
- });
+ assert(await acl.isAllowed("0", "blogs", "view"));
});
- it("Can joed view forums?", function (done) {
- var acl = new Acl(backend);
+ it("Can joed view forums?", async function () {
+ const acl = new Acl(backend);
- acl.isAllowed("joed", "forums", "view", function (err, allow) {
- assert.ifError(err);
- assert(allow);
- done();
- });
+ assert(await acl.isAllowed("joed", "forums", "view"));
});
- it("Can userId=0 view forums?", function (done) {
- var acl = new Acl(backend);
+ it("Can userId=0 view forums?", async function () {
+ const acl = new Acl(backend);
- acl.isAllowed(0, "forums", "view", function (err, allow) {
- assert.ifError(err);
- assert(allow);
- done();
- });
+ assert(await acl.isAllowed("0", "forums", "view"));
});
- it("Can joed edit forums?", function (done) {
- var acl = new Acl(backend);
+ it("Can joed edit forums?", async function () {
+ const acl = new Acl(backend);
- acl.isAllowed("joed", "forums", "edit", function (err, allow) {
- assert.ifError(err);
- assert(!allow);
- done();
- });
+ assert(!(await acl.isAllowed("joed", "forums", "edit")));
});
- it("Can userId=0 edit forums?", function (done) {
- var acl = new Acl(backend);
+ it("Can userId=0 edit forums?", async function () {
+ const acl = new Acl(backend);
- acl.isAllowed(0, "forums", "edit", function (err, allow) {
- assert.ifError(err);
- assert(!allow);
- done();
- });
+ assert(!(await acl.isAllowed("0", "forums", "edit")));
});
- it("Can jsmith edit forums?", function (done) {
- var acl = new Acl(backend);
+ it("Can jsmith edit forums?", async function () {
+ const acl = new Acl(backend);
- acl.isAllowed("jsmith", "forums", "edit", function (err, allow) {
- assert.ifError(err);
- assert(!allow);
- done();
- });
+ assert(!(await acl.isAllowed("jsmith", "forums", "edit")));
});
- it("Can jsmith edit forums?", function (done) {
- var acl = new Acl(backend);
+ it("Can jsmith edit forums?", async function () {
+ const acl = new Acl(backend);
- acl.isAllowed("jsmith", "forums", "edit", function (err, allow) {
- assert.ifError(err);
- assert(!allow);
- done();
- });
+ assert(!(await acl.isAllowed("jsmith", "forums", "edit")));
});
- it("Can jsmith edit blogs?", function (done) {
- var acl = new Acl(backend);
+ it("Can jsmith edit blogs?", async function () {
+ const acl = new Acl(backend);
- acl.isAllowed("jsmith", "blogs", "edit", function (err, allow) {
- assert.ifError(err);
- assert(allow);
- done();
- });
+ assert(await acl.isAllowed("jsmith", "blogs", "edit"));
});
- it("Can test@test.com edit forums?", function (done) {
- var acl = new Acl(backend);
+ it("Can test@test.com edit forums?", async function () {
+ const acl = new Acl(backend);
- acl.isAllowed("test@test.com", "forums", "edit", function (err, allow) {
- assert.ifError(err);
- assert(!allow);
- done();
- });
+ assert(!(await acl.isAllowed("test@test.com", "forums", "edit")));
});
- it("Can test@test.com edit forums?", function (done) {
- var acl = new Acl(backend);
+ it("Can test@test.com edit forums?", async function () {
+ const acl = new Acl(backend);
- acl.isAllowed("test@test.com", "forums", "edit", function (err, allow) {
- assert.ifError(err);
- assert(!allow);
- done();
- });
+ assert(!(await acl.isAllowed("test@test.com", "forums", "edit")));
});
- it("Can test@test.com edit blogs?", function (done) {
- var acl = new Acl(backend);
+ it("Can test@test.com edit blogs?", async function () {
+ const acl = new Acl(backend);
- acl.isAllowed("test@test.com", "blogs", "edit", function (err, allow) {
- assert.ifError(err);
- assert(allow);
- done();
- });
+ assert(await acl.isAllowed("test@test.com", "blogs", "edit"));
});
- it("Can userId=1 edit blogs?", function (done) {
- var acl = new Acl(backend);
+ it("Can userId=1 edit blogs?", async function () {
+ const acl = new Acl(backend);
- acl.isAllowed(1, "blogs", "edit", function (err, allow) {
- assert.ifError(err);
- assert(allow);
- done();
- });
+ assert(await acl.isAllowed("1", "blogs", "edit"));
});
- it("Can jsmith edit, delete and clone blogs?", function (done) {
- var acl = new Acl(backend);
+ it("Can jsmith edit, delete and clone blogs?", async function () {
+ const acl = new Acl(backend);
- acl.isAllowed("jsmith", "blogs", ["edit", "view", "clone"], function (err, allow) {
- assert.ifError(err);
- assert(!allow);
- done();
- });
+ assert(!(await acl.isAllowed("jsmith", "blogs", ["edit", "view", "clone"])));
});
- it("Can test@test.com edit, delete and clone blogs?", function (done) {
- var acl = new Acl(backend);
+ it("Can test@test.com edit, delete and clone blogs?", async function () {
+ const acl = new Acl(backend);
- acl.isAllowed("test@test.com", "blogs", ["edit", "view", "clone"], function (err, allow) {
- assert.ifError(err);
- assert(!allow);
- done();
- });
+ assert(!(await acl.isAllowed("test@test.com", "blogs", ["edit", "view", "clone"])));
});
- it("Can userId=1 edit, delete and clone blogs?", function (done) {
- var acl = new Acl(backend);
+ it("Can userId=1 edit, delete and clone blogs?", async function () {
+ const acl = new Acl(backend);
- acl.isAllowed(1, "blogs", ["edit", "view", "clone"], function (err, allow) {
- assert.ifError(err);
- assert(!allow);
- done();
- });
+ assert(!(await acl.isAllowed("1", "blogs", ["edit", "view", "clone"])));
});
- it("Can jsmith edit, clone blogs?", function (done) {
- var acl = new Acl(backend);
+ it("Can jsmith edit, clone blogs?", async function () {
+ const acl = new Acl(backend);
- acl.isAllowed("jsmith", "blogs", ["edit", "clone"], function (err, allow) {
- assert.ifError(err);
- assert(!allow);
- done();
- });
+ assert(!(await acl.isAllowed("jsmith", "blogs", ["edit", "clone"])));
});
- it("Can test@test.com edit, clone blogs?", function (done) {
- var acl = new Acl(backend);
+ it("Can test@test.com edit, clone blogs?", async function () {
+ const acl = new Acl(backend);
- acl.isAllowed("test@test.com", "blogs", ["edit", "clone"], function (err, allow) {
- assert.ifError(err);
- assert(!allow);
- done();
- });
+ assert(!(await acl.isAllowed("test@test.com", "blogs", ["edit", "clone"])));
});
- it("Can userId=1 edit, delete blogs?", function (done) {
- var acl = new Acl(backend);
+ it("Can userId=1 edit, delete blogs?", async function () {
+ const acl = new Acl(backend);
- acl.isAllowed(1, "blogs", ["edit", "clone"], function (err, allow) {
- assert.ifError(err);
- assert(!allow);
- done();
- });
+ assert(!(await acl.isAllowed("1", "blogs", ["edit", "clone"])));
});
- it("Can james add blogs?", function (done) {
- var acl = new Acl(backend);
+ it("Can james add blogs?", async function () {
+ const acl = new Acl(backend);
- acl.isAllowed("james", "blogs", "add", function (err, allow) {
- assert.ifError(err);
- assert(!allow);
- done();
- });
+ assert(!(await acl.isAllowed("james", "blogs", "add")));
});
- it("Can userId=3 add blogs?", function (done) {
- var acl = new Acl(backend);
+ it("Can userId=3 add blogs?", async function () {
+ const acl = new Acl(backend);
- acl.isAllowed(3, "blogs", "add", function (err, allow) {
- assert.ifError(err);
- assert(!allow);
- done();
- });
+ assert(!(await acl.isAllowed("3", "blogs", "add")));
});
- it("Can suzanne add blogs?", function (done) {
- var acl = new Acl(backend);
+ it("Can suzanne add blogs?", async function () {
+ const acl = new Acl(backend);
- acl.isAllowed("suzanne", "blogs", "add", function (err, allow) {
- assert.ifError(err);
- assert(!allow);
- done();
- });
+ assert(!(await acl.isAllowed("suzanne", "blogs", "add")));
});
- it("Can userId=4 add blogs?", function (done) {
- var acl = new Acl(backend);
+ it("Can userId=4 add blogs?", async function () {
+ const acl = new Acl(backend);
- acl.isAllowed(4, "blogs", "add", function (err, allow) {
- assert.ifError(err);
- assert(!allow);
- done();
- });
+ assert(!(await acl.isAllowed("4", "blogs", "add")));
});
- it("Can suzanne get blogs?", function (done) {
- var acl = new Acl(backend);
+ it("Can suzanne get blogs?", async function () {
+ const acl = new Acl(backend);
- acl.isAllowed("suzanne", "blogs", "get", function (err, allow) {
- assert.ifError(err);
- assert(allow);
- done();
- });
+ assert(await acl.isAllowed("suzanne", "blogs", "get"));
});
- it("Can userId=4 get blogs?", function (done) {
- var acl = new Acl(backend);
+ it("Can userId=4 get blogs?", async function () {
+ const acl = new Acl(backend);
- acl.isAllowed(4, "blogs", "get", function (err, allow) {
- assert.ifError(err);
- assert(allow);
- done();
- });
+ assert(await acl.isAllowed("4", "blogs", "get"));
});
- it("Can suzanne delete and put news?", function (done) {
- var acl = new Acl(backend);
+ it("Can suzanne delete and put news?", async function () {
+ const acl = new Acl(backend);
- acl.isAllowed("suzanne", "news", ["put", "delete"], function (err, allow) {
- assert.ifError(err);
- assert(allow);
- done();
- });
+ assert(await acl.isAllowed("suzanne", "news", ["put", "delete"]));
});
- it("Can userId=4 delete and put news?", function (done) {
- var acl = new Acl(backend);
+ it("Can userId=4 delete and put news?", async function () {
+ const acl = new Acl(backend);
- acl.isAllowed(4, "news", ["put", "delete"], function (err, allow) {
- assert.ifError(err);
- assert(allow);
- done();
- });
+ assert(await acl.isAllowed("4", "news", ["put", "delete"]));
});
- it("Can suzanne delete and put forums?", function (done) {
- var acl = new Acl(backend);
+ it("Can suzanne delete and put forums?", async function () {
+ const acl = new Acl(backend);
- acl.isAllowed("suzanne", "forums", ["put", "delete"], function (err, allow) {
- assert.ifError(err);
- assert(allow);
- done();
- });
+ assert(await acl.isAllowed("suzanne", "forums", ["put", "delete"]));
});
- it("Can userId=4 delete and put forums?", function (done) {
- var acl = new Acl(backend);
+ it("Can userId=4 delete and put forums?", async function () {
+ const acl = new Acl(backend);
- acl.isAllowed(4, "forums", ["put", "delete"], function (err, allow) {
- assert.ifError(err);
- assert(allow);
- done();
- });
+ assert(await acl.isAllowed("4", "forums", ["put", "delete"]));
});
- it("Can nobody view news?", function (done) {
- var acl = new Acl(backend);
+ it("Can nobody view news?", async function () {
+ const acl = new Acl(backend);
- acl.isAllowed("nobody", "blogs", "view", function (err, allow) {
- assert.ifError(err);
- assert(!allow);
- done();
- });
+ assert(!(await acl.isAllowed("nobody", "blogs", "view")));
});
- it("Can nobody view nothing?", function (done) {
- var acl = new Acl(backend);
+ it("Can nobody view nothing?", async function () {
+ const acl = new Acl(backend);
- acl.isAllowed("nobody", "nothing", "view", function (err, allow) {
- assert.ifError(err);
- assert(!allow);
- done();
- });
+ assert(!(await acl.isAllowed("nobody", "nothing", "view")));
});
});
describe("allowedPermissions", function () {
- it("What permissions has james over blogs and forums?", function (done) {
- var acl = new Acl(backend);
- acl.allowedPermissions("james", ["blogs", "forums"], function (err, permissions) {
- assert.ifError(err);
+ it("What permissions has james over blogs and forums?", async function () {
+ const acl = new Acl(backend);
- assert.property(permissions, "blogs");
- assert.property(permissions, "forums");
+ const permissions = await acl.allowedPermissions("james", ["blogs", "forums"]);
- assert.include(permissions.blogs, "edit");
- assert.include(permissions.blogs, "delete");
- assert.include(permissions.blogs, "view");
+ assert(permissions.blogs);
+ assert(permissions.forums);
- assert(permissions.forums.length === 0);
+ assert(permissions.blogs.includes("edit"));
+ assert(permissions.blogs.includes("delete"));
+ assert(permissions.blogs.includes("view"));
- done();
- });
+ assert(permissions.forums.length === 0);
});
- it("What permissions has userId=3 over blogs and forums?", function (done) {
- var acl = new Acl(backend);
- acl.allowedPermissions(3, ["blogs", "forums"], function (err, permissions) {
- assert.ifError(err);
- assert.property(permissions, "blogs");
- assert.property(permissions, "forums");
+ it("What permissions has userId=3 over blogs and forums?", async function () {
+ const acl = new Acl(backend);
+
+ const permissions = await acl.allowedPermissions("3", ["blogs", "forums"]);
- assert.include(permissions.blogs, "edit");
- assert.include(permissions.blogs, "delete");
- assert.include(permissions.blogs, "view");
+ assert(permissions.blogs);
+ assert(permissions.forums);
- assert(permissions.forums.length === 0);
+ assert(permissions.blogs.includes("edit"));
+ assert(permissions.blogs.includes("delete"));
+ assert(permissions.blogs.includes("view"));
- done();
- });
+ assert(permissions.forums.length === 0);
});
- it("What permissions has nonsenseUser over blogs and forums?", function (done) {
- var acl = new Acl(backend);
- acl.allowedPermissions("nonsense", ["blogs", "forums"], function (err, permissions) {
- assert.ifError(err);
- assert(permissions.forums.length === 0);
- assert(permissions.blogs.length === 0);
+ it("What permissions has nonsenseUser over blogs and forums?", async function () {
+ const acl = new Acl(backend);
+
+ const permissions = await acl.allowedPermissions("nonsense", ["blogs", "forums"]);
- done();
- });
+ assert(permissions.forums.length === 0);
+ assert(permissions.blogs.length === 0);
});
});
});
describe("whatResources queries", function () {
- it('What resources have "bar" some rights on?', function (done) {
- var acl = new Acl(backend);
-
- acl.whatResources("bar", function (err, resources) {
- assert.isNull(err);
- assert.include(resources.blogs, "view");
- assert.include(resources.blogs, "delete");
- done();
- });
+ it('What resources have "bar" some rights on?', async function () {
+ const acl = new Acl(backend);
+
+ const resources = await acl.whatResources("bar");
+
+ assert(resources.blogs.includes("view"));
+ assert(resources.blogs.includes("delete"));
});
- it('What resources have "bar" view rights on?', function (done) {
- var acl = new Acl(backend);
+ it('What resources have "bar" view rights on?', async function () {
+ const acl = new Acl(backend);
- acl.whatResources("bar", "view", function (err, resources) {
- assert.isNull(err);
- assert.include(resources, "blogs");
- done();
- });
+ const resources = await acl.whatResources("bar", "view");
+
+ assert(resources.includes("blogs"));
});
- it('What resources have "fumanchu" some rights on?', function (done) {
- var acl = new Acl(backend);
-
- acl.whatResources("fumanchu", function (err, resources) {
- assert.isNull(err);
- assert.include(resources.blogs, "get");
- assert.include(resources.forums, "delete");
- assert.include(resources.forums, "get");
- assert.include(resources.forums, "put");
- assert.include(resources.news, "delete");
- assert.include(resources.news, "get");
- assert.include(resources.news, "put");
- assert.include(resources["/path/file/file1.txt"], "delete");
- assert.include(resources["/path/file/file1.txt"], "get");
- assert.include(resources["/path/file/file1.txt"], "put");
- assert.include(resources["/path/file/file2.txt"], "delete");
- assert.include(resources["/path/file/file2.txt"], "get");
- assert.include(resources["/path/file/file2.txt"], "put");
- done();
- });
+ it('What resources have "fumanchu" some rights on?', async function () {
+ const acl = new Acl(backend);
+
+ const resources = await acl.whatResources("fumanchu");
+
+ assert(resources.blogs.includes("get"));
+ assert(resources.forums.includes("delete"));
+ assert(resources.forums.includes("get"));
+ assert(resources.forums.includes("put"));
+ assert(resources.news.includes("delete"));
+ assert(resources.news.includes("get"));
+ assert(resources.news.includes("put"));
+ assert(resources["/path/file/file1.txt"].includes("delete"));
+ assert(resources["/path/file/file1.txt"].includes("get"));
+ assert(resources["/path/file/file1.txt"].includes("put"));
+ assert(resources["/path/file/file2.txt"].includes("delete"));
+ assert(resources["/path/file/file2.txt"].includes("get"));
+ assert(resources["/path/file/file2.txt"].includes("put"));
});
- it('What resources have "baz" some rights on?', function (done) {
- var acl = new Acl(backend);
+ it('What resources have "baz" some rights on?', async function () {
+ const acl = new Acl(backend);
- acl.whatResources("baz", function (err, resources) {
- assert.isNull(err);
- assert.include(resources.blogs, "view");
- assert.include(resources.blogs, "delete");
- assert.include(resources.blogs, "edit");
- done();
- });
+ const resources = await acl.whatResources("baz");
+
+ assert(resources.blogs.includes("view"));
+ assert(resources.blogs.includes("delete"));
+ assert(resources.blogs.includes("edit"));
});
});
describe("removeAllow", function () {
- it("Remove get permissions from resources blogs and forums from role fumanchu", function (done) {
- var acl = new Acl(backend);
- acl.removeAllow("fumanchu", ["blogs", "forums"], "get", function (err) {
- assert.ifError(err);
- done();
- });
+ it("Remove get permissions from resources blogs and forums from role fumanchu", async function () {
+ const acl = new Acl(backend);
+
+ await acl.removeAllow("fumanchu", ["blogs", "forums"], "get");
});
- it("Remove delete and put permissions from resource news from role fumanchu", function (done) {
- var acl = new Acl(backend);
- acl.removeAllow("fumanchu", "news", "delete", function (err) {
- assert.ifError(err);
- done();
- });
+ it("Remove delete and put permissions from resource news from role fumanchu", async function () {
+ const acl = new Acl(backend);
+
+ await acl.removeAllow("fumanchu", "news", "delete");
});
- it("Remove view permissions from resource blogs from role bar", function (done) {
- var acl = new Acl(backend);
- acl.removeAllow("bar", "blogs", "view", function (err) {
- assert.ifError(err);
- done();
- });
+ it("Remove view permissions from resource blogs from role bar", async function () {
+ const acl = new Acl(backend);
+
+ await acl.removeAllow("bar", "blogs", "view");
});
});
describe("See if permissions were removed", function () {
- it('What resources have "fumanchu" some rights on after removed some of them?', function (done) {
- var acl = new Acl(backend);
- acl.whatResources("fumanchu", function (err, resources) {
- assert.isNull(err);
-
- assert.isFalse("blogs" in resources);
- assert.property(resources, "news");
- assert.include(resources.news, "get");
- assert.include(resources.news, "put");
- assert.isFalse("delete" in resources.news);
-
- assert.property(resources, "forums");
- assert.include(resources.forums, "delete");
- assert.include(resources.forums, "put");
- done();
- });
+ it('What resources have "fumanchu" some rights on after removed some of them?', async function () {
+ const acl = new Acl(backend);
+
+ const resources = await acl.whatResources("fumanchu");
+
+ assert(!("blogs" in resources));
+ assert(resources.news);
+ assert(resources.news.includes("get"));
+ assert(resources.news.includes("put"));
+ assert(!("delete" in resources.news));
+
+ assert(resources.forums);
+ assert(resources.forums.includes("delete"));
+ assert(resources.forums.includes("put"));
});
});
describe("removeRole", function () {
- it("Remove role fumanchu", function (done) {
- var acl = new Acl(backend);
- acl.removeRole("fumanchu", function (err) {
- assert.ifError(err);
- done();
- });
+ it("Remove role fumanchu", async function () {
+ const acl = new Acl(backend);
+
+ await acl.removeRole("fumanchu");
});
- it("Remove role member", function (done) {
- var acl = new Acl(backend);
- acl.removeRole("member", function (err) {
- assert.ifError(err);
- done();
- });
+ it("Remove role member", async function () {
+ const acl = new Acl(backend);
+
+ await acl.removeRole("member");
});
- it("Remove role foo", function (done) {
- var acl = new Acl(backend);
- acl.removeRole("foo", function (err) {
- assert.ifError(err);
- done();
- });
+ it("Remove role foo", async function () {
+ const acl = new Acl(backend);
+
+ await acl.removeRole("foo");
});
});
describe("Was role removed?", function () {
- it('What resources have "fumanchu" some rights on after removed?', function (done) {
- var acl = new Acl(backend);
- acl.whatResources("fumanchu", function (err, resources) {
- assert.ifError(err);
- assert(Object.keys(resources).length === 0);
- done();
- });
+ it('What resources have "fumanchu" some rights on after removed?', async function () {
+ const acl = new Acl(backend);
+
+ const resources = await acl.whatResources("fumanchu");
+
+ assert(Object.keys(resources).length === 0);
});
- it('What resources have "member" some rights on after removed?', function (done) {
- var acl = new Acl(backend);
- acl.whatResources("member", function (err, resources) {
- assert.ifError(err);
- assert(Object.keys(resources).length === 0);
- done();
- });
+ it('What resources have "member" some rights on after removed?', async function () {
+ const acl = new Acl(backend);
+
+ const resources = await acl.whatResources("member");
+
+ assert(Object.keys(resources).length === 0);
});
describe("allowed permissions", function () {
- it("What permissions has jsmith over blogs and forums?", function (done) {
- var acl = new Acl(backend);
- acl.allowedPermissions("jsmith", ["blogs", "forums"], function (err, permissions) {
- assert.ifError(err);
- assert(permissions.blogs.length === 0);
- assert(permissions.forums.length === 0);
- done();
- });
+ it("What permissions has jsmith over blogs and forums?", async function () {
+ const acl = new Acl(backend);
+
+ const permissions = await acl.allowedPermissions("jsmith", ["blogs", "forums"]);
+
+ assert(permissions.blogs.length === 0);
+ assert(permissions.forums.length === 0);
});
- it("What permissions has test@test.com over blogs and forums?", function (done) {
- var acl = new Acl(backend);
- acl.allowedPermissions("test@test.com", ["blogs", "forums"], function (err, permissions) {
- assert.ifError(err);
- assert(permissions.blogs.length === 0);
- assert(permissions.forums.length === 0);
- done();
- });
+ it("What permissions has test@test.com over blogs and forums?", async function () {
+ const acl = new Acl(backend);
+
+ const permissions = await acl.allowedPermissions("test@test.com", ["blogs", "forums"]);
+
+ assert(permissions.blogs.length === 0);
+ assert(permissions.forums.length === 0);
});
- it("What permissions has james over blogs?", function (done) {
- var acl = new Acl(backend);
- acl.allowedPermissions("james", "blogs", function (err, permissions) {
- assert.ifError(err);
- assert.property(permissions, "blogs");
- assert.include(permissions.blogs, "delete");
- done();
- });
+ it("What permissions has james over blogs?", async function () {
+ const acl = new Acl(backend);
+
+ const permissions = await acl.allowedPermissions("james", "blogs");
+
+ assert(permissions.blogs);
+ assert(permissions.blogs.includes("delete"));
});
});
});
describe("RoleParentRemoval", function () {
- before(function (done) {
- var acl = new Acl(backend);
- acl.allow("parent1", "x", "read1")
- .then(function () {
- return acl.allow("parent2", "x", "read2");
- })
- .then(function () {
- return acl.allow("parent3", "x", "read3");
- })
- .then(function () {
- return acl.allow("parent4", "x", "read4");
- })
- .then(function () {
- return acl.allow("parent5", "x", "read5");
- })
- .then(function () {
- return acl.addRoleParents("child", ["parent1", "parent2", "parent3", "parent4", "parent5"]);
- })
- .done(done, done);
- });
-
- var acl;
+ before(async function () {
+ const acl = new Acl(backend);
+
+ await acl.allow("parent1", "x", "read1");
+ await acl.allow("parent2", "x", "read2");
+ await acl.allow("parent3", "x", "read3");
+ await acl.allow("parent4", "x", "read4");
+ await acl.allow("parent5", "x", "read5");
+
+ await acl.addRoleParents("child", ["parent1", "parent2", "parent3", "parent4", "parent5"]);
+ });
+
+ let acl;
beforeEach(function () {
acl = new Acl(backend);
});
- it("Environment check", function (done) {
- acl.whatResources("child")
- .then(function (resources) {
- assert.lengthOf(resources.x, 5);
- assert.include(resources.x, "read1");
- assert.include(resources.x, "read2");
- assert.include(resources.x, "read3");
- assert.include(resources.x, "read4");
- assert.include(resources.x, "read5");
- })
- .done(done, done);
+ it("Environment check", async function () {
+ const resources = await acl.whatResources("child");
+
+ assert.equal(resources.x.length, 5);
+ assert(resources.x.includes("read1"));
+ assert(resources.x.includes("read2"));
+ assert(resources.x.includes("read3"));
+ assert(resources.x.includes("read4"));
+ assert(resources.x.includes("read5"));
});
- it("Operation uses a callback when removing a specific parent role", function (done) {
- acl.removeRoleParents("child", "parentX", function (err) {
- assert.ifError(err);
- done();
- });
+ it("Operation removing a specific parent role", async function () {
+ await acl.removeRoleParents("child", "parentX");
});
- it("Operation uses a callback when removing multiple specific parent roles", function (done) {
- acl.removeRoleParents("child", ["parentX", "parentY"], function (err) {
- assert.ifError(err);
- done();
- });
+ it("Operation removing multiple specific parent roles", async function () {
+ await acl.removeRoleParents("child", ["parentX", "parentY"]);
});
- it('Remove parent role "parentX" from role "child"', function (done) {
- acl.removeRoleParents("child", "parentX")
- .then(function () {
- return acl.whatResources("child");
- })
- .then(function (resources) {
- assert.lengthOf(resources.x, 5);
- assert.include(resources.x, "read1");
- assert.include(resources.x, "read2");
- assert.include(resources.x, "read3");
- assert.include(resources.x, "read4");
- assert.include(resources.x, "read5");
- })
- .done(done, done);
- });
-
- it('Remove parent role "parent1" from role "child"', function (done) {
- acl.removeRoleParents("child", "parent1")
- .then(function () {
- return acl.whatResources("child");
- })
- .then(function (resources) {
- assert.lengthOf(resources.x, 4);
- assert.include(resources.x, "read2");
- assert.include(resources.x, "read3");
- assert.include(resources.x, "read4");
- assert.include(resources.x, "read5");
- })
- .done(done, done);
- });
-
- it('Remove parent roles "parent2" & "parent3" from role "child"', function (done) {
- acl.removeRoleParents("child", ["parent2", "parent3"])
- .then(function () {
- return acl.whatResources("child");
- })
- .then(function (resources) {
- assert.lengthOf(resources.x, 2);
- assert.include(resources.x, "read4");
- assert.include(resources.x, "read5");
- })
- .done(done, done);
- });
-
- it('Remove all parent roles from role "child"', function (done) {
- acl.removeRoleParents("child")
- .then(function () {
- return acl.whatResources("child");
- })
- .then(function (resources) {
- assert.notProperty(resources, "x");
- })
- .done(done, done);
- });
-
- it('Remove all parent roles from role "child" with no parents', function (done) {
- acl.removeRoleParents("child")
- .then(function () {
- return acl.whatResources("child");
- })
- .then(function (resources) {
- assert.notProperty(resources, "x");
- })
- .done(done, done);
- });
-
- it('Remove parent role "parent1" from role "child" with no parents', function (done) {
- acl.removeRoleParents("child", "parent1")
- .then(function () {
- return acl.whatResources("child");
- })
- .then(function (resources) {
- assert.notProperty(resources, "x");
- })
- .done(done, done);
- });
-
- it("Operation uses a callback when removing all parent roles", function (done) {
- acl.removeRoleParents("child", function (err) {
- assert.ifError(err);
- done();
- });
+ it('Remove parent role "parentX" from role "child"', async function () {
+ await acl.removeRoleParents("child", "parentX");
+
+ let resources = await acl.whatResources("child");
+
+ assert.equal(resources.x.length, 5);
+ assert(resources.x.includes("read1"));
+ assert(resources.x.includes("read2"));
+ assert(resources.x.includes("read3"));
+ assert(resources.x.includes("read4"));
+ assert(resources.x.includes("read5"));
+ });
+
+ it('Remove parent role "parent1" from role "child"', async function () {
+ await acl.removeRoleParents("child", "parent1");
+
+ let resources = await acl.whatResources("child");
+
+ assert.equal(resources.x.length, 4);
+ assert(resources.x.includes("read2"));
+ assert(resources.x.includes("read3"));
+ assert(resources.x.includes("read4"));
+ assert(resources.x.includes("read5"));
+ });
+
+ it('Remove parent roles "parent2" & "parent3" from role "child"', async function () {
+ await acl.removeRoleParents("child", ["parent2", "parent3"]);
+
+ let resources = await acl.whatResources("child");
+
+ assert.equal(resources.x.length, 2);
+ assert(resources.x.includes("read4"));
+ assert(resources.x.includes("read5"));
+ });
+
+ it('Remove all parent roles from role "child"', async function () {
+ await acl.removeRoleParents("child");
+
+ let resources = await acl.whatResources("child");
+
+ assert(!resources.x);
+ });
+
+ it('Remove all parent roles from role "child" with no parents', async function () {
+ await acl.removeRoleParents("child");
+
+ let resources = await acl.whatResources("child");
+
+ assert(!resources.x);
+ });
+
+ it('Remove parent role "parent1" from role "child" with no parents', async function () {
+ await acl.removeRoleParents("child", "parent1");
+
+ let resources = await acl.whatResources("child");
+
+ assert(!resources.x);
+ });
+
+ it("Operation removing all parent roles", async function () {
+ await acl.removeRoleParents("child");
});
});
describe("removeResource", function () {
- it("Remove resource blogs", function (done) {
- var acl = new Acl(backend);
- acl.removeResource("blogs", function (err) {
- assert.ifError(err);
- done();
- });
+ it("Remove resource blogs", async function () {
+ const acl = new Acl(backend);
+
+ await acl.removeResource("blogs");
});
- it("Remove resource users", function (done) {
- var acl = new Acl(backend);
- acl.removeResource("users", function (err) {
- assert.ifError(err);
- done();
- });
+ it("Remove resource users", async function () {
+ const acl = new Acl(backend);
+
+ await acl.removeResource("users");
});
});
describe("allowedPermissions", function () {
- it("What permissions has james over blogs?", function (done) {
- var acl = new Acl(backend);
- acl.allowedPermissions("james", "blogs", function (err, permissions) {
- assert.isNull(err);
- assert.property(permissions, "blogs");
- assert(permissions.blogs.length === 0);
- done();
- });
+ it("What permissions has james over blogs?", async function () {
+ const acl = new Acl(backend);
+
+ const permissions = await acl.allowedPermissions("james", "blogs");
+
+ assert(permissions.blogs);
+ assert(permissions.blogs.length === 0);
});
- it("What permissions has userId=4 over blogs?", function (done) {
- var acl = new Acl(backend);
- acl.allowedPermissions(4, "blogs").then(function (permissions) {
- assert.property(permissions, "blogs");
- assert(permissions.blogs.length === 0);
- done();
- }, done);
+
+ it("What permissions has userId=4 over blogs?", async function () {
+ const acl = new Acl(backend);
+
+ const permissions = await acl.allowedPermissions("4", "blogs");
+
+ assert(permissions.blogs);
+ assert(permissions.blogs.length === 0);
});
});
describe("whatResources", function () {
- it('What resources have "baz" some rights on after removed blogs?', function (done) {
- var acl = new Acl(backend);
- acl.whatResources("baz", function (err, resources) {
- assert.ifError(err);
- assert.isObject(resources);
- assert(Object.keys(resources).length === 0);
-
- done();
- });
+ it('What resources have "baz" some rights on after removed blogs?', async function () {
+ const acl = new Acl(backend);
+
+ const resources = await acl.whatResources("baz");
+
+ assert(_.isPlainObject(resources));
+ assert(Object.keys(resources).length === 0);
});
- it('What resources have "admin" some rights on after removed users resource?', function (done) {
- var acl = new Acl(backend);
- acl.whatResources("admin", function (err, resources) {
- assert.ifError(err);
- assert.isFalse("users" in resources);
- assert.isFalse("blogs" in resources);
+ it('What resources have "admin" some rights on after removed users resource?', async function () {
+ const acl = new Acl(backend);
- done();
- });
+ const resources = await acl.whatResources("admin");
+
+ assert(!("users" in resources));
+ assert(!("blogs" in resources));
});
});
describe("Remove user roles", function () {
- it("Remove role guest from joed", function (done) {
- var acl = new Acl(backend);
- acl.removeUserRoles("joed", "guest", function (err) {
- assert.ifError(err);
- done();
- });
+ it("Remove role guest from joed", async function () {
+ const acl = new Acl(backend);
+
+ await acl.removeUserRoles("joed", "guest");
});
- it("Remove role guest from userId=0", function (done) {
- var acl = new Acl(backend);
- acl.removeUserRoles(0, "guest", function (err) {
- assert.ifError(err);
- done();
- });
+ it("Remove role guest from userId=0", async function () {
+ const acl = new Acl(backend);
+
+ await acl.removeUserRoles("0", "guest");
});
- it("Remove role admin from harry", function (done) {
- var acl = new Acl(backend);
- acl.removeUserRoles("harry", "admin", function (err) {
- assert.ifError(err);
- done();
- });
+ it("Remove role admin from harry", async function () {
+ const acl = new Acl(backend);
+
+ await acl.removeUserRoles("harry", "admin");
});
- it("Remove role admin from userId=2", function (done) {
- var acl = new Acl(backend);
- acl.removeUserRoles(2, "admin", function (err) {
- assert.ifError(err);
- done();
- });
+ it("Remove role admin from userId=2", async function () {
+ const acl = new Acl(backend);
+
+ await acl.removeUserRoles("2", "admin");
});
});
describe("Were roles removed?", function () {
- it("What permissions has harry over forums and blogs?", function (done) {
- var acl = new Acl(backend);
- acl.allowedPermissions("harry", ["forums", "blogs"], function (err, permissions) {
- assert.ifError(err);
- assert.isObject(permissions);
- assert(permissions.forums.length === 0);
- done();
- });
- it("What permissions has userId=2 over forums and blogs?", function (done) {
- var acl = new Acl(backend);
- acl.allowedPermissions(2, ["forums", "blogs"], function (err, permissions) {
- assert.ifError(err);
- assert.isObject(permissions);
- assert(permissions.forums.length === 0);
- done();
- });
- });
+ it("What permissions has harry over forums and blogs?", async function () {
+ const acl = new Acl(backend);
+
+ const permissions = await acl.allowedPermissions("harry", ["forums", "blogs"]);
+
+ assert(_.isPlainObject(permissions));
+ assert(permissions.forums.length === 0);
+ });
+
+ it("What permissions has userId=2 over forums and blogs?", async function () {
+ const acl = new Acl(backend);
+
+ const permissions = await acl.allowedPermissions("2", ["forums", "blogs"]);
+
+ assert(_.isPlainObject(permissions));
+ assert(permissions.forums.length === 0);
});
});
describe("Github issue #55: removeAllow is removing all permissions.", function () {
- it("Add roles/resources/permissions", function () {
- var acl = new Acl(backend);
-
- return acl
- .addUserRoles("jannette", "member")
- .then(function () {
- return acl.allow("member", "blogs", ["view", "update"]);
- })
- .then(function () {
- return acl.isAllowed("jannette", "blogs", "view", function (err, allowed) {
- expect(allowed).to.be.eql(true);
- });
- })
- .then(function () {
- return acl.removeAllow("member", "blogs", "update");
- })
- .then(function () {
- return acl.isAllowed("jannette", "blogs", "view", function (err, allowed) {
- expect(allowed).to.be.eql(true);
- });
- })
- .then(function () {
- return acl.isAllowed("jannette", "blogs", "update", function (err, allowed) {
- expect(allowed).to.be.eql(false);
- });
- })
- .then(function () {
- return acl.removeAllow("member", "blogs", "view");
- })
- .then(function () {
- return acl.isAllowed("jannette", "blogs", "view", function (err, allowed) {
- expect(allowed).to.be.eql(false);
- });
- });
+ it("Add roles/resources/permissions", async function () {
+ const acl = new Acl(backend);
+
+ await acl.addUserRoles("jannette", "member");
+ await acl.allow("member", "blogs", ["view", "update"]);
+ assert(await acl.isAllowed("jannette", "blogs", "view"));
+
+ await acl.removeAllow("member", "blogs", "update");
+ assert(await acl.isAllowed("jannette", "blogs", "view"));
+
+ assert(!(await acl.isAllowed("jannette", "blogs", "update")));
+
+ await acl.removeAllow("member", "blogs", "view");
+ assert(!(await acl.isAllowed("jannette", "blogs", "view")));
});
});
describe('Github issue #32: Removing a role removes the entire "allows" document.', function () {
- it("Add roles/resources/permissions", function (done) {
- var acl = new Acl(backend);
-
- acl.allow(["role1", "role2", "role3"], ["res1", "res2", "res3"], ["perm1", "perm2", "perm3"], function (
- err
- ) {
- assert.ifError(err);
- done();
- });
+ it("Add roles/resources/permissions", async function () {
+ const acl = new Acl(backend);
+
+ await acl.allow(["role1", "role2", "role3"], ["res1", "res2", "res3"], ["perm1", "perm2", "perm3"]);
});
- it("Add user roles and parent roles", function (done) {
- var acl = new Acl(backend);
+ it("Add user roles and parent roles", async function () {
+ const acl = new Acl(backend);
- acl.addUserRoles("user1", "role1", function (err) {
- assert.ifError(err);
+ await acl.addUserRoles("user1", "role1");
- acl.addRoleParents("role1", "parentRole1", function (err) {
- assert.ifError(err);
- done();
- });
- });
+ await acl.addRoleParents("role1", "parentRole1");
});
- it("Add user roles and parent roles", function (done) {
- var acl = new Acl(backend);
+ it("Add user roles and parent roles", async function () {
+ const acl = new Acl(backend);
- acl.addUserRoles(1, "role1", function (err) {
- assert.ifError(err);
+ await acl.addUserRoles("1", "role1");
- acl.addRoleParents("role1", "parentRole1", function (err) {
- assert.ifError(err);
- done();
- });
- });
+ await acl.addRoleParents("role1", "parentRole1");
});
- it("Verify that roles have permissions as assigned", function (done) {
- var acl = new Acl(backend);
+ it("Verify that roles have permissions as assigned", async function () {
+ const acl = new Acl(backend);
- acl.whatResources("role1", function (err, res) {
- assert.ifError(err);
- assert.deepEqual(res.res1.sort(), ["perm1", "perm2", "perm3"]);
+ let res = await acl.whatResources("role1");
+ assert.deepEqual(res.res1.sort(), ["perm1", "perm2", "perm3"]);
- acl.whatResources("role2", function (err, res) {
- assert.ifError(err);
- assert.deepEqual(res.res1.sort(), ["perm1", "perm2", "perm3"]);
- done();
- });
- });
+ res = await acl.whatResources("role2");
+ assert.deepEqual(res.res1.sort(), ["perm1", "perm2", "perm3"]);
});
- it('Remove role "role1"', function (done) {
- var acl = new Acl(backend);
+ it('Remove role "role1"', async function () {
+ const acl = new Acl(backend);
- acl.removeRole("role1", function (err) {
- assert.ifError(err);
- done();
- });
+ await acl.removeRole("role1");
});
- it('Verify that "role1" has no permissions and "role2" has permissions intact', function (done) {
- var acl = new Acl(backend);
+ it('Verify that "role1" has no permissions and "role2" has permissions intact', async function () {
+ const acl = new Acl(backend);
- acl.removeRole("role1", function (err) {
- assert.ifError(err);
+ await acl.removeRole("role1");
- acl.whatResources("role1", function (err, res) {
- assert(Object.keys(res).length === 0);
+ let res = await acl.whatResources("role1");
+ assert(Object.keys(res).length === 0);
- acl.whatResources("role2", function (err, res) {
- assert.deepEqual(res.res1.sort(), ["perm1", "perm2", "perm3"]);
- done();
- });
- });
- });
+ res = await acl.whatResources("role2");
+ assert.deepEqual(res.res1.sort(), ["perm1", "perm2", "perm3"]);
});
});
});