rolet
Version:
Powerful user permission management
193 lines • 6.02 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Rolet = exports.DEFAULT_ROOT = exports.debug_rolet = void 0;
const debug_1 = require("debug");
const lodash_1 = require("lodash");
const lodash_uniq_1 = __importDefault(require("lodash.uniq"));
const conflict_role_name_1 = require("./error/conflict_role_name");
const rnode_1 = require("./rnode");
exports.debug_rolet = (0, debug_1.debug)('rolet');
const __ = exports.debug_rolet.extend('Rolet');
exports.DEFAULT_ROOT = '_public_';
/**
* Role and permission manager
*/
class Rolet {
constructor(tree, opt) {
this.opt = Object.assign({ root_name: exports.DEFAULT_ROOT }, opt);
this.init(tree);
}
/**
* Analyze Rnode tree and create cache
*/
analyze() {
let roles = [], actions = [];
const r = this.root;
r.walk_down(node => {
const name = node.role;
if (roles.includes(name)) {
throw new conflict_role_name_1.Conflict_role_name(name);
}
else {
roles.push(name);
}
actions = actions.concat(node.actions || []);
});
this.roles = roles;
this.actions = actions;
}
/**
* Collect complete roles upward through ancestors
*/
calc_complete_actions(roles) {
__('calc_complete_actions() input %O', roles);
roles = this.roles_normalize(roles);
let r = [];
for (const it of roles) {
r = r.concat(this._calc_complete_values_single(it, 'actions') || []);
}
r = (0, lodash_uniq_1.default)((0, lodash_1.flatten)(r));
__('calc_complete_actions() output %O', r);
return r;
}
/**
* Collect complete roles upward through ancestors
*/
calc_complete_roles(roles) {
roles = this.roles_normalize(roles);
let r = [];
for (const it of roles) {
r = r.concat(this._calc_complete_values_single(it, 'role') || []);
}
return (0, lodash_uniq_1.default)(r);
}
/**
* Collect complete roles upward through ancestors
*/
calc_complete_values(roles, path, direction = 'up') {
roles = this.roles_normalize(roles);
let r = [];
for (const it of roles) {
r = r.concat(this._calc_complete_values_single(it, path) || []);
}
return (0, lodash_uniq_1.default)(r);
}
/**
* Permission check
* @param roles
* @param {T_action} action
*/
can(roles, action) {
var _a;
roles = this.roles_normalize(roles);
if (this.opt.super && roles.includes(this.opt.super)) {
return true;
}
for (let it of roles) {
const actions = (_a = this
.find_by_role(it)) === null || _a === void 0 ? void 0 : _a.collect_actions();
if (!(actions === null || actions === void 0 ? void 0 : actions.length)) {
continue;
}
for (let it2 of actions) {
if (it2 instanceof RegExp && typeof action === 'string' && it2.test(action)) {
return true;
}
else {
if (it2 === action) {
return true;
}
}
}
}
return false;
}
find_by_role(role_name) {
return rnode_1.Rnode.find_by_role(this.root, role_name);
}
/**
* Init rolet
* @param node
*/
init(node) {
this.load(node);
this.analyze();
}
/**
* Is {roles} a {role}?
*
* is(['admin'], 'admin') --> true
* is(['admin'], '_public_') --> true
* is(['admin', 'employee'], 'employee') --> true
*
* is(['employee'], 'admin') --> false
* is(['_public_'], 'admin') --> false
* is(['_public_'], 'employee') --> false
*/
is(roles, role, { all } = { all: false }) {
roles = this.roles_normalize(roles);
if (this.opt.super && roles.includes(this.opt.super)) {
return true;
}
for (const it of roles) {
const collection = this._calc_complete_values_single(it, 'role');
if (!(collection === null || collection === void 0 ? void 0 : collection.length)) {
continue;
}
if (all) {
if (!collection.includes(role)) {
return false;
}
}
else {
if (collection.includes(role)) {
return true;
}
}
}
return !!all;
}
/**
* Define raw tree and create rnodes
*/
load(node) {
this.raw = Object.freeze(node);
this.root = new rnode_1.Rnode(this.opt.root_name, node);
}
roles_normalize(roles) {
if (!roles) {
roles = [];
}
if (!Array.isArray(roles)) {
roles = [roles];
}
const root = this.opt.root_name;
if (!roles.includes(root)) {
roles.push(root);
}
return roles;
}
/**
* Collect roles upward through ancestors
*/
_calc_complete_values_single(role, path) {
__('_calc_complete_values_single() input:', arguments);
let node;
let r;
if (role === this.opt.super) {
node = this.root;
r = node === null || node === void 0 ? void 0 : node.collect_values(path, 'down');
}
else {
node = rnode_1.Rnode.find_by_role(this.root, role);
r = node === null || node === void 0 ? void 0 : node.collect_values(path);
}
__('_calc_complete_values_single() output:', r);
return r;
}
}
exports.Rolet = Rolet;
//# sourceMappingURL=rolet.js.map