@strapi/permissions 5.12.1 → 5.12.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../../src/engine/index.ts"],"sourcesContent":["import _ from 'lodash/fp';\nimport qs from 'qs';\nimport { Ability } from '@casl/ability';\nimport { providerFactory } from '@strapi/utils';\n\nimport {\n createEngineHooks,\n createWillRegisterContext,\n createBeforeEvaluateContext,\n createValidateContext,\n} from './hooks';\nimport type { PermissionEngineHooks, HookName } from './hooks';\n\nimport * as abilities from './abilities';\nimport { Permission } from '../domain/permission';\nimport type { PermissionRule } from '../types';\n\nexport { abilities };\n\ntype Provider = Omit<ReturnType<typeof providerFactory>, 'register'> & {\n register(...args: unknown[]): Promise<Provider> | Provider;\n};\n\ntype ActionProvider = Provider;\ntype ConditionProvider = Provider;\n\nexport interface Engine {\n hooks: PermissionEngineHooks;\n on(hook: HookName, handler: (...args: any[]) => any): Engine;\n generateAbility(permissions: Permission[], options?: object): Promise<Ability>;\n createRegisterFunction(\n can: (permission: PermissionRule) => unknown,\n options: Record<string, unknown>\n ): (permission: PermissionRule) => Promise<unknown>;\n}\n\nexport interface EngineParams {\n providers: { action: ActionProvider; condition: ConditionProvider };\n abilityBuilderFactory?(): abilities.CustomAbilityBuilder;\n}\n\ninterface EvaluateParams {\n options: Record<string, unknown>;\n register: (permission: PermissionRule) => Promise<unknown>;\n permission: Permission;\n}\n\ninterface Condition {\n name: string;\n handler(...params: unknown[]): boolean | object;\n}\n\n/**\n * Create a default state object for the engine\n */\nconst createEngineState = () => {\n const hooks = createEngineHooks();\n\n return { hooks };\n};\n\nconst newEngine = (params: EngineParams): Engine => {\n const { providers, abilityBuilderFactory = abilities.caslAbilityBuilder } = params;\n\n const state = createEngineState();\n\n const runValidationHook = async (hook: HookName, context: unknown) =>\n state.hooks[hook].call(context);\n\n /**\n * Evaluate a permission using local and registered behaviors (using hooks).\n * Validate, format (add condition, etc...), evaluate (evaluate conditions) and register a permission\n */\n const evaluate = async (params: EvaluateParams) => {\n const { options, register } = params;\n\n const preFormatValidation = await runValidationHook(\n 'before-format::validate.permission',\n createBeforeEvaluateContext(params.permission)\n );\n\n if (preFormatValidation === false) {\n return;\n }\n\n const permission = (await state.hooks['format.permission'].call(\n params.permission\n )) as Permission;\n\n const afterFormatValidation = await runValidationHook(\n 'after-format::validate.permission',\n createValidateContext(permission)\n );\n\n if (afterFormatValidation === false) {\n return;\n }\n\n await state.hooks['before-evaluate.permission'].call(createBeforeEvaluateContext(permission));\n\n const {\n action: actionName,\n subject,\n properties,\n conditions = [],\n actionParameters = {},\n } = permission;\n\n let action = actionName;\n\n if (actionParameters && Object.keys(actionParameters).length > 0) {\n action = `${actionName}?${qs.stringify(actionParameters)}`;\n }\n\n if (conditions.length === 0) {\n return register({ action, subject, properties });\n }\n\n const resolveConditions = _.map(providers.condition.get);\n\n const removeInvalidConditions = _.filter((condition: Condition) =>\n _.isFunction(condition.handler)\n );\n\n const evaluateConditions = (conditions: Condition[]) => {\n return Promise.all(\n conditions.map(async (condition) => ({\n condition,\n result: await condition.handler(\n _.merge(options, { permission: _.cloneDeep(permission) })\n ),\n }))\n );\n };\n\n const removeInvalidResults = _.filter(\n ({ result }) => _.isBoolean(result) || _.isObject(result)\n );\n\n const evaluatedConditions = await Promise.resolve(conditions)\n .then(resolveConditions)\n .then(removeInvalidConditions)\n .then(evaluateConditions)\n .then(removeInvalidResults);\n\n const resultPropEq = _.propEq('result');\n const pickResults = _.map(_.prop('result'));\n\n if (evaluatedConditions.every(resultPropEq(false))) {\n return;\n }\n\n if (_.isEmpty(evaluatedConditions) || evaluatedConditions.some(resultPropEq(true))) {\n return register({ action, subject, properties });\n }\n\n const results = pickResults(evaluatedConditions).filter(_.isObject);\n\n if (_.isEmpty(results)) {\n return register({ action, subject, properties });\n }\n\n return register({\n action,\n subject,\n properties,\n condition: { $and: [{ $or: results }] },\n });\n };\n\n return {\n get hooks() {\n return state.hooks;\n },\n\n /**\n * Create a register function that wraps a `can` function\n * used to register a permission in the ability builder\n */\n createRegisterFunction(can, options: Record<string, unknown>) {\n return async (permission: PermissionRule) => {\n const hookContext = createWillRegisterContext({ options, permission });\n\n await state.hooks['before-register.permission'].call(hookContext);\n\n return can(permission);\n };\n },\n\n /**\n * Register a new handler for a given hook\n */\n on(hook, handler) {\n const validHooks = Object.keys(state.hooks);\n const isValidHook = validHooks.includes(hook);\n\n if (!isValidHook) {\n throw new Error(\n `Invalid hook supplied when trying to register an handler to the permission engine. Got \"${hook}\" but expected one of ${validHooks.join(\n ', '\n )}`\n );\n }\n\n state.hooks[hook].register(handler);\n\n return this;\n },\n\n /**\n * Generate an ability based on the instance's\n * ability builder and the given permissions\n */\n async generateAbility(permissions, options: Record<string, unknown> = {}) {\n const { can, build } = abilityBuilderFactory();\n\n for (const permission of permissions) {\n const register = this.createRegisterFunction(can, options);\n\n await evaluate({ permission, options, register });\n }\n\n return build();\n },\n };\n};\n\nexport { newEngine as new };\n"],"names":["createEngineState","hooks","createEngineHooks","newEngine","params","providers","abilityBuilderFactory","abilities","state","runValidationHook","hook","context","call","evaluate","options","register","preFormatValidation","createBeforeEvaluateContext","permission","afterFormatValidation","createValidateContext","action","actionName","subject","properties","conditions","actionParameters","Object","keys","length","qs","stringify","resolveConditions","_","map","condition","get","removeInvalidConditions","filter","isFunction","handler","evaluateConditions","Promise","all","result","merge","cloneDeep","removeInvalidResults","isBoolean","isObject","evaluatedConditions","resolve","then","resultPropEq","propEq","pickResults","prop","every","isEmpty","some","results","$and","$or","createRegisterFunction","can","hookContext","createWillRegisterContext","on","validHooks","isValidHook","includes","Error","join","generateAbility","permissions","build"],"mappings":"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"}
@@ -0,0 +1,139 @@
1
+ import _ from 'lodash/fp';
2
+ import qs from 'qs';
3
+ import { createWillRegisterContext, createEngineHooks, createBeforeEvaluateContext, createValidateContext } from './hooks.mjs';
4
+ import * as index from './abilities/index.mjs';
5
+ export { index as abilities };
6
+ import { caslAbilityBuilder } from './abilities/casl-ability.mjs';
7
+
8
+ /**
9
+ * Create a default state object for the engine
10
+ */ const createEngineState = ()=>{
11
+ const hooks = createEngineHooks();
12
+ return {
13
+ hooks
14
+ };
15
+ };
16
+ const newEngine = (params)=>{
17
+ const { providers, abilityBuilderFactory = caslAbilityBuilder } = params;
18
+ const state = createEngineState();
19
+ const runValidationHook = async (hook, context)=>state.hooks[hook].call(context);
20
+ /**
21
+ * Evaluate a permission using local and registered behaviors (using hooks).
22
+ * Validate, format (add condition, etc...), evaluate (evaluate conditions) and register a permission
23
+ */ const evaluate = async (params)=>{
24
+ const { options, register } = params;
25
+ const preFormatValidation = await runValidationHook('before-format::validate.permission', createBeforeEvaluateContext(params.permission));
26
+ if (preFormatValidation === false) {
27
+ return;
28
+ }
29
+ const permission = await state.hooks['format.permission'].call(params.permission);
30
+ const afterFormatValidation = await runValidationHook('after-format::validate.permission', createValidateContext(permission));
31
+ if (afterFormatValidation === false) {
32
+ return;
33
+ }
34
+ await state.hooks['before-evaluate.permission'].call(createBeforeEvaluateContext(permission));
35
+ const { action: actionName, subject, properties, conditions = [], actionParameters = {} } = permission;
36
+ let action = actionName;
37
+ if (actionParameters && Object.keys(actionParameters).length > 0) {
38
+ action = `${actionName}?${qs.stringify(actionParameters)}`;
39
+ }
40
+ if (conditions.length === 0) {
41
+ return register({
42
+ action,
43
+ subject,
44
+ properties
45
+ });
46
+ }
47
+ const resolveConditions = _.map(providers.condition.get);
48
+ const removeInvalidConditions = _.filter((condition)=>_.isFunction(condition.handler));
49
+ const evaluateConditions = (conditions)=>{
50
+ return Promise.all(conditions.map(async (condition)=>({
51
+ condition,
52
+ result: await condition.handler(_.merge(options, {
53
+ permission: _.cloneDeep(permission)
54
+ }))
55
+ })));
56
+ };
57
+ const removeInvalidResults = _.filter(({ result })=>_.isBoolean(result) || _.isObject(result));
58
+ const evaluatedConditions = await Promise.resolve(conditions).then(resolveConditions).then(removeInvalidConditions).then(evaluateConditions).then(removeInvalidResults);
59
+ const resultPropEq = _.propEq('result');
60
+ const pickResults = _.map(_.prop('result'));
61
+ if (evaluatedConditions.every(resultPropEq(false))) {
62
+ return;
63
+ }
64
+ if (_.isEmpty(evaluatedConditions) || evaluatedConditions.some(resultPropEq(true))) {
65
+ return register({
66
+ action,
67
+ subject,
68
+ properties
69
+ });
70
+ }
71
+ const results = pickResults(evaluatedConditions).filter(_.isObject);
72
+ if (_.isEmpty(results)) {
73
+ return register({
74
+ action,
75
+ subject,
76
+ properties
77
+ });
78
+ }
79
+ return register({
80
+ action,
81
+ subject,
82
+ properties,
83
+ condition: {
84
+ $and: [
85
+ {
86
+ $or: results
87
+ }
88
+ ]
89
+ }
90
+ });
91
+ };
92
+ return {
93
+ get hooks () {
94
+ return state.hooks;
95
+ },
96
+ /**
97
+ * Create a register function that wraps a `can` function
98
+ * used to register a permission in the ability builder
99
+ */ createRegisterFunction (can, options) {
100
+ return async (permission)=>{
101
+ const hookContext = createWillRegisterContext({
102
+ options,
103
+ permission
104
+ });
105
+ await state.hooks['before-register.permission'].call(hookContext);
106
+ return can(permission);
107
+ };
108
+ },
109
+ /**
110
+ * Register a new handler for a given hook
111
+ */ on (hook, handler) {
112
+ const validHooks = Object.keys(state.hooks);
113
+ const isValidHook = validHooks.includes(hook);
114
+ if (!isValidHook) {
115
+ throw new Error(`Invalid hook supplied when trying to register an handler to the permission engine. Got "${hook}" but expected one of ${validHooks.join(', ')}`);
116
+ }
117
+ state.hooks[hook].register(handler);
118
+ return this;
119
+ },
120
+ /**
121
+ * Generate an ability based on the instance's
122
+ * ability builder and the given permissions
123
+ */ async generateAbility (permissions, options = {}) {
124
+ const { can, build } = abilityBuilderFactory();
125
+ for (const permission of permissions){
126
+ const register = this.createRegisterFunction(can, options);
127
+ await evaluate({
128
+ permission,
129
+ options,
130
+ register
131
+ });
132
+ }
133
+ return build();
134
+ }
135
+ };
136
+ };
137
+
138
+ export { newEngine as new };
139
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","sources":["../../src/engine/index.ts"],"sourcesContent":["import _ from 'lodash/fp';\nimport qs from 'qs';\nimport { Ability } from '@casl/ability';\nimport { providerFactory } from '@strapi/utils';\n\nimport {\n createEngineHooks,\n createWillRegisterContext,\n createBeforeEvaluateContext,\n createValidateContext,\n} from './hooks';\nimport type { PermissionEngineHooks, HookName } from './hooks';\n\nimport * as abilities from './abilities';\nimport { Permission } from '../domain/permission';\nimport type { PermissionRule } from '../types';\n\nexport { abilities };\n\ntype Provider = Omit<ReturnType<typeof providerFactory>, 'register'> & {\n register(...args: unknown[]): Promise<Provider> | Provider;\n};\n\ntype ActionProvider = Provider;\ntype ConditionProvider = Provider;\n\nexport interface Engine {\n hooks: PermissionEngineHooks;\n on(hook: HookName, handler: (...args: any[]) => any): Engine;\n generateAbility(permissions: Permission[], options?: object): Promise<Ability>;\n createRegisterFunction(\n can: (permission: PermissionRule) => unknown,\n options: Record<string, unknown>\n ): (permission: PermissionRule) => Promise<unknown>;\n}\n\nexport interface EngineParams {\n providers: { action: ActionProvider; condition: ConditionProvider };\n abilityBuilderFactory?(): abilities.CustomAbilityBuilder;\n}\n\ninterface EvaluateParams {\n options: Record<string, unknown>;\n register: (permission: PermissionRule) => Promise<unknown>;\n permission: Permission;\n}\n\ninterface Condition {\n name: string;\n handler(...params: unknown[]): boolean | object;\n}\n\n/**\n * Create a default state object for the engine\n */\nconst createEngineState = () => {\n const hooks = createEngineHooks();\n\n return { hooks };\n};\n\nconst newEngine = (params: EngineParams): Engine => {\n const { providers, abilityBuilderFactory = abilities.caslAbilityBuilder } = params;\n\n const state = createEngineState();\n\n const runValidationHook = async (hook: HookName, context: unknown) =>\n state.hooks[hook].call(context);\n\n /**\n * Evaluate a permission using local and registered behaviors (using hooks).\n * Validate, format (add condition, etc...), evaluate (evaluate conditions) and register a permission\n */\n const evaluate = async (params: EvaluateParams) => {\n const { options, register } = params;\n\n const preFormatValidation = await runValidationHook(\n 'before-format::validate.permission',\n createBeforeEvaluateContext(params.permission)\n );\n\n if (preFormatValidation === false) {\n return;\n }\n\n const permission = (await state.hooks['format.permission'].call(\n params.permission\n )) as Permission;\n\n const afterFormatValidation = await runValidationHook(\n 'after-format::validate.permission',\n createValidateContext(permission)\n );\n\n if (afterFormatValidation === false) {\n return;\n }\n\n await state.hooks['before-evaluate.permission'].call(createBeforeEvaluateContext(permission));\n\n const {\n action: actionName,\n subject,\n properties,\n conditions = [],\n actionParameters = {},\n } = permission;\n\n let action = actionName;\n\n if (actionParameters && Object.keys(actionParameters).length > 0) {\n action = `${actionName}?${qs.stringify(actionParameters)}`;\n }\n\n if (conditions.length === 0) {\n return register({ action, subject, properties });\n }\n\n const resolveConditions = _.map(providers.condition.get);\n\n const removeInvalidConditions = _.filter((condition: Condition) =>\n _.isFunction(condition.handler)\n );\n\n const evaluateConditions = (conditions: Condition[]) => {\n return Promise.all(\n conditions.map(async (condition) => ({\n condition,\n result: await condition.handler(\n _.merge(options, { permission: _.cloneDeep(permission) })\n ),\n }))\n );\n };\n\n const removeInvalidResults = _.filter(\n ({ result }) => _.isBoolean(result) || _.isObject(result)\n );\n\n const evaluatedConditions = await Promise.resolve(conditions)\n .then(resolveConditions)\n .then(removeInvalidConditions)\n .then(evaluateConditions)\n .then(removeInvalidResults);\n\n const resultPropEq = _.propEq('result');\n const pickResults = _.map(_.prop('result'));\n\n if (evaluatedConditions.every(resultPropEq(false))) {\n return;\n }\n\n if (_.isEmpty(evaluatedConditions) || evaluatedConditions.some(resultPropEq(true))) {\n return register({ action, subject, properties });\n }\n\n const results = pickResults(evaluatedConditions).filter(_.isObject);\n\n if (_.isEmpty(results)) {\n return register({ action, subject, properties });\n }\n\n return register({\n action,\n subject,\n properties,\n condition: { $and: [{ $or: results }] },\n });\n };\n\n return {\n get hooks() {\n return state.hooks;\n },\n\n /**\n * Create a register function that wraps a `can` function\n * used to register a permission in the ability builder\n */\n createRegisterFunction(can, options: Record<string, unknown>) {\n return async (permission: PermissionRule) => {\n const hookContext = createWillRegisterContext({ options, permission });\n\n await state.hooks['before-register.permission'].call(hookContext);\n\n return can(permission);\n };\n },\n\n /**\n * Register a new handler for a given hook\n */\n on(hook, handler) {\n const validHooks = Object.keys(state.hooks);\n const isValidHook = validHooks.includes(hook);\n\n if (!isValidHook) {\n throw new Error(\n `Invalid hook supplied when trying to register an handler to the permission engine. Got \"${hook}\" but expected one of ${validHooks.join(\n ', '\n )}`\n );\n }\n\n state.hooks[hook].register(handler);\n\n return this;\n },\n\n /**\n * Generate an ability based on the instance's\n * ability builder and the given permissions\n */\n async generateAbility(permissions, options: Record<string, unknown> = {}) {\n const { can, build } = abilityBuilderFactory();\n\n for (const permission of permissions) {\n const register = this.createRegisterFunction(can, options);\n\n await evaluate({ permission, options, register });\n }\n\n return build();\n },\n };\n};\n\nexport { newEngine as new };\n"],"names":["createEngineState","hooks","createEngineHooks","newEngine","params","providers","abilityBuilderFactory","abilities","state","runValidationHook","hook","context","call","evaluate","options","register","preFormatValidation","createBeforeEvaluateContext","permission","afterFormatValidation","createValidateContext","action","actionName","subject","properties","conditions","actionParameters","Object","keys","length","qs","stringify","resolveConditions","_","map","condition","get","removeInvalidConditions","filter","isFunction","handler","evaluateConditions","Promise","all","result","merge","cloneDeep","removeInvalidResults","isBoolean","isObject","evaluatedConditions","resolve","then","resultPropEq","propEq","pickResults","prop","every","isEmpty","some","results","$and","$or","createRegisterFunction","can","hookContext","createWillRegisterContext","on","validHooks","isValidHook","includes","Error","join","generateAbility","permissions","build"],"mappings":";;;;;;;AAoDA;;AAEC,IACD,MAAMA,iBAAoB,GAAA,IAAA;AACxB,IAAA,MAAMC,KAAQC,GAAAA,iBAAAA,EAAAA;IAEd,OAAO;AAAED,QAAAA;AAAM,KAAA;AACjB,CAAA;AAEA,MAAME,YAAY,CAACC,MAAAA,GAAAA;AACjB,IAAA,MAAM,EAAEC,SAAS,EAAEC,wBAAwBC,kBAA4B,EAAE,GAAGH,MAAAA;AAE5E,IAAA,MAAMI,KAAQR,GAAAA,iBAAAA,EAAAA;IAEd,MAAMS,iBAAAA,GAAoB,OAAOC,IAAAA,EAAgBC,OAC/CH,GAAAA,KAAAA,CAAMP,KAAK,CAACS,IAAAA,CAAK,CAACE,IAAI,CAACD,OAAAA,CAAAA;AAEzB;;;MAIA,MAAME,WAAW,OAAOT,MAAAA,GAAAA;AACtB,QAAA,MAAM,EAAEU,OAAO,EAAEC,QAAQ,EAAE,GAAGX,MAAAA;AAE9B,QAAA,MAAMY,sBAAsB,MAAMP,iBAAAA,CAChC,oCACAQ,EAAAA,2BAAAA,CAA4Bb,OAAOc,UAAU,CAAA,CAAA;AAG/C,QAAA,IAAIF,wBAAwB,KAAO,EAAA;AACjC,YAAA;AACF;QAEA,MAAME,UAAAA,GAAc,MAAMV,KAAAA,CAAMP,KAAK,CAAC,oBAAoB,CAACW,IAAI,CAC7DR,MAAAA,CAAOc,UAAU,CAAA;AAGnB,QAAA,MAAMC,qBAAwB,GAAA,MAAMV,iBAClC,CAAA,mCAAA,EACAW,qBAAsBF,CAAAA,UAAAA,CAAAA,CAAAA;AAGxB,QAAA,IAAIC,0BAA0B,KAAO,EAAA;AACnC,YAAA;AACF;AAEA,QAAA,MAAMX,MAAMP,KAAK,CAAC,6BAA6B,CAACW,IAAI,CAACK,2BAA4BC,CAAAA,UAAAA,CAAAA,CAAAA;AAEjF,QAAA,MAAM,EACJG,MAAAA,EAAQC,UAAU,EAClBC,OAAO,EACPC,UAAU,EACVC,UAAAA,GAAa,EAAE,EACfC,gBAAAA,GAAmB,EAAE,EACtB,GAAGR,UAAAA;AAEJ,QAAA,IAAIG,MAASC,GAAAA,UAAAA;AAEb,QAAA,IAAII,oBAAoBC,MAAOC,CAAAA,IAAI,CAACF,gBAAkBG,CAAAA,CAAAA,MAAM,GAAG,CAAG,EAAA;YAChER,MAAS,GAAA,CAAC,EAAEC,UAAW,CAAA,CAAC,EAAEQ,EAAGC,CAAAA,SAAS,CAACL,gBAAAA,CAAAA,CAAkB,CAAC;AAC5D;QAEA,IAAID,UAAAA,CAAWI,MAAM,KAAK,CAAG,EAAA;AAC3B,YAAA,OAAOd,QAAS,CAAA;AAAEM,gBAAAA,MAAAA;AAAQE,gBAAAA,OAAAA;AAASC,gBAAAA;AAAW,aAAA,CAAA;AAChD;AAEA,QAAA,MAAMQ,oBAAoBC,CAAEC,CAAAA,GAAG,CAAC7B,SAAU8B,CAAAA,SAAS,CAACC,GAAG,CAAA;QAEvD,MAAMC,uBAAAA,GAA0BJ,CAAEK,CAAAA,MAAM,CAAC,CAACH,YACxCF,CAAEM,CAAAA,UAAU,CAACJ,SAAAA,CAAUK,OAAO,CAAA,CAAA;AAGhC,QAAA,MAAMC,qBAAqB,CAAChB,UAAAA,GAAAA;YAC1B,OAAOiB,OAAAA,CAAQC,GAAG,CAChBlB,UAAAA,CAAWS,GAAG,CAAC,OAAOC,aAAe;AACnCA,oBAAAA,SAAAA;AACAS,oBAAAA,MAAAA,EAAQ,MAAMT,SAAUK,CAAAA,OAAO,CAC7BP,CAAEY,CAAAA,KAAK,CAAC/B,OAAS,EAAA;wBAAEI,UAAYe,EAAAA,CAAAA,CAAEa,SAAS,CAAC5B,UAAAA;AAAY,qBAAA,CAAA;iBAE3D,CAAA,CAAA,CAAA;AAEJ,SAAA;AAEA,QAAA,MAAM6B,oBAAuBd,GAAAA,CAAAA,CAAEK,MAAM,CACnC,CAAC,EAAEM,MAAM,EAAE,GAAKX,EAAEe,SAAS,CAACJ,MAAWX,CAAAA,IAAAA,CAAAA,CAAEgB,QAAQ,CAACL,MAAAA,CAAAA,CAAAA;AAGpD,QAAA,MAAMM,sBAAsB,MAAMR,OAAAA,CAAQS,OAAO,CAAC1B,YAC/C2B,IAAI,CAACpB,iBACLoB,CAAAA,CAAAA,IAAI,CAACf,uBACLe,CAAAA,CAAAA,IAAI,CAACX,kBAAAA,CAAAA,CACLW,IAAI,CAACL,oBAAAA,CAAAA;QAER,MAAMM,YAAAA,GAAepB,CAAEqB,CAAAA,MAAM,CAAC,QAAA,CAAA;AAC9B,QAAA,MAAMC,cAActB,CAAEC,CAAAA,GAAG,CAACD,CAAAA,CAAEuB,IAAI,CAAC,QAAA,CAAA,CAAA;AAEjC,QAAA,IAAIN,mBAAoBO,CAAAA,KAAK,CAACJ,YAAAA,CAAa,KAAS,CAAA,CAAA,EAAA;AAClD,YAAA;AACF;QAEA,IAAIpB,CAAAA,CAAEyB,OAAO,CAACR,mBAAAA,CAAAA,IAAwBA,oBAAoBS,IAAI,CAACN,aAAa,IAAQ,CAAA,CAAA,EAAA;AAClF,YAAA,OAAOtC,QAAS,CAAA;AAAEM,gBAAAA,MAAAA;AAAQE,gBAAAA,OAAAA;AAASC,gBAAAA;AAAW,aAAA,CAAA;AAChD;AAEA,QAAA,MAAMoC,UAAUL,WAAYL,CAAAA,mBAAAA,CAAAA,CAAqBZ,MAAM,CAACL,EAAEgB,QAAQ,CAAA;QAElE,IAAIhB,CAAAA,CAAEyB,OAAO,CAACE,OAAU,CAAA,EAAA;AACtB,YAAA,OAAO7C,QAAS,CAAA;AAAEM,gBAAAA,MAAAA;AAAQE,gBAAAA,OAAAA;AAASC,gBAAAA;AAAW,aAAA,CAAA;AAChD;AAEA,QAAA,OAAOT,QAAS,CAAA;AACdM,YAAAA,MAAAA;AACAE,YAAAA,OAAAA;AACAC,YAAAA,UAAAA;YACAW,SAAW,EAAA;gBAAE0B,IAAM,EAAA;AAAC,oBAAA;wBAAEC,GAAKF,EAAAA;AAAQ;AAAE;AAAC;AACxC,SAAA,CAAA;AACF,KAAA;IAEA,OAAO;AACL,QAAA,IAAI3D,KAAQ,CAAA,GAAA;AACV,YAAA,OAAOO,MAAMP,KAAK;AACpB,SAAA;AAEA;;;QAIA8D,sBAAAA,CAAAA,CAAuBC,GAAG,EAAElD,OAAgC,EAAA;AAC1D,YAAA,OAAO,OAAOI,UAAAA,GAAAA;AACZ,gBAAA,MAAM+C,cAAcC,yBAA0B,CAAA;AAAEpD,oBAAAA,OAAAA;AAASI,oBAAAA;AAAW,iBAAA,CAAA;AAEpE,gBAAA,MAAMV,MAAMP,KAAK,CAAC,4BAA6B,CAAA,CAACW,IAAI,CAACqD,WAAAA,CAAAA;AAErD,gBAAA,OAAOD,GAAI9C,CAAAA,UAAAA,CAAAA;AACb,aAAA;AACF,SAAA;AAEA;;QAGAiD,EAAAA,CAAAA,CAAGzD,IAAI,EAAE8B,OAAO,EAAA;AACd,YAAA,MAAM4B,UAAazC,GAAAA,MAAAA,CAAOC,IAAI,CAACpB,MAAMP,KAAK,CAAA;YAC1C,MAAMoE,WAAAA,GAAcD,UAAWE,CAAAA,QAAQ,CAAC5D,IAAAA,CAAAA;AAExC,YAAA,IAAI,CAAC2D,WAAa,EAAA;AAChB,gBAAA,MAAM,IAAIE,KAAAA,CACR,CAAC,wFAAwF,EAAE7D,IAAAA,CAAK,sBAAsB,EAAE0D,UAAWI,CAAAA,IAAI,CACrI,IAAA,CAAA,CACA,CAAC,CAAA;AAEP;AAEAhE,YAAAA,KAAAA,CAAMP,KAAK,CAACS,IAAK,CAAA,CAACK,QAAQ,CAACyB,OAAAA,CAAAA;AAE3B,YAAA,OAAO,IAAI;AACb,SAAA;AAEA;;;AAGC,QACD,MAAMiC,eAAgBC,CAAAA,CAAAA,WAAW,EAAE5D,OAAAA,GAAmC,EAAE,EAAA;AACtE,YAAA,MAAM,EAAEkD,GAAG,EAAEW,KAAK,EAAE,GAAGrE,qBAAAA,EAAAA;YAEvB,KAAK,MAAMY,cAAcwD,WAAa,CAAA;AACpC,gBAAA,MAAM3D,QAAW,GAAA,IAAI,CAACgD,sBAAsB,CAACC,GAAKlD,EAAAA,OAAAA,CAAAA;AAElD,gBAAA,MAAMD,QAAS,CAAA;AAAEK,oBAAAA,UAAAA;AAAYJ,oBAAAA,OAAAA;AAASC,oBAAAA;AAAS,iBAAA,CAAA;AACjD;YAEA,OAAO4D,KAAAA,EAAAA;AACT;AACF,KAAA;AACF;;;;"}
package/dist/index.js CHANGED
@@ -1,345 +1,10 @@
1
1
  'use strict';
2
2
 
3
- var _ = require('lodash/fp');
4
- var qs = require('qs');
5
- var utils = require('@strapi/utils');
6
- var sift = require('sift');
7
- var ability = require('@casl/ability');
3
+ var index = require('./domain/index.js');
4
+ var index$1 = require('./engine/index.js');
8
5
 
9
- function _interopNamespaceDefault(e) {
10
- var n = Object.create(null);
11
- if (e) {
12
- Object.keys(e).forEach(function (k) {
13
- if (k !== 'default') {
14
- var d = Object.getOwnPropertyDescriptor(e, k);
15
- Object.defineProperty(n, k, d.get ? d : {
16
- enumerable: true,
17
- get: function () { return e[k]; }
18
- });
19
- }
20
- });
21
- }
22
- n.default = e;
23
- return Object.freeze(n);
24
- }
25
6
 
26
- var sift__namespace = /*#__PURE__*/_interopNamespaceDefault(sift);
27
7
 
28
- const PERMISSION_FIELDS = [
29
- 'action',
30
- 'subject',
31
- 'properties',
32
- 'conditions'
33
- ];
34
- const sanitizePermissionFields = _.pick(PERMISSION_FIELDS);
35
- /**
36
- * Creates a permission with default values for optional properties
37
- */ const getDefaultPermission = ()=>({
38
- conditions: [],
39
- properties: {},
40
- subject: null
41
- });
42
- /**
43
- * Create a new permission based on given attributes
44
- *
45
- * @param {object} attributes
46
- */ const create = _.pipe(_.pick(PERMISSION_FIELDS), _.merge(getDefaultPermission()));
47
- /**
48
- * Add a condition to a permission
49
- */ const addCondition = _.curry((condition, permission)=>{
50
- const { conditions } = permission;
51
- const newConditions = Array.isArray(conditions) ? _.uniq(conditions.concat(condition)) : [
52
- condition
53
- ];
54
- return _.set('conditions', newConditions, permission);
55
- });
56
- /**
57
- * Gets a property or a part of a property from a permission.
58
- */ const getProperty = _.curry((property, permission)=>_.get(`properties.${property}`, permission));
59
-
60
- var index$3 = /*#__PURE__*/Object.freeze({
61
- __proto__: null,
62
- addCondition: addCondition,
63
- create: create,
64
- getProperty: getProperty,
65
- sanitizePermissionFields: sanitizePermissionFields
66
- });
67
-
68
- var index$2 = /*#__PURE__*/Object.freeze({
69
- __proto__: null,
70
- permission: index$3
71
- });
72
-
73
- /**
74
- * Create a hook map used by the permission Engine
75
- */ const createEngineHooks = ()=>({
76
- 'before-format::validate.permission': utils.hooks.createAsyncBailHook(),
77
- 'format.permission': utils.hooks.createAsyncSeriesWaterfallHook(),
78
- 'after-format::validate.permission': utils.hooks.createAsyncBailHook(),
79
- 'before-evaluate.permission': utils.hooks.createAsyncSeriesHook(),
80
- 'before-register.permission': utils.hooks.createAsyncSeriesHook()
81
- });
82
- /**
83
- * Create a context from a domain {@link Permission} used by the validate hooks
84
- */ const createValidateContext = (permission)=>({
85
- get permission () {
86
- return _.cloneDeep(permission);
87
- }
88
- });
89
- /**
90
- * Create a context from a domain {@link Permission} used by the before valuate hook
91
- */ const createBeforeEvaluateContext = (permission)=>({
92
- get permission () {
93
- return _.cloneDeep(permission);
94
- },
95
- addCondition (condition) {
96
- Object.assign(permission, addCondition(condition, permission));
97
- return this;
98
- }
99
- });
100
- /**
101
- * Create a context from a casl Permission & some options
102
- * @param caslPermission
103
- */ const createWillRegisterContext = ({ permission, options })=>({
104
- ...options,
105
- get permission () {
106
- return _.cloneDeep(permission);
107
- },
108
- condition: {
109
- and (rawConditionObject) {
110
- if (!permission.condition) {
111
- permission.condition = {
112
- $and: []
113
- };
114
- }
115
- if (_.isArray(permission.condition.$and)) {
116
- permission.condition.$and.push(rawConditionObject);
117
- }
118
- return this;
119
- },
120
- or (rawConditionObject) {
121
- if (!permission.condition) {
122
- permission.condition = {
123
- $and: []
124
- };
125
- }
126
- if (_.isArray(permission.condition.$and)) {
127
- const orClause = permission.condition.$and.find(_.has('$or'));
128
- if (orClause) {
129
- orClause.$or.push(rawConditionObject);
130
- } else {
131
- permission.condition.$and.push({
132
- $or: [
133
- rawConditionObject
134
- ]
135
- });
136
- }
137
- }
138
- return this;
139
- }
140
- }
141
- });
142
-
143
- const allowedOperations = [
144
- '$or',
145
- '$and',
146
- '$eq',
147
- '$ne',
148
- '$in',
149
- '$nin',
150
- '$lt',
151
- '$lte',
152
- '$gt',
153
- '$gte',
154
- '$exists',
155
- '$elemMatch'
156
- ];
157
- const operations = _.pick(allowedOperations, sift__namespace);
158
- const conditionsMatcher = (conditions)=>{
159
- return sift__namespace.createQueryTester(conditions, {
160
- operations
161
- });
162
- };
163
- const buildParametrizedAction = ({ name, params })=>{
164
- return `${name}?${qs.stringify(params)}`;
165
- };
166
- /**
167
- * Casl Ability Builder.
168
- */ const caslAbilityBuilder = ()=>{
169
- const { can, build, ...rest } = new ability.AbilityBuilder(ability.Ability);
170
- return {
171
- can (permission) {
172
- const { action, subject, properties = {}, condition } = permission;
173
- const { fields } = properties;
174
- const caslAction = typeof action === 'string' ? action : buildParametrizedAction(action);
175
- return can(caslAction, _.isNil(subject) ? 'all' : subject, fields, _.isObject(condition) ? condition : undefined);
176
- },
177
- buildParametrizedAction ({ name, params }) {
178
- return `${name}?${qs.stringify(params)}`;
179
- },
180
- build () {
181
- const ability = build({
182
- conditionsMatcher
183
- });
184
- function decorateCan(originalCan) {
185
- return function(...args) {
186
- const [action, ...rest] = args;
187
- const caslAction = typeof action === 'string' ? action : buildParametrizedAction(action);
188
- // Call the original `can` method
189
- return originalCan.apply(ability, [
190
- caslAction,
191
- ...rest
192
- ]);
193
- };
194
- }
195
- ability.can = decorateCan(ability.can);
196
- return ability;
197
- },
198
- ...rest
199
- };
200
- };
201
-
202
- var index$1 = /*#__PURE__*/Object.freeze({
203
- __proto__: null,
204
- caslAbilityBuilder: caslAbilityBuilder
205
- });
206
-
207
- /**
208
- * Create a default state object for the engine
209
- */ const createEngineState = ()=>{
210
- const hooks = createEngineHooks();
211
- return {
212
- hooks
213
- };
214
- };
215
- const newEngine = (params)=>{
216
- const { providers, abilityBuilderFactory = caslAbilityBuilder } = params;
217
- const state = createEngineState();
218
- const runValidationHook = async (hook, context)=>state.hooks[hook].call(context);
219
- /**
220
- * Evaluate a permission using local and registered behaviors (using hooks).
221
- * Validate, format (add condition, etc...), evaluate (evaluate conditions) and register a permission
222
- */ const evaluate = async (params)=>{
223
- const { options, register } = params;
224
- const preFormatValidation = await runValidationHook('before-format::validate.permission', createBeforeEvaluateContext(params.permission));
225
- if (preFormatValidation === false) {
226
- return;
227
- }
228
- const permission = await state.hooks['format.permission'].call(params.permission);
229
- const afterFormatValidation = await runValidationHook('after-format::validate.permission', createValidateContext(permission));
230
- if (afterFormatValidation === false) {
231
- return;
232
- }
233
- await state.hooks['before-evaluate.permission'].call(createBeforeEvaluateContext(permission));
234
- const { action: actionName, subject, properties, conditions = [], actionParameters = {} } = permission;
235
- let action = actionName;
236
- if (actionParameters && Object.keys(actionParameters).length > 0) {
237
- action = `${actionName}?${qs.stringify(actionParameters)}`;
238
- }
239
- if (conditions.length === 0) {
240
- return register({
241
- action,
242
- subject,
243
- properties
244
- });
245
- }
246
- const resolveConditions = _.map(providers.condition.get);
247
- const removeInvalidConditions = _.filter((condition)=>_.isFunction(condition.handler));
248
- const evaluateConditions = (conditions)=>{
249
- return Promise.all(conditions.map(async (condition)=>({
250
- condition,
251
- result: await condition.handler(_.merge(options, {
252
- permission: _.cloneDeep(permission)
253
- }))
254
- })));
255
- };
256
- const removeInvalidResults = _.filter(({ result })=>_.isBoolean(result) || _.isObject(result));
257
- const evaluatedConditions = await Promise.resolve(conditions).then(resolveConditions).then(removeInvalidConditions).then(evaluateConditions).then(removeInvalidResults);
258
- const resultPropEq = _.propEq('result');
259
- const pickResults = _.map(_.prop('result'));
260
- if (evaluatedConditions.every(resultPropEq(false))) {
261
- return;
262
- }
263
- if (_.isEmpty(evaluatedConditions) || evaluatedConditions.some(resultPropEq(true))) {
264
- return register({
265
- action,
266
- subject,
267
- properties
268
- });
269
- }
270
- const results = pickResults(evaluatedConditions).filter(_.isObject);
271
- if (_.isEmpty(results)) {
272
- return register({
273
- action,
274
- subject,
275
- properties
276
- });
277
- }
278
- return register({
279
- action,
280
- subject,
281
- properties,
282
- condition: {
283
- $and: [
284
- {
285
- $or: results
286
- }
287
- ]
288
- }
289
- });
290
- };
291
- return {
292
- get hooks () {
293
- return state.hooks;
294
- },
295
- /**
296
- * Create a register function that wraps a `can` function
297
- * used to register a permission in the ability builder
298
- */ createRegisterFunction (can, options) {
299
- return async (permission)=>{
300
- const hookContext = createWillRegisterContext({
301
- options,
302
- permission
303
- });
304
- await state.hooks['before-register.permission'].call(hookContext);
305
- return can(permission);
306
- };
307
- },
308
- /**
309
- * Register a new handler for a given hook
310
- */ on (hook, handler) {
311
- const validHooks = Object.keys(state.hooks);
312
- const isValidHook = validHooks.includes(hook);
313
- if (!isValidHook) {
314
- throw new Error(`Invalid hook supplied when trying to register an handler to the permission engine. Got "${hook}" but expected one of ${validHooks.join(', ')}`);
315
- }
316
- state.hooks[hook].register(handler);
317
- return this;
318
- },
319
- /**
320
- * Generate an ability based on the instance's
321
- * ability builder and the given permissions
322
- */ async generateAbility (permissions, options = {}) {
323
- const { can, build } = abilityBuilderFactory();
324
- for (const permission of permissions){
325
- const register = this.createRegisterFunction(can, options);
326
- await evaluate({
327
- permission,
328
- options,
329
- register
330
- });
331
- }
332
- return build();
333
- }
334
- };
335
- };
336
-
337
- var index = /*#__PURE__*/Object.freeze({
338
- __proto__: null,
339
- abilities: index$1,
340
- new: newEngine
341
- });
342
-
343
- exports.domain = index$2;
344
- exports.engine = index;
8
+ exports.domain = index;
9
+ exports.engine = index$1;
345
10
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/domain/permission/index.ts","../src/engine/hooks.ts","../src/engine/abilities/casl-ability.ts","../src/engine/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","import { cloneDeep, has, isArray } from 'lodash/fp';\nimport { hooks } from '@strapi/utils';\n\nimport * as domain from '../domain';\nimport type { Permission } from '../domain/permission';\nimport type { PermissionRule } from '../types';\n\nexport interface PermissionEngineHooks {\n 'before-format::validate.permission': ReturnType<typeof hooks.createAsyncBailHook>;\n 'format.permission': ReturnType<typeof hooks.createAsyncSeriesWaterfallHook>;\n 'after-format::validate.permission': ReturnType<typeof hooks.createAsyncBailHook>;\n 'before-evaluate.permission': ReturnType<typeof hooks.createAsyncSeriesHook>;\n 'before-register.permission': ReturnType<typeof hooks.createAsyncSeriesHook>;\n}\n\nexport type HookName = keyof PermissionEngineHooks;\n\n/**\n * Create a hook map used by the permission Engine\n */\nconst createEngineHooks = (): PermissionEngineHooks => ({\n 'before-format::validate.permission': hooks.createAsyncBailHook(),\n 'format.permission': hooks.createAsyncSeriesWaterfallHook(),\n 'after-format::validate.permission': hooks.createAsyncBailHook(),\n 'before-evaluate.permission': hooks.createAsyncSeriesHook(),\n 'before-register.permission': hooks.createAsyncSeriesHook(),\n});\n\n/**\n * Create a context from a domain {@link Permission} used by the validate hooks\n */\nconst createValidateContext = (permission: Permission) => ({\n get permission(): Readonly<Permission> {\n return cloneDeep(permission);\n },\n});\n\n/**\n * Create a context from a domain {@link Permission} used by the before valuate hook\n */\nconst createBeforeEvaluateContext = (permission: Permission) => ({\n get permission(): Readonly<Permission> {\n return cloneDeep(permission);\n },\n\n addCondition(condition: string) {\n Object.assign(permission, domain.permission.addCondition(condition, permission));\n\n return this;\n },\n});\n\ninterface WillRegisterContextParams {\n permission: PermissionRule;\n options: Record<string, unknown>;\n}\n\n/**\n * Create a context from a casl Permission & some options\n * @param caslPermission\n */\nconst createWillRegisterContext = ({ permission, options }: WillRegisterContextParams) => ({\n ...options,\n\n get permission() {\n return cloneDeep(permission);\n },\n\n condition: {\n and(rawConditionObject: unknown) {\n if (!permission.condition) {\n permission.condition = { $and: [] };\n }\n\n if (isArray(permission.condition.$and)) {\n permission.condition.$and.push(rawConditionObject);\n }\n\n return this;\n },\n\n or(rawConditionObject: unknown) {\n if (!permission.condition) {\n permission.condition = { $and: [] };\n }\n\n if (isArray(permission.condition.$and)) {\n const orClause = permission.condition.$and.find(has('$or'));\n\n if (orClause) {\n orClause.$or.push(rawConditionObject);\n } else {\n permission.condition.$and.push({ $or: [rawConditionObject] });\n }\n }\n\n return this;\n },\n },\n});\n\nexport {\n createEngineHooks,\n createValidateContext,\n createBeforeEvaluateContext,\n createWillRegisterContext,\n};\n","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","import _ from 'lodash/fp';\nimport qs from 'qs';\nimport { Ability } from '@casl/ability';\nimport { providerFactory } from '@strapi/utils';\n\nimport {\n createEngineHooks,\n createWillRegisterContext,\n createBeforeEvaluateContext,\n createValidateContext,\n} from './hooks';\nimport type { PermissionEngineHooks, HookName } from './hooks';\n\nimport * as abilities from './abilities';\nimport { Permission } from '../domain/permission';\nimport type { PermissionRule } from '../types';\n\nexport { abilities };\n\ntype Provider = Omit<ReturnType<typeof providerFactory>, 'register'> & {\n register(...args: unknown[]): Promise<Provider> | Provider;\n};\n\ntype ActionProvider = Provider;\ntype ConditionProvider = Provider;\n\nexport interface Engine {\n hooks: PermissionEngineHooks;\n on(hook: HookName, handler: (...args: any[]) => any): Engine;\n generateAbility(permissions: Permission[], options?: object): Promise<Ability>;\n createRegisterFunction(\n can: (permission: PermissionRule) => unknown,\n options: Record<string, unknown>\n ): (permission: PermissionRule) => Promise<unknown>;\n}\n\nexport interface EngineParams {\n providers: { action: ActionProvider; condition: ConditionProvider };\n abilityBuilderFactory?(): abilities.CustomAbilityBuilder;\n}\n\ninterface EvaluateParams {\n options: Record<string, unknown>;\n register: (permission: PermissionRule) => Promise<unknown>;\n permission: Permission;\n}\n\ninterface Condition {\n name: string;\n handler(...params: unknown[]): boolean | object;\n}\n\n/**\n * Create a default state object for the engine\n */\nconst createEngineState = () => {\n const hooks = createEngineHooks();\n\n return { hooks };\n};\n\nconst newEngine = (params: EngineParams): Engine => {\n const { providers, abilityBuilderFactory = abilities.caslAbilityBuilder } = params;\n\n const state = createEngineState();\n\n const runValidationHook = async (hook: HookName, context: unknown) =>\n state.hooks[hook].call(context);\n\n /**\n * Evaluate a permission using local and registered behaviors (using hooks).\n * Validate, format (add condition, etc...), evaluate (evaluate conditions) and register a permission\n */\n const evaluate = async (params: EvaluateParams) => {\n const { options, register } = params;\n\n const preFormatValidation = await runValidationHook(\n 'before-format::validate.permission',\n createBeforeEvaluateContext(params.permission)\n );\n\n if (preFormatValidation === false) {\n return;\n }\n\n const permission = (await state.hooks['format.permission'].call(\n params.permission\n )) as Permission;\n\n const afterFormatValidation = await runValidationHook(\n 'after-format::validate.permission',\n createValidateContext(permission)\n );\n\n if (afterFormatValidation === false) {\n return;\n }\n\n await state.hooks['before-evaluate.permission'].call(createBeforeEvaluateContext(permission));\n\n const {\n action: actionName,\n subject,\n properties,\n conditions = [],\n actionParameters = {},\n } = permission;\n\n let action = actionName;\n\n if (actionParameters && Object.keys(actionParameters).length > 0) {\n action = `${actionName}?${qs.stringify(actionParameters)}`;\n }\n\n if (conditions.length === 0) {\n return register({ action, subject, properties });\n }\n\n const resolveConditions = _.map(providers.condition.get);\n\n const removeInvalidConditions = _.filter((condition: Condition) =>\n _.isFunction(condition.handler)\n );\n\n const evaluateConditions = (conditions: Condition[]) => {\n return Promise.all(\n conditions.map(async (condition) => ({\n condition,\n result: await condition.handler(\n _.merge(options, { permission: _.cloneDeep(permission) })\n ),\n }))\n );\n };\n\n const removeInvalidResults = _.filter(\n ({ result }) => _.isBoolean(result) || _.isObject(result)\n );\n\n const evaluatedConditions = await Promise.resolve(conditions)\n .then(resolveConditions)\n .then(removeInvalidConditions)\n .then(evaluateConditions)\n .then(removeInvalidResults);\n\n const resultPropEq = _.propEq('result');\n const pickResults = _.map(_.prop('result'));\n\n if (evaluatedConditions.every(resultPropEq(false))) {\n return;\n }\n\n if (_.isEmpty(evaluatedConditions) || evaluatedConditions.some(resultPropEq(true))) {\n return register({ action, subject, properties });\n }\n\n const results = pickResults(evaluatedConditions).filter(_.isObject);\n\n if (_.isEmpty(results)) {\n return register({ action, subject, properties });\n }\n\n return register({\n action,\n subject,\n properties,\n condition: { $and: [{ $or: results }] },\n });\n };\n\n return {\n get hooks() {\n return state.hooks;\n },\n\n /**\n * Create a register function that wraps a `can` function\n * used to register a permission in the ability builder\n */\n createRegisterFunction(can, options: Record<string, unknown>) {\n return async (permission: PermissionRule) => {\n const hookContext = createWillRegisterContext({ options, permission });\n\n await state.hooks['before-register.permission'].call(hookContext);\n\n return can(permission);\n };\n },\n\n /**\n * Register a new handler for a given hook\n */\n on(hook, handler) {\n const validHooks = Object.keys(state.hooks);\n const isValidHook = validHooks.includes(hook);\n\n if (!isValidHook) {\n throw new Error(\n `Invalid hook supplied when trying to register an handler to the permission engine. Got \"${hook}\" but expected one of ${validHooks.join(\n ', '\n )}`\n );\n }\n\n state.hooks[hook].register(handler);\n\n return this;\n },\n\n /**\n * Generate an ability based on the instance's\n * ability builder and the given permissions\n */\n async generateAbility(permissions, options: Record<string, unknown> = {}) {\n const { can, build } = abilityBuilderFactory();\n\n for (const permission of permissions) {\n const register = this.createRegisterFunction(can, options);\n\n await evaluate({ permission, options, register });\n }\n\n return build();\n },\n };\n};\n\nexport { newEngine as new };\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","createEngineHooks","hooks","createAsyncBailHook","createAsyncSeriesWaterfallHook","createAsyncSeriesHook","createValidateContext","cloneDeep","createBeforeEvaluateContext","Object","assign","domain","createWillRegisterContext","options","and","rawConditionObject","$and","push","or","orClause","find","has","$or","allowedOperations","operations","sift","conditionsMatcher","createQueryTester","buildParametrizedAction","name","params","qs","stringify","caslAbilityBuilder","can","build","rest","AbilityBuilder","Ability","action","fields","caslAction","isNil","isObject","undefined","ability","decorateCan","originalCan","args","apply","createEngineState","newEngine","providers","abilityBuilderFactory","abilities","state","runValidationHook","hook","context","call","evaluate","register","preFormatValidation","afterFormatValidation","actionName","actionParameters","keys","length","resolveConditions","map","removeInvalidConditions","filter","isFunction","handler","evaluateConditions","Promise","all","result","removeInvalidResults","isBoolean","evaluatedConditions","resolve","then","resultPropEq","propEq","pickResults","prop","every","isEmpty","some","results","createRegisterFunction","hookContext","on","validHooks","isValidHook","includes","Error","join","generateAbility","permissions"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;"}