UNPKG

@superawesome/permissions

Version:

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

434 lines (423 loc) 12.3 kB
import * as _ from 'lodash'; import { EPossession } from '../types'; import { Permissions } from '../Permissions'; import { eachWithOnly } from './utils/test.utils'; import { PermissionDefinition } from '../PermissionDefinitions'; import { setLogger } from '../logger'; const ignoreOnly = false; const ignoreSkip = false; const invertOnly = false; const isOwner = _.noop; const listOwned = _.noop; setLogger(null); describe('getDefinitions.spec', () => { eachWithOnly( [ { // only: true, descr: 'filters PDs & excludes matching props in `filters` from resulted PDs (if `filters` are an {})', filters: { roles: ['ADMIN', 'EMPLOYEE_MANAGER', 'EMPLOYEE'], // in different order works also :-) resource: 'document', }, definitions: [ { roles: ['EMPLOYEE', 'EMPLOYEE_MANAGER', 'ADMIN'], resource: 'document', isOwner, listOwned, grant: { read: ['*', '!price', '!confidential'], }, }, { roles: ['EMPLOYEE_MANAGER', 'ADMIN', 'EMPLOYEE'], // note: roles in diff order is fine (1st one wins) resource: 'document', isOwner, listOwned, grant: { 'create:own': ['*', '!price', '!confidential'], }, }, { // this PD is omitted due to filters roles: ['EMPLOYEE_MANAGER', 'EMPLOYEE'], resource: 'comment', isOwner, listOwned, grant: { 'fooaction:own': ['*'], }, }, ], expected: [ { // eliminated cause its in filters // roles: ['EMPLOYEE', 'EMPLOYEE_MANAGER'], // resource: 'document', isOwner, listOwned, grant: { 'read:any': ['*', '!price', '!confidential'], 'create:own': ['*', '!price', '!confidential'], }, }, ], }, { // only: true, descr: 'doesnt consolidate definitions that are granted/denied to more role(s)', defaults: { resource: 'document' }, definitions: [ { roles: ['EMPLOYEE', 'EMPLOYEE_MANAGER', 'SOME_OTHER_ROLE'], grant: { read: ['*', '!price', '!confidential'], }, }, { roles: ['EMPLOYEE_MANAGER', 'EMPLOYEE'], grant: { create: ['*', '!price', '!confidential'], }, }, ], expected: [ { roles: ['EMPLOYEE', 'EMPLOYEE_MANAGER', 'SOME_OTHER_ROLE'], resource: 'document', grant: { 'read:any': ['*', '!price', '!confidential'], }, }, { roles: ['EMPLOYEE_MANAGER', 'EMPLOYEE'], resource: 'document', grant: { 'create:any': ['*', '!price', '!confidential'], }, }, ], }, // mergeCompatibleGrants { // only: true, descr: 'merge grants by joining compatible roles', definitions: [ { roles: ['EMPLOYEE', 'EMPLOYEE_MANAGER'], resource: 'document', grant: { 'read:any': ['*'], 'update:any': ['*'], 'create:any': ['*'], }, }, { roles: ['ANOTHER_ROLE1', 'ANOTHER_ROLE2'], resource: 'document', grant: { 'read:any': ['*'], 'update:any': ['*'], 'create:any': ['*'], anotherAction: ['*'], }, }, ], expected: [ { roles: ['EMPLOYEE', 'EMPLOYEE_MANAGER', 'ANOTHER_ROLE1', 'ANOTHER_ROLE2'], resource: 'document', grant: { 'read:any': ['*'], 'update:any': ['*'], 'create:any': ['*'], }, }, { roles: ['ANOTHER_ROLE1', 'ANOTHER_ROLE2'], resource: 'document', grant: { 'anotherAction:any': ['*'], }, }, ], }, { // only: true, descr: 'doesnt merge incompatible grants', definitions: [ { roles: ['EMPLOYEE', 'EMPLOYEE_MANAGER'], resource: 'document', grant: { 'read:any': ['*'], 'update:any': ['*'], 'create:any': ['*'], incompatibleAction: ['*'], }, }, { roles: ['ANOTHER_ROLE'], resource: 'document', grant: { 'read:any': ['*'], 'update:any': ['*'], 'create:any': ['*'], anotherAction: ['*'], }, }, ], expected: [ { roles: ['EMPLOYEE', 'EMPLOYEE_MANAGER'], resource: 'document', grant: { 'read:any': ['*'], 'update:any': ['*'], 'create:any': ['*'], 'incompatibleAction:any': ['*'], }, }, { roles: ['ANOTHER_ROLE'], resource: 'document', grant: { 'read:any': ['*'], 'update:any': ['*'], 'create:any': ['*'], 'anotherAction:any': ['*'], }, }, ], }, { descr: 'consolidates definitions that are granted/denied to the exact same role(s) & resources', defaults: { resource: 'document' }, definitions: [ { roles: ['EMPLOYEE', 'EMPLOYEE_MANAGER'], grant: { read: ['*', '!price', '!confidential'], }, }, { roles: ['EMPLOYEE_MANAGER', 'EMPLOYEE'], isOwner, listOwned, grant: { read: ['*', '!price', '!confidential'], 'create:own': ['*', '!price', '!confidential'], }, }, { roles: ['EMPLOYEE', 'EMPLOYEE_MANAGER'], possession: EPossession.own, isOwner, listOwned, grant: { read: ['*'], update: ['*', '!price', '!confidential'], delete: ['*'], 'list:any': ['title', 'date'], }, }, { roles: ['EMPLOYEE', 'EMPLOYEE_MANAGER'], resource: 'comment', grant: { report: ['*'], }, }, ], expected: [ { roles: ['EMPLOYEE', 'EMPLOYEE_MANAGER'], resource: 'document', isOwner, listOwned, grant: { 'read:any': ['*', '!price', '!confidential'], 'read:own': ['*'], 'list:any': ['title', 'date'], 'create:own': ['*', '!price', '!confidential'], 'delete:own': ['*'], 'update:own': ['*', '!price', '!confidential'], }, }, { roles: ['EMPLOYEE', 'EMPLOYEE_MANAGER'], resource: 'comment', grant: { 'report:any': ['*'], }, }, ], }, { descr: 'deletes Defined Grants to eliminate PDs', definitions: [ { roles: ['EMPLOYEE_MANAGER', 'EMPLOYEE', 'ANOTHER_ROLE'], resource: 'comment', isOwner, listOwned, grant: { 'baraction:own': ['*'], 'fooaction:own': ['*'], list: ['*'], }, }, { // whole object should be eliminated, cause all it's grants are included above roles: ['EMPLOYEE', 'EMPLOYEE_MANAGER'], resource: 'comment', isOwner, listOwned, grant: { 'baraction:own': ['*'], 'fooaction:own': ['*'], }, }, ], expected: [ { roles: ['EMPLOYEE_MANAGER', 'EMPLOYEE', 'ANOTHER_ROLE'], resource: 'comment', isOwner, listOwned, grant: { 'baraction:own': ['*'], 'fooaction:own': ['*'], 'list:any': ['*'], }, }, ], }, { descr: 'consolidates all PermissionDefinitions', definitions: [ { roles: ['EMPLOYEE', 'EMPLOYEE_MANAGER', 'ADMIN'], resource: 'document', grant: { 'read:any': ['*', '!price', '!confidential'], }, }, { roles: ['EMPLOYEE_MANAGER', 'ADMIN', 'EMPLOYEE'], // note: roles in diff order is fine (1st one wins) resource: 'document', isOwner, listOwned, grant: { 'read:own': ['*'], // added as well as any @todo: must be obeyed for ownership 'create:own': ['*', '!price', '!confidential'], }, }, { roles: ['EMPLOYEE_MANAGER', 'EMPLOYEE'], resource: 'comment', isOwner, listOwned, grant: { 'baraction:own': ['*'], 'fooaction:own': ['*'], list: ['*'], }, }, { // whole object should be eliminated, cause all it's grants are included above roles: ['EMPLOYEE', 'EMPLOYEE_MANAGER'], resource: 'comment', isOwner, listOwned, grant: { 'baraction:own': ['*'], 'fooaction:own': ['*'], }, }, { roles: ['EMPLOYEE_MANAGER'], resource: 'comment', isOwner, listOwned, grant: { managerAction: ['*'], // grant stays, cause its NOT included above 'baraction:own': ['*'], // grant eliminated, cause included above 'fooaction:own': ['*'], // grant eliminated, cause included above }, }, ], expected: [ { roles: ['EMPLOYEE_MANAGER', 'ADMIN', 'EMPLOYEE'], resource: 'document', isOwner, listOwned, grant: { 'read:any': ['*', '!price', '!confidential'], 'read:own': ['*'], 'create:own': ['*', '!price', '!confidential'], }, }, { roles: ['EMPLOYEE', 'EMPLOYEE_MANAGER'], resource: 'comment', isOwner, listOwned, grant: { 'baraction:own': ['*'], 'fooaction:own': ['*'], 'list:any': ['*'], }, }, { roles: ['EMPLOYEE_MANAGER'], resource: 'comment', isOwner, listOwned, grant: { 'managerAction:any': ['*'], // grant stays, cause its NOT included above }, }, ], }, ], ( { skip, only, descr, definitions, defaults = {}, expected, filters = {}, }: { skip?: boolean; only?: boolean; descr: string; definitions: PermissionDefinition[]; defaults?: {}; expected: any[]; filters?: {}; }, onlyMode: boolean ) => { only = invertOnly ? !only : only; if ((skip && !ignoreSkip) || (!ignoreOnly && onlyMode && !only)) { it.skip(descr, () => {}); } else { it(descr, () => { const permissions = new Permissions({ permissionDefinitions: definitions, permissionDefinitionDefaults: defaults, }).build(); const result = permissions.getDefinitions(filters, 'force'); expect(result).toIncludeSameMembers(expected); }); } } ); });