UNPKG

@parthar/rbac

Version:

Role Based Access Control

126 lines (103 loc) 3.04 kB
"use strict"; // Permission => Resource & Actions // store: [{res: "resource-name", acts: ["action-1", "action-2", ...]}] const DELIMITER = "%"; const RES_REGEX = new RegExp(`^[^${DELIMITER}\\s]+$`); const PERM_REGEX = new RegExp(`^([^${DELIMITER}]+)${DELIMITER}(.*)$`); function makeString(res, act) { return res + DELIMITER + act; } function addPerms2store(store, resource, actions) { let perm; perm = store.find(function find(ele) { return ele.res === resource; }); // sorted & unique actions if (perm) { perm.acts = Array.from(new Set(perm.acts.concat(actions).sort())); } else { store.push({ "res": resource, "acts": Array.from(new Set(Array.from(actions).sort())) }); } } function strings2store(store, arr) { arr.forEach(function each(str) { let matches = str.match(PERM_REGEX); addPerms2store(store, matches[1], [matches[2]]); // eslint-disable-line no-magic-numbers }); return store; } function store2strings(store) { let strs = []; store.forEach(function eachPerm(perms) { perms.acts.forEach(function eachAct(act) { strs.push(makeString(perms.res, act)); }); }); return strs.sort(); } class Permissions { static makeString(res, act) { return makeString(res, act); } constructor(permStrs) { this._store = []; if (permStrs) { strings2store(this._store, permStrs); } } listResources() { return this._store.map(e => e.res).sort(); } actions4resource(res) { let perm = this._store.find(function find(ele) { return ele.res === res; }); return perm ? perm.acts : null; } export() { return store2strings(this._store); } can(res, act) { let actions; if (this.listResources().indexOf("*") >= 0) { // eslint-disable-line no-magic-numbers return true; } actions = this.actions4resource(res); if (actions) { return actions.indexOf("*") >= 0 || actions.indexOf(act) >= 0; // eslint-disable-line no-magic-numbers } return false; } // fluent API resource(res) { if (!RES_REGEX.test(res)) { throw new Error("badly-formatted resource token"); } this._resource = res; return this; } actions(arr) { if (!this._resource) { throw new Error("set resource before setting actions"); } addPerms2store(this._store, this._resource, arr); delete this._resource; return this; } include(obj) { strings2store(this._store, obj.export()); return this; } exclude(obj) { let base = this.export(); let excl = obj.export(); let diff = base.filter(x => !excl.includes(x)); this._store = []; strings2store(this._store, diff); return this; } } module.exports = Permissions;