accesscontrol-re
Advanced tools
Comparing version 2.0.0 to 3.0.1
@@ -1,7 +0,10 @@ | ||
import { AccessControl, IAccessInfo } from 'accesscontrol'; | ||
import * as _ from 'lodash'; | ||
import { IAccessInfo, IQueryInfo, Permission } from 'accesscontrol'; | ||
export declare class AccessControlRe { | ||
private accessInfos; | ||
addAccessInfo: (accessInfo: IAccessInfo | IAccessInfo[]) => void; | ||
build: () => AccessControl; | ||
addCustomActions: (customActions: string[]) => void; | ||
private _accessControl; | ||
constructor(accessInfo?: IAccessInfo | IAccessInfo[]); | ||
addAccessInfo: (accessInfo: IAccessInfo | IAccessInfo[]) => AccessControlRe; | ||
build: () => AccessControlRe; | ||
permission: (queryInfo: IQueryInfo) => Permission; | ||
getRoles: () => string[]; | ||
@@ -11,2 +14,2 @@ getResources: () => string[]; | ||
} | ||
export declare const cleanStarEtc: (a1: {}) => any[]; | ||
export declare const cleanStarEtc: <T>(array: ArrayLike<_.Many<T>>) => any[]; |
@@ -6,7 +6,17 @@ "use strict"; | ||
const accesscontrol_1 = require("accesscontrol"); | ||
const __INTERNAL_DUMMY_ROLE__ = '__INTERNAL_DUMMY_ROLE__'; | ||
const enums_1 = require("accesscontrol/lib/enums"); | ||
const crudActions = [...enums_1.actions]; | ||
const addCustomActions = (customActions) => { | ||
_.each(_.uniq(customActions), customAction => { | ||
customAction = customAction.toLowerCase(); | ||
enums_1.Action[customAction.toUpperCase()] = customAction; | ||
if (!enums_1.actions.includes(customAction)) | ||
enums_1.actions.push(customAction); | ||
}); | ||
}; | ||
class AccessControlRe { | ||
constructor() { | ||
constructor(accessInfo) { | ||
this.accessInfos = []; | ||
this._accessControl = new accesscontrol_1.AccessControl(); | ||
this.addAccessInfo = (accessInfo) => { | ||
@@ -18,2 +28,3 @@ if (!accessInfo || !_.isObject(accessInfo)) | ||
: this.accessInfos.push(accessInfo); | ||
return this; | ||
}; | ||
@@ -24,4 +35,3 @@ this.build = _.once(() => { | ||
const roles = this.getRoles(); | ||
this.addCustomActions(actions); | ||
const ac = new accesscontrol_1.AccessControl(); | ||
addCustomActions(actions.concat(__INTERNAL_DUMMY_ROLE__)); | ||
for (const ai of this.accessInfos) { | ||
@@ -35,31 +45,30 @@ const [action, actionPossession] = ai.action.split(':'); | ||
for (const resourceToGrant of resourcesToGrant) { | ||
const accessInfo = Object.assign({}, ai, { possession: actionPossession || ai.possession || 'any', action: actionToGrant, resource: resourceToGrant, role: rolesToGrant }); | ||
accessInfo.denied ? ac.deny(accessInfo) : ac.grant(accessInfo); | ||
const accessInfo = Object.assign(Object.assign({}, ai), { possession: actionPossession || ai.possession || 'any', action: actionToGrant, resource: resourceToGrant, role: rolesToGrant }); | ||
accessInfo.denied | ||
? this._accessControl.deny(accessInfo) | ||
: this._accessControl.grant(accessInfo); | ||
} | ||
} | ||
this._accessControl.deny({ | ||
action: __INTERNAL_DUMMY_ROLE__, | ||
role: __INTERNAL_DUMMY_ROLE__, | ||
resource: __INTERNAL_DUMMY_ROLE__, | ||
}); | ||
} | ||
return ac.lock(); | ||
this._accessControl.lock(); | ||
return this; | ||
}); | ||
this.addCustomActions = (customActions) => { | ||
_.each(_.uniq(customActions), customAction => { | ||
customAction = customAction.toLowerCase(); | ||
enums_1.Action[customAction.toUpperCase()] = customAction; | ||
if (!enums_1.actions.includes(customAction)) | ||
enums_1.actions.push(customAction); | ||
}); | ||
}; | ||
this.getRoles = () => { | ||
return exports.cleanStarEtc(_.map(this.accessInfos, ai => ai.role)); | ||
}; | ||
this.getResources = () => { | ||
return exports.cleanStarEtc(_.map(this.accessInfos, ai => ai.resource)); | ||
}; | ||
this.getActions = () => { | ||
return exports.cleanStarEtc(_.reduce(this.accessInfos, (actions, accessInfo) => { | ||
const [action] = accessInfo.action.split(':'); | ||
if (action !== '*') | ||
actions.push(action); | ||
return actions; | ||
}, []).concat(crudActions)); | ||
}; | ||
this.permission = (queryInfo) => this._accessControl.permission(Object.assign(Object.assign({}, queryInfo), { role: _.isEmpty(queryInfo.role) ? __INTERNAL_DUMMY_ROLE__ : queryInfo.role })); | ||
this.getRoles = () => exports.cleanStarEtc(_.map(this.accessInfos, ai => ai.role)).sort(); | ||
this.getResources = () => exports.cleanStarEtc(_.map(this.accessInfos, ai => ai.resource)).sort(); | ||
this.getActions = () => exports.cleanStarEtc(_.reduce(this.accessInfos, (actions, accessInfo) => { | ||
const [action] = accessInfo.action.split(':'); | ||
if (action !== '*') | ||
actions.push(action); | ||
return actions; | ||
}, []) | ||
.concat(crudActions) | ||
.sort()); | ||
if (accessInfo) | ||
this.addAccessInfo(accessInfo); | ||
} | ||
@@ -66,0 +75,0 @@ } |
{ | ||
"name": "accesscontrol-re", | ||
"version": "2.0.0", | ||
"version": "3.0.1", | ||
"main": "./build/src/index.js", | ||
@@ -17,3 +17,3 @@ "scripts": { | ||
"dependencies": { | ||
"lodash": "^4.17.11" | ||
"lodash": "^4.17.15" | ||
}, | ||
@@ -24,19 +24,19 @@ "peerDependencies": { | ||
"devDependencies": { | ||
"@types/jest": "^23.3.12", | ||
"@types/lodash": "^4.14.121", | ||
"@types/node": "^10.12.18", | ||
"@types/jest": "^24.0.18", | ||
"@types/lodash": "^4.14.138", | ||
"@types/node": "^10.14.18", | ||
"accesscontrol": "^2.2.1", | ||
"husky": "^1.3.1", | ||
"jest": "~23.6.0", | ||
"jest": "^24.9.0", | ||
"lint-staged": "^7.3.0", | ||
"nodemon": "^1.18.10", | ||
"npm-run-all": "^4.1.5", | ||
"prettier": "1.16.1", | ||
"rimraf": "^2.6.3", | ||
"ts-jest": "~23.10.5", | ||
"tslint": "~5.12.1", | ||
"tslint-config-airbnb": "^5.11.1", | ||
"tslint-config-prettier": "~1.17.0", | ||
"tsutils": "~3.7.0", | ||
"typescript": "^3.3.3" | ||
"prettier": "1.18.2", | ||
"rimraf": "^2.7.1", | ||
"ts-jest": "^24.1.0", | ||
"tslint": "^5.20.0", | ||
"tslint-config-airbnb": "^5.11.2", | ||
"tslint-config-prettier": "^1.18.0", | ||
"tsutils": "^3.17.1", | ||
"typescript": "^3.6.3" | ||
}, | ||
@@ -43,0 +43,0 @@ "engines": { |
@@ -1,2 +0,2 @@ | ||
# Access Control Re v2.0.0 | ||
# Access Control Re v3.0.1 | ||
@@ -37,10 +37,12 @@ A facade enhancing the great javascript [Access Control](https://onury.io/accesscontrol), but with much desired missing features! | ||
- Solving various smaller issues and bugs: | ||
- In **AccessControl**, `AccessControl.grant` is NOT respecting `denied: true` of that `IAccessInfo` (see https://github.com/onury/accesscontrol/issues/67). **AccessControlRe** instead properly handles it they way someone would expect. | ||
- Not respecting `denied: true` of `IAccessInfo` in `AccessControl.grant` - https://github.com/onury/accesscontrol/issues/67 | ||
- In **AccessControl**, `accessControl.permission()` throws an Error `AccessControlError: Invalid role(s): []` when empty roles (eg a User with an empty `roles: []`) is passed in that `IQueryInfo`. | ||
**AccessControlRe** instead silently overcomes it (and returns a `permission.granted === false`). Reasoning is that an empty roles array foR the User, is something normal in the real world (eg a new user without any assigned roles). | ||
## How to use | ||
import { AcccessControlRe } from 'accesscontrol-re';; | ||
import { AccessControl, Access, IAccessInfo } from 'accesscontrol'; | ||
```typescript | ||
import { IAccessInfo, Permission } from 'accesscontrol'; | ||
import { AccessControlRe } from 'accesscontrol-re'; | ||
@@ -58,6 +60,11 @@ const accessInfos: IAccessInfo[] = [ | ||
acre.addAccessInfo(accessInfos); // also accepts a single IAccessInfo | ||
const ac: AccessControl = acre.build(); // can call only `_.once` pre instance! | ||
acre.addAccessInfo(accessInfos); // repeat as many times as needed | ||
acre.build(); // call `build()` to start querying (only `_.once` per instance)! | ||
// you can use `ac.permission()` (and only that!) from now on :-) | ||
const userPerm = ac.permission({ | ||
// the above can be done fluently in one statement | ||
const acre2 = new AccessControlRe(accessInfos).build(); | ||
// From now on, you use `acre.permission()` - there is no need to use anything else from AccessControl :-) | ||
// It has the exact signature & usage as `accessControl.permission` (it delegates to it) and also returns a `Permission` | ||
const userPerm: Permission = acre.permission({ | ||
role: 'user', | ||
@@ -69,11 +76,11 @@ resource: 'comment', | ||
console.log('USER', userPerm.granted); | ||
``` | ||
## Caveats | ||
- Only the `.grant(accessInfo: IAccessInfo)` (implicitly and only through `AccessControlRe::addAccessInfo(accessInfo: IAccessInfo)`) and `ac.permission(queryInfo: IQueryInfo)` are supported for now, not the chained fluent methods like `createAny` & `updateOwn` or the `grantsObject` etc. The upside of this is that you can do anything without just those, and they are cleaner and easier to use for DB or bulk creation & querying of permissions than the fluent ones. | ||
This problem could be solved with an ES6 Proxy, but I wont even bother :-) | ||
- Only the `.grant(accessInfo: IAccessInfo)` (implicitly and only through `AccessControlRe::addAccessInfo(accessInfo: IAccessInfo)`) and `AccessControlRe::permission(queryInfo: IQueryInfo)` are supported for now, not the chained fluent methods like `createAny` & `updateOwn` or the `grantsObject` etc of **AccessControl**. The upside of this is that you can do anything without those, and it is actually cleaner and easier to use and follow for DB or bulk creation & querying of permissions than the fluent ones. | ||
- There is some patching going on, as this is *not a fork* or reworked version of Access Control, just a facade. This is actually a very good point, cause Access Control version 2.x is just in `peerdependencies` so its updates on your local version will be picked up. | ||
- You need to create ALL your grants (i.e add all your `addAccessInfo`) before you can use it & call `.build` to retrieve an ActionControl instance with the grants locked. This is due to the way the `'*'` actions & resources actually work: the `'*'` is forcing all known actions / resources / roles to be created. Also you can call `build()` only `_.once`, it has no effect after that (use `require-clean` if you want a fresh instance :-). | ||
- You need to create ALL your grants (i.e add all your `addAccessInfo()`) before you can use it & call `.build()` to retrieve an ActionControl instance with the grants locked. This is due to the way the `'*'` actions & resources actually work: the `'*'` is forcing all known actions / resources / roles to be created. Also you can call `build()` only `_.once`, it has no effect after that (use `require-clean` if you want a fresh instance :-). | ||
@@ -86,2 +93,34 @@ - @todo: `.extend` is disabled by design and is discouraged, for your own sake. Its evil to use while this is open https://github.com/onury/accesscontrol/issues/34#issuecomment-466387586 - when closed I'll happily add it :-) | ||
## Public API | ||
### constructor AccessControlRe(accessInfo?: IAccessInfo | IAccessInfo[]) | ||
Optionally pass an initial `accessInfo` to add to your instance. | ||
### addAccessInfo(accessInfo: IAccessInfo | IAccessInfo[]): AccessControlRe | ||
Call it as many times as you want (but before calling `.build()`) to add new `accessInfos` to your instance. | ||
### build(): AccessControlRe | ||
You **have to call it** after you've finished adding ALL your `accessInfos`. After calling `.build()` you can't call `.addAccessInfo()` again on that instance. | ||
Internally, it creates the tweaked AccessControl instance that you can start query with `.permission()`. | ||
### permission(queryInfo: IQueryInfo): Permission { | ||
Works like `AccessControl.permission()` - see node_modules/accesscontrol/lib/AccessControl.d.ts | ||
### getRoles(): string[] | ||
Get all available roles (sorted). | ||
### getResources: string[] | ||
Get all available resources (sorted). | ||
### getActions: string[] | ||
Get all available actions (sorted). | ||
## Coming up | ||
@@ -88,0 +127,0 @@ |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
18229
126
139
Updatedlodash@^4.17.15