/
hooks.ts
107 lines (88 loc) 路 2.98 KB
/
hooks.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import { cloneDeep, has, isArray } from 'lodash/fp';
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
*/
const createEngineHooks = (): PermissionEngineHooks => ({
'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: Permission) => ({
get permission(): Readonly<Permission> {
return cloneDeep(permission);
},
});
/**
* Create a context from a domain {@link Permission} used by the before valuate hook
*/
const createBeforeEvaluateContext = (permission: Permission) => ({
get permission(): Readonly<Permission> {
return cloneDeep(permission);
},
addCondition(condition: string) {
Object.assign(permission, domain.permission.addCondition(condition, permission));
return this;
},
});
interface WillRegisterContextParams {
permission: PermissionRule;
options: Record<string, unknown>;
}
/**
* Create a context from a casl Permission & some options
* @param caslPermission
*/
const createWillRegisterContext = ({ permission, options }: WillRegisterContextParams) => ({
...options,
get permission() {
return cloneDeep(permission);
},
condition: {
and(rawConditionObject: unknown) {
if (!permission.condition) {
permission.condition = { $and: [] };
}
if (isArray(permission.condition.$and)) {
permission.condition.$and.push(rawConditionObject);
}
return this;
},
or(rawConditionObject: unknown) {
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 {
createEngineHooks,
createValidateContext,
createBeforeEvaluateContext,
createWillRegisterContext,
};