UNPKG

@superawesome/permissions

Version:

Fine grained permissions / access control with ownerships & attribute picking, done right.

94 lines 4.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.consolidatePermissionDefinitions = exports.mergeCompatibleGrants = exports.deleteDefinedGrants = exports.consolidatePermissions = exports.areCompatibleOwnHooks = exports.mergeTwoPermissions = void 0; // 3rd const _ = require("lodash"); const _f = require("lodash/fp"); const accesscontrol_1 = require("accesscontrol"); // own const utils_1 = require("./utils"); const logger_1 = require("./logger"); exports.mergeTwoPermissions = (receivingPD, pd) => { // @todo: throw if !canPermissionsBeMerged const result = Object.assign(Object.assign(Object.assign({}, receivingPD), pd), { grant: Object.assign(Object.assign({}, receivingPD.grant), pd.grant) }); return result; }; exports.areCompatibleOwnHooks = (pd1, pd2) => (pd1.isOwner === pd2.isOwner || !pd1.isOwner || !pd2.isOwner) && (pd1.listOwned === pd2.listOwned || !pd1.listOwned || !pd2.listOwned); exports.consolidatePermissions = _f.reduce((consolidatedCPDs, cpd) => { const matchingPds = _.filter(consolidatedCPDs, (consolidatedCpd) => utils_1.isArraySetEqual(consolidatedCpd.roles, cpd.roles, _.isEqual) && consolidatedCpd.resource === cpd.resource && exports.areCompatibleOwnHooks(consolidatedCpd, cpd)); if (_.isEmpty(matchingPds)) { consolidatedCPDs.push(cpd); } else if (matchingPds.length === 1) { // consolidate the two const idx = _.indexOf(consolidatedCPDs, matchingPds[0]); consolidatedCPDs[idx] = exports.mergeTwoPermissions(consolidatedCPDs[idx], cpd); } else throw new Error('Something is wrong with _internalPermissionDefinitions - we have duplicated consolidated PDs'); return consolidatedCPDs; }); exports.deleteDefinedGrants = _f.reduce( // refactor, not needs to be reducer, just a visitor to delete grant props (consolidatedCPDs, cpd) => { const [accessControl] = _.isEmpty(consolidatedCPDs) ? [new accesscontrol_1.AccessControl()] // dummy : utils_1.buildAccessControl(consolidatedCPDs); // check if grant for all roles is already defined and delete it! _.each(cpd.grant, (attributes, action) => { const grantExists = _.every(cpd.roles, (role) => { try { const perm = accessControl.permission({ action, resource: cpd.resource, role, }); return perm.granted && _.isEqual(perm.attributes, attributes); } catch (error) { return false; // ignore errors of roles missing etc, simply means its not defined } }); if (grantExists) delete cpd.grant[action]; }); // add anyway, it will be eliminated if it ends up empty consolidatedCPDs.push(cpd); return consolidatedCPDs; }); exports.mergeCompatibleGrants = (pds) => { // for every parent PD, find ones below it that have the a super set with the same exact grants for (let parentIdx = 0; parentIdx < pds.length; parentIdx++) { const parentPd = pds[parentIdx]; for (let childIdx = parentIdx + 1; childIdx < pds.length; childIdx++) { const childPd = pds[childIdx]; if (parentPd.resource === childPd.resource && utils_1.isLike(parentPd.grant, childPd.grant)) { // delete ALL child grants that exist in parent (and are seen as moved there) // add all roles of child to parent parentPd.roles = _.uniq([...parentPd.roles, ...childPd.roles]); _.each(_.keys(parentPd.grant), (actionKey) => delete childPd.grant[actionKey]); } } } return pds; }; exports.consolidatePermissionDefinitions = (filter, consolidateFlag) => _f.flow(_f.filter(filter), _f.tap((ipds) => { if (_.some(ipds, utils_1.hasSomeOwnGrant)) { const msg = `getDefinitions() with consolidate = true PermissionDefinitions is **experimental** and NOT compatible when Possession.own is used ('force' is needed)! Use "getDefinitions()" with consolidate = false to avoid consolidations.`; if (consolidateFlag === true) throw new Error(`SA-Permissions: ${msg} Use "getDefinitions()" with consolidate = 'force' to proceed with consolidations of own, at your own risk.`); if (consolidateFlag === 'force') logger_1.getLogger().warn(msg); } }), exports.consolidatePermissions([]), exports.deleteDefinedGrants([]), exports.mergeCompatibleGrants, _f.map(_f.omitBy( // omit keys of filter & empty ones (val, key) => (_.isEmpty(val) && !_.isFunction(val)) || (_.isObjectLike(filter) && (_.isEqual(filter[key], val) || utils_1.isArraySetEqual(filter[key], val))))), // eliminate PDs with empty grants _f.reject((pd) => _.isEmpty(pd.grant))); //# sourceMappingURL=consolidations.js.map