node_modules ignore

This commit is contained in:
2025-05-08 23:43:47 +02:00
parent e19d52f172
commit 4574544c9f
65041 changed files with 10593536 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
import * as permission from './permission';
export { permission };
//# sourceMappingURL=index.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/domain/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,UAAU,MAAM,cAAc,CAAC;AAE3C,OAAO,EAAE,UAAU,EAAE,CAAC"}

View File

@@ -0,0 +1,8 @@
'use strict';
var index = require('./permission/index.js');
exports.permission = index;
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;"}

View File

@@ -0,0 +1,3 @@
import * as index from './permission/index.mjs';
export { index as permission };
//# sourceMappingURL=index.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";"}

View File

@@ -0,0 +1,26 @@
/// <reference types="lodash" />
import _ from 'lodash/fp';
declare const sanitizePermissionFields: _.LodashPick2x1;
export interface Permission {
action: string;
actionParameters?: Record<string, unknown>;
subject?: string | object | null;
properties?: Record<string, any>;
conditions?: string[];
}
/**
* Create a new permission based on given attributes
*
* @param {object} attributes
*/
declare const create: <T>(object: T | null | undefined) => Pick<Permission, "subject" | "properties" | "conditions"> & Partial<T>;
/**
* Add a condition to a permission
*/
declare const addCondition: import("lodash").CurriedFunction2<string, Permission, Permission>;
/**
* Gets a property or a part of a property from a permission.
*/
declare const getProperty: (...args: any[]) => any;
export { create, sanitizePermissionFields, addCondition, getProperty };
//# sourceMappingURL=index.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/domain/permission/index.ts"],"names":[],"mappings":";AAAA,OAAO,CAAC,MAAM,WAAW,CAAC;AAI1B,QAAA,MAAM,wBAAwB,iBAA4B,CAAC;AAE3D,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC3C,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACjC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACjC,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB;AAWD;;;;GAIG;AACH,QAAA,MAAM,MAAM,6GAAqE,CAAC;AAElF;;GAEG;AACH,QAAA,MAAM,YAAY,mEAQhB,CAAC;AAEH;;GAEG;AACH,QAAA,MAAM,WAAW,yBAKhB,CAAC;AAEF,OAAO,EAAE,MAAM,EAAE,wBAAwB,EAAE,YAAY,EAAE,WAAW,EAAE,CAAC"}

View File

@@ -0,0 +1,41 @@
'use strict';
var _ = require('lodash/fp');
const PERMISSION_FIELDS = [
'action',
'subject',
'properties',
'conditions'
];
const sanitizePermissionFields = _.pick(PERMISSION_FIELDS);
/**
* Creates a permission with default values for optional properties
*/ const getDefaultPermission = ()=>({
conditions: [],
properties: {},
subject: null
});
/**
* Create a new permission based on given attributes
*
* @param {object} attributes
*/ const create = _.pipe(_.pick(PERMISSION_FIELDS), _.merge(getDefaultPermission()));
/**
* Add a condition to a permission
*/ const addCondition = _.curry((condition, permission)=>{
const { conditions } = permission;
const newConditions = Array.isArray(conditions) ? _.uniq(conditions.concat(condition)) : [
condition
];
return _.set('conditions', newConditions, permission);
});
/**
* Gets a property or a part of a property from a permission.
*/ const getProperty = _.curry((property, permission)=>_.get(`properties.${property}`, permission));
exports.addCondition = addCondition;
exports.create = create;
exports.getProperty = getProperty;
exports.sanitizePermissionFields = sanitizePermissionFields;
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.js","sources":["../../../src/domain/permission/index.ts"],"sourcesContent":["import _ from 'lodash/fp';\n\nconst PERMISSION_FIELDS = ['action', 'subject', 'properties', 'conditions'] as const;\n\nconst sanitizePermissionFields = _.pick(PERMISSION_FIELDS);\n\nexport interface Permission {\n action: string;\n actionParameters?: Record<string, unknown>;\n subject?: string | object | null;\n properties?: Record<string, any>;\n conditions?: string[];\n}\n\n/**\n * Creates a permission with default values for optional properties\n */\nconst getDefaultPermission = (): Pick<Permission, 'conditions' | 'properties' | 'subject'> => ({\n conditions: [],\n properties: {},\n subject: null,\n});\n\n/**\n * Create a new permission based on given attributes\n *\n * @param {object} attributes\n */\nconst create = _.pipe(_.pick(PERMISSION_FIELDS), _.merge(getDefaultPermission()));\n\n/**\n * Add a condition to a permission\n */\nconst addCondition = _.curry((condition: string, permission: Permission): Permission => {\n const { conditions } = permission;\n\n const newConditions = Array.isArray(conditions)\n ? _.uniq(conditions.concat(condition))\n : [condition];\n\n return _.set('conditions', newConditions, permission);\n});\n\n/**\n * Gets a property or a part of a property from a permission.\n */\nconst getProperty = _.curry(\n <T extends keyof Permission['properties']>(\n property: T,\n permission: Permission\n ): Permission['properties'][T] => _.get(`properties.${property}`, permission)\n);\n\nexport { create, sanitizePermissionFields, addCondition, getProperty };\n"],"names":["PERMISSION_FIELDS","sanitizePermissionFields","_","pick","getDefaultPermission","conditions","properties","subject","create","pipe","merge","addCondition","curry","condition","permission","newConditions","Array","isArray","uniq","concat","set","getProperty","property","get"],"mappings":";;;;AAEA,MAAMA,iBAAoB,GAAA;AAAC,IAAA,QAAA;AAAU,IAAA,SAAA;AAAW,IAAA,YAAA;AAAc,IAAA;AAAa,CAAA;AAErEC,MAAAA,wBAAAA,GAA2BC,CAAEC,CAAAA,IAAI,CAACH,iBAAAA;AAUxC;;IAGA,MAAMI,oBAAuB,GAAA,KAAkE;AAC7FC,QAAAA,UAAAA,EAAY,EAAE;AACdC,QAAAA,UAAAA,EAAY,EAAC;QACbC,OAAS,EAAA;KACX,CAAA;AAEA;;;;IAKA,MAAMC,MAASN,GAAAA,CAAAA,CAAEO,IAAI,CAACP,CAAEC,CAAAA,IAAI,CAACH,iBAAAA,CAAAA,EAAoBE,CAAEQ,CAAAA,KAAK,CAACN,oBAAAA,EAAAA,CAAAA;AAEzD;;AAEC,UACKO,YAAeT,GAAAA,CAAAA,CAAEU,KAAK,CAAC,CAACC,SAAmBC,EAAAA,UAAAA,GAAAA;IAC/C,MAAM,EAAET,UAAU,EAAE,GAAGS,UAAAA;IAEvB,MAAMC,aAAAA,GAAgBC,KAAMC,CAAAA,OAAO,CAACZ,UAAAA,CAAAA,GAChCH,CAAEgB,CAAAA,IAAI,CAACb,UAAAA,CAAWc,MAAM,CAACN,SACzB,CAAA,CAAA,GAAA;AAACA,QAAAA;AAAU,KAAA;AAEf,IAAA,OAAOX,CAAEkB,CAAAA,GAAG,CAAC,YAAA,EAAcL,aAAeD,EAAAA,UAAAA,CAAAA;AAC5C,CAAA;AAEA;;AAEC,UACKO,WAAcnB,GAAAA,CAAAA,CAAEU,KAAK,CACzB,CACEU,QACAR,EAAAA,UAAAA,GACgCZ,CAAEqB,CAAAA,GAAG,CAAC,CAAC,WAAW,EAAED,QAAAA,CAAS,CAAC,EAAER,UAAAA,CAAAA;;;;;;;"}

View File

@@ -0,0 +1,36 @@
import _ from 'lodash/fp';
const PERMISSION_FIELDS = [
'action',
'subject',
'properties',
'conditions'
];
const sanitizePermissionFields = _.pick(PERMISSION_FIELDS);
/**
* Creates a permission with default values for optional properties
*/ const getDefaultPermission = ()=>({
conditions: [],
properties: {},
subject: null
});
/**
* Create a new permission based on given attributes
*
* @param {object} attributes
*/ const create = _.pipe(_.pick(PERMISSION_FIELDS), _.merge(getDefaultPermission()));
/**
* Add a condition to a permission
*/ const addCondition = _.curry((condition, permission)=>{
const { conditions } = permission;
const newConditions = Array.isArray(conditions) ? _.uniq(conditions.concat(condition)) : [
condition
];
return _.set('conditions', newConditions, permission);
});
/**
* Gets a property or a part of a property from a permission.
*/ const getProperty = _.curry((property, permission)=>_.get(`properties.${property}`, permission));
export { addCondition, create, getProperty, sanitizePermissionFields };
//# sourceMappingURL=index.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.mjs","sources":["../../../src/domain/permission/index.ts"],"sourcesContent":["import _ from 'lodash/fp';\n\nconst PERMISSION_FIELDS = ['action', 'subject', 'properties', 'conditions'] as const;\n\nconst sanitizePermissionFields = _.pick(PERMISSION_FIELDS);\n\nexport interface Permission {\n action: string;\n actionParameters?: Record<string, unknown>;\n subject?: string | object | null;\n properties?: Record<string, any>;\n conditions?: string[];\n}\n\n/**\n * Creates a permission with default values for optional properties\n */\nconst getDefaultPermission = (): Pick<Permission, 'conditions' | 'properties' | 'subject'> => ({\n conditions: [],\n properties: {},\n subject: null,\n});\n\n/**\n * Create a new permission based on given attributes\n *\n * @param {object} attributes\n */\nconst create = _.pipe(_.pick(PERMISSION_FIELDS), _.merge(getDefaultPermission()));\n\n/**\n * Add a condition to a permission\n */\nconst addCondition = _.curry((condition: string, permission: Permission): Permission => {\n const { conditions } = permission;\n\n const newConditions = Array.isArray(conditions)\n ? _.uniq(conditions.concat(condition))\n : [condition];\n\n return _.set('conditions', newConditions, permission);\n});\n\n/**\n * Gets a property or a part of a property from a permission.\n */\nconst getProperty = _.curry(\n <T extends keyof Permission['properties']>(\n property: T,\n permission: Permission\n ): Permission['properties'][T] => _.get(`properties.${property}`, permission)\n);\n\nexport { create, sanitizePermissionFields, addCondition, getProperty };\n"],"names":["PERMISSION_FIELDS","sanitizePermissionFields","_","pick","getDefaultPermission","conditions","properties","subject","create","pipe","merge","addCondition","curry","condition","permission","newConditions","Array","isArray","uniq","concat","set","getProperty","property","get"],"mappings":";;AAEA,MAAMA,iBAAoB,GAAA;AAAC,IAAA,QAAA;AAAU,IAAA,SAAA;AAAW,IAAA,YAAA;AAAc,IAAA;AAAa,CAAA;AAErEC,MAAAA,wBAAAA,GAA2BC,CAAEC,CAAAA,IAAI,CAACH,iBAAAA;AAUxC;;IAGA,MAAMI,oBAAuB,GAAA,KAAkE;AAC7FC,QAAAA,UAAAA,EAAY,EAAE;AACdC,QAAAA,UAAAA,EAAY,EAAC;QACbC,OAAS,EAAA;KACX,CAAA;AAEA;;;;IAKA,MAAMC,MAASN,GAAAA,CAAAA,CAAEO,IAAI,CAACP,CAAEC,CAAAA,IAAI,CAACH,iBAAAA,CAAAA,EAAoBE,CAAEQ,CAAAA,KAAK,CAACN,oBAAAA,EAAAA,CAAAA;AAEzD;;AAEC,UACKO,YAAeT,GAAAA,CAAAA,CAAEU,KAAK,CAAC,CAACC,SAAmBC,EAAAA,UAAAA,GAAAA;IAC/C,MAAM,EAAET,UAAU,EAAE,GAAGS,UAAAA;IAEvB,MAAMC,aAAAA,GAAgBC,KAAMC,CAAAA,OAAO,CAACZ,UAAAA,CAAAA,GAChCH,CAAEgB,CAAAA,IAAI,CAACb,UAAAA,CAAWc,MAAM,CAACN,SACzB,CAAA,CAAA,GAAA;AAACA,QAAAA;AAAU,KAAA;AAEf,IAAA,OAAOX,CAAEkB,CAAAA,GAAG,CAAC,YAAA,EAAcL,aAAeD,EAAAA,UAAAA,CAAAA;AAC5C,CAAA;AAEA;;AAEC,UACKO,WAAcnB,GAAAA,CAAAA,CAAEU,KAAK,CACzB,CACEU,QACAR,EAAAA,UAAAA,GACgCZ,CAAEqB,CAAAA,GAAG,CAAC,CAAC,WAAW,EAAED,QAAAA,CAAS,CAAC,EAAER,UAAAA,CAAAA;;;;"}

View File

@@ -0,0 +1,12 @@
import { AbilityBuilder, Ability } from '@casl/ability';
import type { ParametrizedAction, PermissionRule } from '../../types';
export interface CustomAbilityBuilder {
can(permission: PermissionRule): ReturnType<AbilityBuilder<Ability>['can']>;
buildParametrizedAction: (parametrizedAction: ParametrizedAction) => string;
build(): Ability;
}
/**
* Casl Ability Builder.
*/
export declare const caslAbilityBuilder: () => CustomAbilityBuilder;
//# sourceMappingURL=casl-ability.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"casl-ability.d.ts","sourceRoot":"","sources":["../../../src/engine/abilities/casl-ability.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAExD,OAAO,KAAK,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAEtE,MAAM,WAAW,oBAAoB;IACnC,GAAG,CAAC,UAAU,EAAE,cAAc,GAAG,UAAU,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;IAC5E,uBAAuB,EAAE,CAAC,kBAAkB,EAAE,kBAAkB,KAAK,MAAM,CAAC;IAC5E,KAAK,IAAI,OAAO,CAAC;CAClB;AA2BD;;GAEG;AACH,eAAO,MAAM,kBAAkB,QAAO,oBAyCrC,CAAC"}

View File

@@ -0,0 +1,87 @@
'use strict';
var sift = require('sift');
var qs = require('qs');
var ability = require('@casl/ability');
var _ = require('lodash/fp');
function _interopNamespaceDefault(e) {
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
}
n.default = e;
return Object.freeze(n);
}
var sift__namespace = /*#__PURE__*/_interopNamespaceDefault(sift);
const allowedOperations = [
'$or',
'$and',
'$eq',
'$ne',
'$in',
'$nin',
'$lt',
'$lte',
'$gt',
'$gte',
'$exists',
'$elemMatch'
];
const operations = _.pick(allowedOperations, sift__namespace);
const conditionsMatcher = (conditions)=>{
return sift__namespace.createQueryTester(conditions, {
operations
});
};
const buildParametrizedAction = ({ name, params })=>{
return `${name}?${qs.stringify(params)}`;
};
/**
* Casl Ability Builder.
*/ const caslAbilityBuilder = ()=>{
const { can, build, ...rest } = new ability.AbilityBuilder(ability.Ability);
return {
can (permission) {
const { action, subject, properties = {}, condition } = permission;
const { fields } = properties;
const caslAction = typeof action === 'string' ? action : buildParametrizedAction(action);
return can(caslAction, _.isNil(subject) ? 'all' : subject, fields, _.isObject(condition) ? condition : undefined);
},
buildParametrizedAction ({ name, params }) {
return `${name}?${qs.stringify(params)}`;
},
build () {
const ability = build({
conditionsMatcher
});
function decorateCan(originalCan) {
return function(...args) {
const [action, ...rest] = args;
const caslAction = typeof action === 'string' ? action : buildParametrizedAction(action);
// Call the original `can` method
return originalCan.apply(ability, [
caslAction,
...rest
]);
};
}
ability.can = decorateCan(ability.can);
return ability;
},
...rest
};
};
exports.caslAbilityBuilder = caslAbilityBuilder;
//# sourceMappingURL=casl-ability.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"casl-ability.js","sources":["../../../src/engine/abilities/casl-ability.ts"],"sourcesContent":["import * as sift from 'sift';\nimport qs from 'qs';\nimport { AbilityBuilder, Ability } from '@casl/ability';\nimport { pick, isNil, isObject } from 'lodash/fp';\nimport type { ParametrizedAction, PermissionRule } from '../../types';\n\nexport interface CustomAbilityBuilder {\n can(permission: PermissionRule): ReturnType<AbilityBuilder<Ability>['can']>;\n buildParametrizedAction: (parametrizedAction: ParametrizedAction) => string;\n build(): Ability;\n}\n\nconst allowedOperations = [\n '$or',\n '$and',\n '$eq',\n '$ne',\n '$in',\n '$nin',\n '$lt',\n '$lte',\n '$gt',\n '$gte',\n '$exists',\n '$elemMatch',\n] as const;\n\nconst operations = pick(allowedOperations, sift);\n\nconst conditionsMatcher = (conditions: unknown) => {\n return sift.createQueryTester(conditions, { operations });\n};\n\nconst buildParametrizedAction = ({ name, params }: ParametrizedAction) => {\n return `${name}?${qs.stringify(params)}`;\n};\n\n/**\n * Casl Ability Builder.\n */\nexport const caslAbilityBuilder = (): CustomAbilityBuilder => {\n const { can, build, ...rest } = new AbilityBuilder(Ability);\n\n return {\n can(permission: PermissionRule) {\n const { action, subject, properties = {}, condition } = permission;\n const { fields } = properties;\n\n const caslAction = typeof action === 'string' ? action : buildParametrizedAction(action);\n\n return can(\n caslAction,\n isNil(subject) ? 'all' : subject,\n fields,\n isObject(condition) ? condition : undefined\n );\n },\n\n buildParametrizedAction({ name, params }: ParametrizedAction) {\n return `${name}?${qs.stringify(params)}`;\n },\n\n build() {\n const ability = build({ conditionsMatcher });\n\n function decorateCan(originalCan: Ability['can']) {\n return function (...args: Parameters<Ability['can']>) {\n const [action, ...rest] = args;\n const caslAction = typeof action === 'string' ? action : buildParametrizedAction(action);\n\n // Call the original `can` method\n return originalCan.apply(ability, [caslAction, ...rest]);\n };\n }\n\n ability.can = decorateCan(ability.can);\n return ability;\n },\n\n ...rest,\n };\n};\n"],"names":["allowedOperations","operations","pick","sift","conditionsMatcher","conditions","createQueryTester","buildParametrizedAction","name","params","qs","stringify","caslAbilityBuilder","can","build","rest","AbilityBuilder","Ability","permission","action","subject","properties","condition","fields","caslAction","isNil","isObject","undefined","ability","decorateCan","originalCan","args","apply"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAYA,MAAMA,iBAAoB,GAAA;AACxB,IAAA,KAAA;AACA,IAAA,MAAA;AACA,IAAA,KAAA;AACA,IAAA,KAAA;AACA,IAAA,KAAA;AACA,IAAA,MAAA;AACA,IAAA,KAAA;AACA,IAAA,MAAA;AACA,IAAA,KAAA;AACA,IAAA,MAAA;AACA,IAAA,SAAA;AACA,IAAA;AACD,CAAA;AAED,MAAMC,UAAAA,GAAaC,OAAKF,iBAAmBG,EAAAA,eAAAA,CAAAA;AAE3C,MAAMC,oBAAoB,CAACC,UAAAA,GAAAA;IACzB,OAAOF,eAAAA,CAAKG,iBAAiB,CAACD,UAAY,EAAA;AAAEJ,QAAAA;AAAW,KAAA,CAAA;AACzD,CAAA;AAEA,MAAMM,0BAA0B,CAAC,EAAEC,IAAI,EAAEC,MAAM,EAAsB,GAAA;IACnE,OAAO,CAAC,EAAED,IAAK,CAAA,CAAC,EAAEE,EAAGC,CAAAA,SAAS,CAACF,MAAAA,CAAAA,CAAQ,CAAC;AAC1C,CAAA;AAEA;;UAGaG,kBAAqB,GAAA,IAAA;IAChC,MAAM,EAAEC,GAAG,EAAEC,KAAK,EAAE,GAAGC,IAAAA,EAAM,GAAG,IAAIC,sBAAeC,CAAAA,eAAAA,CAAAA;IAEnD,OAAO;AACLJ,QAAAA,GAAAA,CAAAA,CAAIK,UAA0B,EAAA;YAC5B,MAAM,EAAEC,MAAM,EAAEC,OAAO,EAAEC,UAAa,GAAA,EAAE,EAAEC,SAAS,EAAE,GAAGJ,UAAAA;YACxD,MAAM,EAAEK,MAAM,EAAE,GAAGF,UAAAA;AAEnB,YAAA,MAAMG,UAAa,GAAA,OAAOL,MAAW,KAAA,QAAA,GAAWA,SAASZ,uBAAwBY,CAAAA,MAAAA,CAAAA;YAEjF,OAAON,GAAAA,CACLW,YACAC,OAAML,CAAAA,OAAAA,CAAAA,GAAW,QAAQA,OACzBG,EAAAA,MAAAA,EACAG,UAASJ,CAAAA,SAAAA,CAAAA,GAAaA,SAAYK,GAAAA,SAAAA,CAAAA;AAEtC,SAAA;AAEApB,QAAAA,uBAAAA,CAAAA,CAAwB,EAAEC,IAAI,EAAEC,MAAM,EAAsB,EAAA;YAC1D,OAAO,CAAC,EAAED,IAAK,CAAA,CAAC,EAAEE,EAAGC,CAAAA,SAAS,CAACF,MAAAA,CAAAA,CAAQ,CAAC;AAC1C,SAAA;AAEAK,QAAAA,KAAAA,CAAAA,GAAAA;AACE,YAAA,MAAMc,UAAUd,KAAM,CAAA;AAAEV,gBAAAA;AAAkB,aAAA,CAAA;AAE1C,YAAA,SAASyB,YAAYC,WAA2B,EAAA;gBAC9C,OAAO,SAAU,GAAGC,IAAgC,EAAA;AAClD,oBAAA,MAAM,CAACZ,MAAAA,EAAQ,GAAGJ,IAAAA,CAAK,GAAGgB,IAAAA;AAC1B,oBAAA,MAAMP,UAAa,GAAA,OAAOL,MAAW,KAAA,QAAA,GAAWA,SAASZ,uBAAwBY,CAAAA,MAAAA,CAAAA;;oBAGjF,OAAOW,WAAAA,CAAYE,KAAK,CAACJ,OAAS,EAAA;AAACJ,wBAAAA,UAAAA;AAAeT,wBAAAA,GAAAA;AAAK,qBAAA,CAAA;AACzD,iBAAA;AACF;AAEAa,YAAAA,OAAAA,CAAQf,GAAG,GAAGgB,WAAYD,CAAAA,OAAAA,CAAQf,GAAG,CAAA;YACrC,OAAOe,OAAAA;AACT,SAAA;AAEA,QAAA,GAAGb;AACL,KAAA;AACF;;;;"}

View File

@@ -0,0 +1,66 @@
import * as sift from 'sift';
import qs from 'qs';
import { AbilityBuilder, Ability } from '@casl/ability';
import { pick, isNil, isObject } from 'lodash/fp';
const allowedOperations = [
'$or',
'$and',
'$eq',
'$ne',
'$in',
'$nin',
'$lt',
'$lte',
'$gt',
'$gte',
'$exists',
'$elemMatch'
];
const operations = pick(allowedOperations, sift);
const conditionsMatcher = (conditions)=>{
return sift.createQueryTester(conditions, {
operations
});
};
const buildParametrizedAction = ({ name, params })=>{
return `${name}?${qs.stringify(params)}`;
};
/**
* Casl Ability Builder.
*/ const caslAbilityBuilder = ()=>{
const { can, build, ...rest } = new AbilityBuilder(Ability);
return {
can (permission) {
const { action, subject, properties = {}, condition } = permission;
const { fields } = properties;
const caslAction = typeof action === 'string' ? action : buildParametrizedAction(action);
return can(caslAction, isNil(subject) ? 'all' : subject, fields, isObject(condition) ? condition : undefined);
},
buildParametrizedAction ({ name, params }) {
return `${name}?${qs.stringify(params)}`;
},
build () {
const ability = build({
conditionsMatcher
});
function decorateCan(originalCan) {
return function(...args) {
const [action, ...rest] = args;
const caslAction = typeof action === 'string' ? action : buildParametrizedAction(action);
// Call the original `can` method
return originalCan.apply(ability, [
caslAction,
...rest
]);
};
}
ability.can = decorateCan(ability.can);
return ability;
},
...rest
};
};
export { caslAbilityBuilder };
//# sourceMappingURL=casl-ability.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"casl-ability.mjs","sources":["../../../src/engine/abilities/casl-ability.ts"],"sourcesContent":["import * as sift from 'sift';\nimport qs from 'qs';\nimport { AbilityBuilder, Ability } from '@casl/ability';\nimport { pick, isNil, isObject } from 'lodash/fp';\nimport type { ParametrizedAction, PermissionRule } from '../../types';\n\nexport interface CustomAbilityBuilder {\n can(permission: PermissionRule): ReturnType<AbilityBuilder<Ability>['can']>;\n buildParametrizedAction: (parametrizedAction: ParametrizedAction) => string;\n build(): Ability;\n}\n\nconst allowedOperations = [\n '$or',\n '$and',\n '$eq',\n '$ne',\n '$in',\n '$nin',\n '$lt',\n '$lte',\n '$gt',\n '$gte',\n '$exists',\n '$elemMatch',\n] as const;\n\nconst operations = pick(allowedOperations, sift);\n\nconst conditionsMatcher = (conditions: unknown) => {\n return sift.createQueryTester(conditions, { operations });\n};\n\nconst buildParametrizedAction = ({ name, params }: ParametrizedAction) => {\n return `${name}?${qs.stringify(params)}`;\n};\n\n/**\n * Casl Ability Builder.\n */\nexport const caslAbilityBuilder = (): CustomAbilityBuilder => {\n const { can, build, ...rest } = new AbilityBuilder(Ability);\n\n return {\n can(permission: PermissionRule) {\n const { action, subject, properties = {}, condition } = permission;\n const { fields } = properties;\n\n const caslAction = typeof action === 'string' ? action : buildParametrizedAction(action);\n\n return can(\n caslAction,\n isNil(subject) ? 'all' : subject,\n fields,\n isObject(condition) ? condition : undefined\n );\n },\n\n buildParametrizedAction({ name, params }: ParametrizedAction) {\n return `${name}?${qs.stringify(params)}`;\n },\n\n build() {\n const ability = build({ conditionsMatcher });\n\n function decorateCan(originalCan: Ability['can']) {\n return function (...args: Parameters<Ability['can']>) {\n const [action, ...rest] = args;\n const caslAction = typeof action === 'string' ? action : buildParametrizedAction(action);\n\n // Call the original `can` method\n return originalCan.apply(ability, [caslAction, ...rest]);\n };\n }\n\n ability.can = decorateCan(ability.can);\n return ability;\n },\n\n ...rest,\n };\n};\n"],"names":["allowedOperations","operations","pick","sift","conditionsMatcher","conditions","createQueryTester","buildParametrizedAction","name","params","qs","stringify","caslAbilityBuilder","can","build","rest","AbilityBuilder","Ability","permission","action","subject","properties","condition","fields","caslAction","isNil","isObject","undefined","ability","decorateCan","originalCan","args","apply"],"mappings":";;;;;AAYA,MAAMA,iBAAoB,GAAA;AACxB,IAAA,KAAA;AACA,IAAA,MAAA;AACA,IAAA,KAAA;AACA,IAAA,KAAA;AACA,IAAA,KAAA;AACA,IAAA,MAAA;AACA,IAAA,KAAA;AACA,IAAA,MAAA;AACA,IAAA,KAAA;AACA,IAAA,MAAA;AACA,IAAA,SAAA;AACA,IAAA;AACD,CAAA;AAED,MAAMC,UAAAA,GAAaC,KAAKF,iBAAmBG,EAAAA,IAAAA,CAAAA;AAE3C,MAAMC,oBAAoB,CAACC,UAAAA,GAAAA;IACzB,OAAOF,IAAAA,CAAKG,iBAAiB,CAACD,UAAY,EAAA;AAAEJ,QAAAA;AAAW,KAAA,CAAA;AACzD,CAAA;AAEA,MAAMM,0BAA0B,CAAC,EAAEC,IAAI,EAAEC,MAAM,EAAsB,GAAA;IACnE,OAAO,CAAC,EAAED,IAAK,CAAA,CAAC,EAAEE,EAAGC,CAAAA,SAAS,CAACF,MAAAA,CAAAA,CAAQ,CAAC;AAC1C,CAAA;AAEA;;UAGaG,kBAAqB,GAAA,IAAA;IAChC,MAAM,EAAEC,GAAG,EAAEC,KAAK,EAAE,GAAGC,IAAAA,EAAM,GAAG,IAAIC,cAAeC,CAAAA,OAAAA,CAAAA;IAEnD,OAAO;AACLJ,QAAAA,GAAAA,CAAAA,CAAIK,UAA0B,EAAA;YAC5B,MAAM,EAAEC,MAAM,EAAEC,OAAO,EAAEC,UAAa,GAAA,EAAE,EAAEC,SAAS,EAAE,GAAGJ,UAAAA;YACxD,MAAM,EAAEK,MAAM,EAAE,GAAGF,UAAAA;AAEnB,YAAA,MAAMG,UAAa,GAAA,OAAOL,MAAW,KAAA,QAAA,GAAWA,SAASZ,uBAAwBY,CAAAA,MAAAA,CAAAA;YAEjF,OAAON,GAAAA,CACLW,YACAC,KAAML,CAAAA,OAAAA,CAAAA,GAAW,QAAQA,OACzBG,EAAAA,MAAAA,EACAG,QAASJ,CAAAA,SAAAA,CAAAA,GAAaA,SAAYK,GAAAA,SAAAA,CAAAA;AAEtC,SAAA;AAEApB,QAAAA,uBAAAA,CAAAA,CAAwB,EAAEC,IAAI,EAAEC,MAAM,EAAsB,EAAA;YAC1D,OAAO,CAAC,EAAED,IAAK,CAAA,CAAC,EAAEE,EAAGC,CAAAA,SAAS,CAACF,MAAAA,CAAAA,CAAQ,CAAC;AAC1C,SAAA;AAEAK,QAAAA,KAAAA,CAAAA,GAAAA;AACE,YAAA,MAAMc,UAAUd,KAAM,CAAA;AAAEV,gBAAAA;AAAkB,aAAA,CAAA;AAE1C,YAAA,SAASyB,YAAYC,WAA2B,EAAA;gBAC9C,OAAO,SAAU,GAAGC,IAAgC,EAAA;AAClD,oBAAA,MAAM,CAACZ,MAAAA,EAAQ,GAAGJ,IAAAA,CAAK,GAAGgB,IAAAA;AAC1B,oBAAA,MAAMP,UAAa,GAAA,OAAOL,MAAW,KAAA,QAAA,GAAWA,SAASZ,uBAAwBY,CAAAA,MAAAA,CAAAA;;oBAGjF,OAAOW,WAAAA,CAAYE,KAAK,CAACJ,OAAS,EAAA;AAACJ,wBAAAA,UAAAA;AAAeT,wBAAAA,GAAAA;AAAK,qBAAA,CAAA;AACzD,iBAAA;AACF;AAEAa,YAAAA,OAAAA,CAAQf,GAAG,GAAGgB,WAAYD,CAAAA,OAAAA,CAAQf,GAAG,CAAA;YACrC,OAAOe,OAAAA;AACT,SAAA;AAEA,QAAA,GAAGb;AACL,KAAA;AACF;;;;"}

View File

@@ -0,0 +1,2 @@
export * from './casl-ability';
//# sourceMappingURL=index.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/engine/abilities/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC"}

View File

@@ -0,0 +1,8 @@
'use strict';
var caslAbility = require('./casl-ability.js');
exports.caslAbilityBuilder = caslAbility.caslAbilityBuilder;
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;"}

View File

@@ -0,0 +1,2 @@
export { caslAbilityBuilder } from './casl-ability.mjs';
//# sourceMappingURL=index.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":""}

View File

@@ -0,0 +1,55 @@
import { hooks } from '@strapi/utils';
import * as domain from '../domain';
import type { Permission } from '../domain/permission';
import type { PermissionRule } from '../types';
export interface PermissionEngineHooks {
'before-format::validate.permission': ReturnType<typeof hooks.createAsyncBailHook>;
'format.permission': ReturnType<typeof hooks.createAsyncSeriesWaterfallHook>;
'after-format::validate.permission': ReturnType<typeof hooks.createAsyncBailHook>;
'before-evaluate.permission': ReturnType<typeof hooks.createAsyncSeriesHook>;
'before-register.permission': ReturnType<typeof hooks.createAsyncSeriesHook>;
}
export type HookName = keyof PermissionEngineHooks;
/**
* Create a hook map used by the permission Engine
*/
declare const createEngineHooks: () => PermissionEngineHooks;
/**
* Create a context from a domain {@link Permission} used by the validate hooks
*/
declare const createValidateContext: (permission: Permission) => {
readonly permission: Readonly<domain.permission.Permission>;
};
/**
* Create a context from a domain {@link Permission} used by the before valuate hook
*/
declare const createBeforeEvaluateContext: (permission: Permission) => {
readonly permission: Readonly<domain.permission.Permission>;
addCondition(condition: string): {
readonly permission: Readonly<domain.permission.Permission>;
addCondition(condition: string): any;
};
};
interface WillRegisterContextParams {
permission: PermissionRule;
options: Record<string, unknown>;
}
/**
* Create a context from a casl Permission & some options
* @param caslPermission
*/
declare const createWillRegisterContext: ({ permission, options }: WillRegisterContextParams) => {
permission: PermissionRule;
condition: {
and(rawConditionObject: unknown): {
and(rawConditionObject: unknown): any;
or(rawConditionObject: unknown): any;
};
or(rawConditionObject: unknown): {
and(rawConditionObject: unknown): any;
or(rawConditionObject: unknown): any;
};
};
};
export { createEngineHooks, createValidateContext, createBeforeEvaluateContext, createWillRegisterContext, };
//# sourceMappingURL=hooks.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/engine/hooks.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAEtC,OAAO,KAAK,MAAM,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE/C,MAAM,WAAW,qBAAqB;IACpC,oCAAoC,EAAE,UAAU,CAAC,OAAO,KAAK,CAAC,mBAAmB,CAAC,CAAC;IACnF,mBAAmB,EAAE,UAAU,CAAC,OAAO,KAAK,CAAC,8BAA8B,CAAC,CAAC;IAC7E,mCAAmC,EAAE,UAAU,CAAC,OAAO,KAAK,CAAC,mBAAmB,CAAC,CAAC;IAClF,4BAA4B,EAAE,UAAU,CAAC,OAAO,KAAK,CAAC,qBAAqB,CAAC,CAAC;IAC7E,4BAA4B,EAAE,UAAU,CAAC,OAAO,KAAK,CAAC,qBAAqB,CAAC,CAAC;CAC9E;AAED,MAAM,MAAM,QAAQ,GAAG,MAAM,qBAAqB,CAAC;AAEnD;;GAEG;AACH,QAAA,MAAM,iBAAiB,QAAO,qBAM5B,CAAC;AAEH;;GAEG;AACH,QAAA,MAAM,qBAAqB,eAAgB,UAAU;;CAInD,CAAC;AAEH;;GAEG;AACH,QAAA,MAAM,2BAA2B,eAAgB,UAAU;;4BAKjC,MAAM;;gCAAN,MAAM;;CAK9B,CAAC;AAEH,UAAU,yBAAyB;IACjC,UAAU,EAAE,cAAc,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED;;;GAGG;AACH,QAAA,MAAM,yBAAyB,4BAA6B,yBAAyB;;;gCAQzD,OAAO;oCAAP,OAAO;mCAYR,OAAO;;+BAAP,OAAO;oCAZN,OAAO;mCAYR,OAAO;;;CAkBhC,CAAC;AAEH,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,2BAA2B,EAC3B,yBAAyB,GAC1B,CAAC"}

View File

@@ -0,0 +1,81 @@
'use strict';
var _ = require('lodash/fp');
var utils = require('@strapi/utils');
var index = require('../domain/permission/index.js');
/**
* Create a hook map used by the permission Engine
*/ const createEngineHooks = ()=>({
'before-format::validate.permission': utils.hooks.createAsyncBailHook(),
'format.permission': utils.hooks.createAsyncSeriesWaterfallHook(),
'after-format::validate.permission': utils.hooks.createAsyncBailHook(),
'before-evaluate.permission': utils.hooks.createAsyncSeriesHook(),
'before-register.permission': utils.hooks.createAsyncSeriesHook()
});
/**
* Create a context from a domain {@link Permission} used by the validate hooks
*/ const createValidateContext = (permission)=>({
get permission () {
return _.cloneDeep(permission);
}
});
/**
* Create a context from a domain {@link Permission} used by the before valuate hook
*/ const createBeforeEvaluateContext = (permission)=>({
get permission () {
return _.cloneDeep(permission);
},
addCondition (condition) {
Object.assign(permission, index.addCondition(condition, permission));
return this;
}
});
/**
* Create a context from a casl Permission & some options
* @param caslPermission
*/ const createWillRegisterContext = ({ permission, options })=>({
...options,
get permission () {
return _.cloneDeep(permission);
},
condition: {
and (rawConditionObject) {
if (!permission.condition) {
permission.condition = {
$and: []
};
}
if (_.isArray(permission.condition.$and)) {
permission.condition.$and.push(rawConditionObject);
}
return this;
},
or (rawConditionObject) {
if (!permission.condition) {
permission.condition = {
$and: []
};
}
if (_.isArray(permission.condition.$and)) {
const orClause = permission.condition.$and.find(_.has('$or'));
if (orClause) {
orClause.$or.push(rawConditionObject);
} else {
permission.condition.$and.push({
$or: [
rawConditionObject
]
});
}
}
return this;
}
}
});
exports.createBeforeEvaluateContext = createBeforeEvaluateContext;
exports.createEngineHooks = createEngineHooks;
exports.createValidateContext = createValidateContext;
exports.createWillRegisterContext = createWillRegisterContext;
//# sourceMappingURL=hooks.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,76 @@
import { cloneDeep, isArray, has } from 'lodash/fp';
import { hooks } from '@strapi/utils';
import { addCondition } from '../domain/permission/index.mjs';
/**
* Create a hook map used by the permission Engine
*/ const createEngineHooks = ()=>({
'before-format::validate.permission': hooks.createAsyncBailHook(),
'format.permission': hooks.createAsyncSeriesWaterfallHook(),
'after-format::validate.permission': hooks.createAsyncBailHook(),
'before-evaluate.permission': hooks.createAsyncSeriesHook(),
'before-register.permission': hooks.createAsyncSeriesHook()
});
/**
* Create a context from a domain {@link Permission} used by the validate hooks
*/ const createValidateContext = (permission)=>({
get permission () {
return cloneDeep(permission);
}
});
/**
* Create a context from a domain {@link Permission} used by the before valuate hook
*/ const createBeforeEvaluateContext = (permission)=>({
get permission () {
return cloneDeep(permission);
},
addCondition (condition) {
Object.assign(permission, addCondition(condition, permission));
return this;
}
});
/**
* Create a context from a casl Permission & some options
* @param caslPermission
*/ const createWillRegisterContext = ({ permission, options })=>({
...options,
get permission () {
return cloneDeep(permission);
},
condition: {
and (rawConditionObject) {
if (!permission.condition) {
permission.condition = {
$and: []
};
}
if (isArray(permission.condition.$and)) {
permission.condition.$and.push(rawConditionObject);
}
return this;
},
or (rawConditionObject) {
if (!permission.condition) {
permission.condition = {
$and: []
};
}
if (isArray(permission.condition.$and)) {
const orClause = permission.condition.$and.find(has('$or'));
if (orClause) {
orClause.$or.push(rawConditionObject);
} else {
permission.condition.$and.push({
$or: [
rawConditionObject
]
});
}
}
return this;
}
}
});
export { createBeforeEvaluateContext, createEngineHooks, createValidateContext, createWillRegisterContext };
//# sourceMappingURL=hooks.mjs.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,28 @@
import { Ability } from '@casl/ability';
import { providerFactory } from '@strapi/utils';
import type { PermissionEngineHooks, HookName } from './hooks';
import * as abilities from './abilities';
import { Permission } from '../domain/permission';
import type { PermissionRule } from '../types';
export { abilities };
type Provider = Omit<ReturnType<typeof providerFactory>, 'register'> & {
register(...args: unknown[]): Promise<Provider> | Provider;
};
type ActionProvider = Provider;
type ConditionProvider = Provider;
export interface Engine {
hooks: PermissionEngineHooks;
on(hook: HookName, handler: (...args: any[]) => any): Engine;
generateAbility(permissions: Permission[], options?: object): Promise<Ability>;
createRegisterFunction(can: (permission: PermissionRule) => unknown, options: Record<string, unknown>): (permission: PermissionRule) => Promise<unknown>;
}
export interface EngineParams {
providers: {
action: ActionProvider;
condition: ConditionProvider;
};
abilityBuilderFactory?(): abilities.CustomAbilityBuilder;
}
declare const newEngine: (params: EngineParams) => Engine;
export { newEngine as new };
//# sourceMappingURL=index.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/engine/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAQhD,OAAO,KAAK,EAAE,qBAAqB,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAE/D,OAAO,KAAK,SAAS,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE/C,OAAO,EAAE,SAAS,EAAE,CAAC;AAErB,KAAK,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,OAAO,eAAe,CAAC,EAAE,UAAU,CAAC,GAAG;IACrE,QAAQ,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAC;CAC5D,CAAC;AAEF,KAAK,cAAc,GAAG,QAAQ,CAAC;AAC/B,KAAK,iBAAiB,GAAG,QAAQ,CAAC;AAElC,MAAM,WAAW,MAAM;IACrB,KAAK,EAAE,qBAAqB,CAAC;IAC7B,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,GAAG,MAAM,CAAC;IAC7D,eAAe,CAAC,WAAW,EAAE,UAAU,EAAE,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/E,sBAAsB,CACpB,GAAG,EAAE,CAAC,UAAU,EAAE,cAAc,KAAK,OAAO,EAC5C,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,CAAC,UAAU,EAAE,cAAc,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CACrD;AAED,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE;QAAE,MAAM,EAAE,cAAc,CAAC;QAAC,SAAS,EAAE,iBAAiB,CAAA;KAAE,CAAC;IACpE,qBAAqB,CAAC,IAAI,SAAS,CAAC,oBAAoB,CAAC;CAC1D;AAsBD,QAAA,MAAM,SAAS,WAAY,YAAY,KAAG,MAoKzC,CAAC;AAEF,OAAO,EAAE,SAAS,IAAI,GAAG,EAAE,CAAC"}

View File

@@ -0,0 +1,141 @@
'use strict';
var _ = require('lodash/fp');
var qs = require('qs');
var hooks = require('./hooks.js');
var index = require('./abilities/index.js');
var caslAbility = require('./abilities/casl-ability.js');
/**
* Create a default state object for the engine
*/ const createEngineState = ()=>{
const hooks$1 = hooks.createEngineHooks();
return {
hooks: hooks$1
};
};
const newEngine = (params)=>{
const { providers, abilityBuilderFactory = caslAbility.caslAbilityBuilder } = params;
const state = createEngineState();
const runValidationHook = async (hook, context)=>state.hooks[hook].call(context);
/**
* Evaluate a permission using local and registered behaviors (using hooks).
* Validate, format (add condition, etc...), evaluate (evaluate conditions) and register a permission
*/ const evaluate = async (params)=>{
const { options, register } = params;
const preFormatValidation = await runValidationHook('before-format::validate.permission', hooks.createBeforeEvaluateContext(params.permission));
if (preFormatValidation === false) {
return;
}
const permission = await state.hooks['format.permission'].call(params.permission);
const afterFormatValidation = await runValidationHook('after-format::validate.permission', hooks.createValidateContext(permission));
if (afterFormatValidation === false) {
return;
}
await state.hooks['before-evaluate.permission'].call(hooks.createBeforeEvaluateContext(permission));
const { action: actionName, subject, properties, conditions = [], actionParameters = {} } = permission;
let action = actionName;
if (actionParameters && Object.keys(actionParameters).length > 0) {
action = `${actionName}?${qs.stringify(actionParameters)}`;
}
if (conditions.length === 0) {
return register({
action,
subject,
properties
});
}
const resolveConditions = _.map(providers.condition.get);
const removeInvalidConditions = _.filter((condition)=>_.isFunction(condition.handler));
const evaluateConditions = (conditions)=>{
return Promise.all(conditions.map(async (condition)=>({
condition,
result: await condition.handler(_.merge(options, {
permission: _.cloneDeep(permission)
}))
})));
};
const removeInvalidResults = _.filter(({ result })=>_.isBoolean(result) || _.isObject(result));
const evaluatedConditions = await Promise.resolve(conditions).then(resolveConditions).then(removeInvalidConditions).then(evaluateConditions).then(removeInvalidResults);
const resultPropEq = _.propEq('result');
const pickResults = _.map(_.prop('result'));
if (evaluatedConditions.every(resultPropEq(false))) {
return;
}
if (_.isEmpty(evaluatedConditions) || evaluatedConditions.some(resultPropEq(true))) {
return register({
action,
subject,
properties
});
}
const results = pickResults(evaluatedConditions).filter(_.isObject);
if (_.isEmpty(results)) {
return register({
action,
subject,
properties
});
}
return register({
action,
subject,
properties,
condition: {
$and: [
{
$or: results
}
]
}
});
};
return {
get hooks () {
return state.hooks;
},
/**
* Create a register function that wraps a `can` function
* used to register a permission in the ability builder
*/ createRegisterFunction (can, options) {
return async (permission)=>{
const hookContext = hooks.createWillRegisterContext({
options,
permission
});
await state.hooks['before-register.permission'].call(hookContext);
return can(permission);
};
},
/**
* Register a new handler for a given hook
*/ on (hook, handler) {
const validHooks = Object.keys(state.hooks);
const isValidHook = validHooks.includes(hook);
if (!isValidHook) {
throw new Error(`Invalid hook supplied when trying to register an handler to the permission engine. Got "${hook}" but expected one of ${validHooks.join(', ')}`);
}
state.hooks[hook].register(handler);
return this;
},
/**
* Generate an ability based on the instance's
* ability builder and the given permissions
*/ async generateAbility (permissions, options = {}) {
const { can, build } = abilityBuilderFactory();
for (const permission of permissions){
const register = this.createRegisterFunction(can, options);
await evaluate({
permission,
options,
register
});
}
return build();
}
};
};
exports.abilities = index;
exports.new = newEngine;
//# sourceMappingURL=index.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,139 @@
import _ from 'lodash/fp';
import qs from 'qs';
import { createWillRegisterContext, createEngineHooks, createBeforeEvaluateContext, createValidateContext } from './hooks.mjs';
import * as index from './abilities/index.mjs';
export { index as abilities };
import { caslAbilityBuilder } from './abilities/casl-ability.mjs';
/**
* Create a default state object for the engine
*/ const createEngineState = ()=>{
const hooks = createEngineHooks();
return {
hooks
};
};
const newEngine = (params)=>{
const { providers, abilityBuilderFactory = caslAbilityBuilder } = params;
const state = createEngineState();
const runValidationHook = async (hook, context)=>state.hooks[hook].call(context);
/**
* Evaluate a permission using local and registered behaviors (using hooks).
* Validate, format (add condition, etc...), evaluate (evaluate conditions) and register a permission
*/ const evaluate = async (params)=>{
const { options, register } = params;
const preFormatValidation = await runValidationHook('before-format::validate.permission', createBeforeEvaluateContext(params.permission));
if (preFormatValidation === false) {
return;
}
const permission = await state.hooks['format.permission'].call(params.permission);
const afterFormatValidation = await runValidationHook('after-format::validate.permission', createValidateContext(permission));
if (afterFormatValidation === false) {
return;
}
await state.hooks['before-evaluate.permission'].call(createBeforeEvaluateContext(permission));
const { action: actionName, subject, properties, conditions = [], actionParameters = {} } = permission;
let action = actionName;
if (actionParameters && Object.keys(actionParameters).length > 0) {
action = `${actionName}?${qs.stringify(actionParameters)}`;
}
if (conditions.length === 0) {
return register({
action,
subject,
properties
});
}
const resolveConditions = _.map(providers.condition.get);
const removeInvalidConditions = _.filter((condition)=>_.isFunction(condition.handler));
const evaluateConditions = (conditions)=>{
return Promise.all(conditions.map(async (condition)=>({
condition,
result: await condition.handler(_.merge(options, {
permission: _.cloneDeep(permission)
}))
})));
};
const removeInvalidResults = _.filter(({ result })=>_.isBoolean(result) || _.isObject(result));
const evaluatedConditions = await Promise.resolve(conditions).then(resolveConditions).then(removeInvalidConditions).then(evaluateConditions).then(removeInvalidResults);
const resultPropEq = _.propEq('result');
const pickResults = _.map(_.prop('result'));
if (evaluatedConditions.every(resultPropEq(false))) {
return;
}
if (_.isEmpty(evaluatedConditions) || evaluatedConditions.some(resultPropEq(true))) {
return register({
action,
subject,
properties
});
}
const results = pickResults(evaluatedConditions).filter(_.isObject);
if (_.isEmpty(results)) {
return register({
action,
subject,
properties
});
}
return register({
action,
subject,
properties,
condition: {
$and: [
{
$or: results
}
]
}
});
};
return {
get hooks () {
return state.hooks;
},
/**
* Create a register function that wraps a `can` function
* used to register a permission in the ability builder
*/ createRegisterFunction (can, options) {
return async (permission)=>{
const hookContext = createWillRegisterContext({
options,
permission
});
await state.hooks['before-register.permission'].call(hookContext);
return can(permission);
};
},
/**
* Register a new handler for a given hook
*/ on (hook, handler) {
const validHooks = Object.keys(state.hooks);
const isValidHook = validHooks.includes(hook);
if (!isValidHook) {
throw new Error(`Invalid hook supplied when trying to register an handler to the permission engine. Got "${hook}" but expected one of ${validHooks.join(', ')}`);
}
state.hooks[hook].register(handler);
return this;
},
/**
* Generate an ability based on the instance's
* ability builder and the given permissions
*/ async generateAbility (permissions, options = {}) {
const { can, build } = abilityBuilderFactory();
for (const permission of permissions){
const register = this.createRegisterFunction(can, options);
await evaluate({
permission,
options,
register
});
}
return build();
}
};
};
export { newEngine as new };
//# sourceMappingURL=index.mjs.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,4 @@
import * as domain from './domain';
import * as engine from './engine';
export { domain, engine };
//# sourceMappingURL=index.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,UAAU,CAAC;AACnC,OAAO,KAAK,MAAM,MAAM,UAAU,CAAC;AAEnC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC"}

10
server/node_modules/@strapi/permissions/dist/index.js generated vendored Normal file
View File

@@ -0,0 +1,10 @@
'use strict';
var index = require('./domain/index.js');
var index$1 = require('./engine/index.js');
exports.domain = index;
exports.engine = index$1;
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;"}

View File

@@ -0,0 +1,5 @@
import * as index from './domain/index.mjs';
export { index as domain };
import * as index$1 from './engine/index.mjs';
export { index$1 as engine };
//# sourceMappingURL=index.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;"}

View File

@@ -0,0 +1,19 @@
/**
* These were imported from `@strapi/types` but if we do that
* it becomes a circular dependency. This is the source of truth,
* they're re-exported from `@strapi/types` for convenience.
*/
import type { Subject } from '@casl/ability';
export interface ParametrizedAction {
name: string;
params: Record<string, unknown>;
}
export interface PermissionRule {
action: string | ParametrizedAction;
subject?: Subject | null;
properties?: {
fields?: string[];
};
condition?: Record<string, unknown>;
}
//# sourceMappingURL=types.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAE7C,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AACD,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,GAAG,kBAAkB,CAAC;IACpC,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IACzB,UAAU,CAAC,EAAE;QACX,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;KACnB,CAAC;IACF,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACrC"}