@tachybase/acl 0.23.8

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,184 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var acl_role_exports = {};
30
+ __export(acl_role_exports, {
31
+ ACLRole: () => ACLRole
32
+ });
33
+ module.exports = __toCommonJS(acl_role_exports);
34
+ var import_lodash = __toESM(require("lodash"));
35
+ var import_minimatch = __toESM(require("minimatch"));
36
+ var import_acl_available_strategy = require("./acl-available-strategy");
37
+ var import_acl_resource = require("./acl-resource");
38
+ const _ACLRole = class _ACLRole {
39
+ constructor(acl, name) {
40
+ this.acl = acl;
41
+ this.name = name;
42
+ }
43
+ strategy;
44
+ resources = /* @__PURE__ */ new Map();
45
+ snippets = /* @__PURE__ */ new Set();
46
+ _snippetCache = {
47
+ params: null,
48
+ result: null
49
+ };
50
+ _serializeSet(set) {
51
+ return JSON.stringify([...set].sort());
52
+ }
53
+ getResource(name) {
54
+ return this.resources.get(name);
55
+ }
56
+ setStrategy(value) {
57
+ this.strategy = value;
58
+ }
59
+ getStrategy() {
60
+ if (!this.strategy) {
61
+ return null;
62
+ }
63
+ return import_lodash.default.isString(this.strategy) ? this.acl.availableStrategy.get(this.strategy) : new import_acl_available_strategy.ACLAvailableStrategy(this.acl, this.strategy);
64
+ }
65
+ getResourceActionsParams(resourceName) {
66
+ const resource = this.getResource(resourceName);
67
+ return resource.getActions();
68
+ }
69
+ revokeResource(resourceName) {
70
+ for (const key of [...this.resources.keys()]) {
71
+ if (key === resourceName || key.includes(`${resourceName}.`)) {
72
+ this.resources.delete(key);
73
+ }
74
+ }
75
+ }
76
+ grantAction(path, options) {
77
+ let { resource } = this.getResourceActionFromPath(path);
78
+ const { resourceName, actionName } = this.getResourceActionFromPath(path);
79
+ if (!resource) {
80
+ resource = new import_acl_resource.ACLResource({
81
+ role: this,
82
+ name: resourceName
83
+ });
84
+ this.resources.set(resourceName, resource);
85
+ }
86
+ resource.setAction(actionName, options);
87
+ }
88
+ getActionParams(path) {
89
+ const { action } = this.getResourceActionFromPath(path);
90
+ return action;
91
+ }
92
+ revokeAction(path) {
93
+ const { resource, actionName } = this.getResourceActionFromPath(path);
94
+ resource.removeAction(actionName);
95
+ }
96
+ effectiveSnippets() {
97
+ const currentParams = this._serializeSet(this.snippets);
98
+ if (this._snippetCache.params === currentParams) {
99
+ return this._snippetCache.result;
100
+ }
101
+ const allowedSnippets = /* @__PURE__ */ new Set();
102
+ const rejectedSnippets = /* @__PURE__ */ new Set();
103
+ const availableSnippets = this.acl.snippetManager.snippets;
104
+ for (let snippetRule of this.snippets) {
105
+ const negated = snippetRule.startsWith("!");
106
+ snippetRule = negated ? snippetRule.slice(1) : snippetRule;
107
+ for (const [_, availableSnippet] of availableSnippets) {
108
+ if ((0, import_minimatch.default)(availableSnippet.name, snippetRule)) {
109
+ if (negated) {
110
+ rejectedSnippets.add(availableSnippet.name);
111
+ } else {
112
+ allowedSnippets.add(availableSnippet.name);
113
+ }
114
+ }
115
+ }
116
+ }
117
+ const effectiveSnippets = new Set([...allowedSnippets].filter((x) => !rejectedSnippets.has(x)));
118
+ this._snippetCache = {
119
+ params: currentParams,
120
+ result: {
121
+ allowed: [...effectiveSnippets],
122
+ rejected: [...rejectedSnippets]
123
+ }
124
+ };
125
+ return this._snippetCache.result;
126
+ }
127
+ snippetAllowed(actionPath) {
128
+ const effectiveSnippets = this.effectiveSnippets();
129
+ const getActions = /* @__PURE__ */ __name((snippets) => {
130
+ return snippets.map((snippetName) => this.acl.snippetManager.snippets.get(snippetName).actions).flat();
131
+ }, "getActions");
132
+ const allowedActions = getActions(effectiveSnippets.allowed);
133
+ const rejectedActions = getActions(effectiveSnippets.rejected);
134
+ const actionMatched = /* @__PURE__ */ __name((actionPath2, actionRule) => {
135
+ return (0, import_minimatch.default)(actionPath2, actionRule);
136
+ }, "actionMatched");
137
+ for (const action of allowedActions) {
138
+ if (actionMatched(actionPath, action)) {
139
+ return true;
140
+ }
141
+ }
142
+ for (const action of rejectedActions) {
143
+ if (actionMatched(actionPath, action)) {
144
+ return false;
145
+ }
146
+ }
147
+ return null;
148
+ }
149
+ toJSON() {
150
+ const actions = {};
151
+ for (const resourceName of this.resources.keys()) {
152
+ const resourceActions = this.getResourceActionsParams(resourceName);
153
+ for (const actionName of Object.keys(resourceActions)) {
154
+ actions[`${resourceName}:${actionName}`] = resourceActions[actionName];
155
+ }
156
+ }
157
+ return {
158
+ role: this.name,
159
+ strategy: this.strategy,
160
+ actions,
161
+ snippets: Array.from(this.snippets)
162
+ };
163
+ }
164
+ getResourceActionFromPath(path) {
165
+ const [resourceName, actionName] = path.split(":");
166
+ const resource = this.resources.get(resourceName);
167
+ let action = null;
168
+ if (resource) {
169
+ action = resource.getAction(actionName);
170
+ }
171
+ return {
172
+ resourceName,
173
+ actionName,
174
+ resource,
175
+ action
176
+ };
177
+ }
178
+ };
179
+ __name(_ACLRole, "ACLRole");
180
+ let ACLRole = _ACLRole;
181
+ // Annotate the CommonJS export names for ESM import in node:
182
+ 0 && (module.exports = {
183
+ ACLRole
184
+ });
package/lib/acl.d.ts ADDED
@@ -0,0 +1,117 @@
1
+ import EventEmitter from 'node:events';
2
+ import { Toposort, ToposortOptions } from '@tachybase/utils';
3
+ import { ACLAvailableAction, AvailableActionOptions } from './acl-available-action';
4
+ import { ACLAvailableStrategy, AvailableStrategyOptions } from './acl-available-strategy';
5
+ import { ACLRole, ResourceActionsOptions, RoleActionParams } from './acl-role';
6
+ import { AllowManager, ConditionFunc } from './allow-manager';
7
+ import FixedParamsManager, { Merger } from './fixed-params-manager';
8
+ import SnippetManager, { SnippetOptions } from './snippet-manager';
9
+ interface CanResult {
10
+ role: string;
11
+ resource: string;
12
+ action: string;
13
+ params?: any;
14
+ }
15
+ export interface DefineOptions {
16
+ role: string;
17
+ allowConfigure?: boolean;
18
+ strategy?: string | AvailableStrategyOptions;
19
+ actions?: ResourceActionsOptions;
20
+ routes?: any;
21
+ snippets?: string[];
22
+ }
23
+ export interface ListenerContext {
24
+ acl: ACL;
25
+ role: ACLRole;
26
+ path: string;
27
+ actionName: string;
28
+ resourceName: string;
29
+ params: RoleActionParams;
30
+ }
31
+ type Listener = (ctx: ListenerContext) => void;
32
+ interface CanArgs {
33
+ role: string;
34
+ resource: string;
35
+ action: string;
36
+ ctx?: any;
37
+ }
38
+ export declare class ACL extends EventEmitter {
39
+ /**
40
+ * @internal
41
+ */
42
+ availableStrategy: Map<string, ACLAvailableStrategy>;
43
+ /**
44
+ * @internal
45
+ */
46
+ allowManager: AllowManager;
47
+ /**
48
+ * @internal
49
+ */
50
+ snippetManager: SnippetManager;
51
+ /**
52
+ * @internal
53
+ */
54
+ roles: Map<string, ACLRole>;
55
+ /**
56
+ * @internal
57
+ */
58
+ actionAlias: Map<string, string>;
59
+ /**
60
+ * @internal
61
+ */
62
+ configResources: string[];
63
+ protected availableActions: Map<string, ACLAvailableAction>;
64
+ protected fixedParamsManager: FixedParamsManager;
65
+ protected middlewares: Toposort<any>;
66
+ middlewareSourceMap: WeakMap<Function, string>;
67
+ constructor();
68
+ define(options: DefineOptions): ACLRole;
69
+ getRole(name: string): ACLRole;
70
+ removeRole(name: string): boolean;
71
+ /**
72
+ * @internal
73
+ */
74
+ registerConfigResources(names: string[]): void;
75
+ /**
76
+ * @internal
77
+ */
78
+ registerConfigResource(name: string): void;
79
+ /**
80
+ * @internal
81
+ */
82
+ isConfigResource(name: string): boolean;
83
+ setAvailableAction(name: string, options?: AvailableActionOptions): void;
84
+ getAvailableAction(name: string): ACLAvailableAction;
85
+ getAvailableActions(): Map<string, ACLAvailableAction>;
86
+ setAvailableStrategy(name: string, options: AvailableStrategyOptions): void;
87
+ beforeGrantAction(listener?: Listener): void;
88
+ can(options: CanArgs): CanResult | null;
89
+ /**
90
+ * @internal
91
+ */
92
+ resolveActionAlias(action: string): string;
93
+ use(fn: any, options?: ToposortOptions): void;
94
+ allow(resourceName: string, actionNames: string[] | string, condition?: string | ConditionFunc): void;
95
+ /**
96
+ * @deprecated
97
+ */
98
+ skip(resourceName: string, actionNames: string[] | string, condition?: string | ConditionFunc): void;
99
+ /**
100
+ * @internal
101
+ */
102
+ parseJsonTemplate(json: any, ctx: any): Promise<any>;
103
+ middleware(): (ctx: any, next: any) => Promise<any>;
104
+ /**
105
+ * @internal
106
+ */
107
+ getActionParams(ctx: any): Promise<void>;
108
+ addFixedParams(resource: string, action: string, merger: Merger): void;
109
+ registerSnippet(snippet: SnippetOptions): void;
110
+ /**
111
+ * @internal
112
+ */
113
+ filterParams(ctx: any, resourceName: any, params: any): any;
114
+ protected addCoreMiddleware(): void;
115
+ protected isAvailableAction(actionName: string): boolean;
116
+ }
117
+ export {};
package/lib/acl.js ADDED
@@ -0,0 +1,384 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var acl_exports = {};
30
+ __export(acl_exports, {
31
+ ACL: () => ACL
32
+ });
33
+ module.exports = __toCommonJS(acl_exports);
34
+ var import_node_events = __toESM(require("node:events"));
35
+ var import_utils = require("@tachybase/utils");
36
+ var import_koa_compose = __toESM(require("koa-compose"));
37
+ var import_lodash = __toESM(require("lodash"));
38
+ var import_acl_available_action = require("./acl-available-action");
39
+ var import_acl_available_strategy = require("./acl-available-strategy");
40
+ var import_acl_role = require("./acl-role");
41
+ var import_allow_manager = require("./allow-manager");
42
+ var import_fixed_params_manager = __toESM(require("./fixed-params-manager"));
43
+ var import_snippet_manager = __toESM(require("./snippet-manager"));
44
+ const _ACL = class _ACL extends import_node_events.default {
45
+ /**
46
+ * @internal
47
+ */
48
+ availableStrategy = /* @__PURE__ */ new Map();
49
+ /**
50
+ * @internal
51
+ */
52
+ allowManager = new import_allow_manager.AllowManager(this);
53
+ /**
54
+ * @internal
55
+ */
56
+ snippetManager = new import_snippet_manager.default();
57
+ /**
58
+ * @internal
59
+ */
60
+ roles = /* @__PURE__ */ new Map();
61
+ /**
62
+ * @internal
63
+ */
64
+ actionAlias = /* @__PURE__ */ new Map();
65
+ /**
66
+ * @internal
67
+ */
68
+ configResources = [];
69
+ availableActions = /* @__PURE__ */ new Map();
70
+ fixedParamsManager = new import_fixed_params_manager.default();
71
+ middlewares;
72
+ middlewareSourceMap = /* @__PURE__ */ new WeakMap();
73
+ constructor() {
74
+ super();
75
+ this.middlewares = new import_utils.Toposort();
76
+ this.beforeGrantAction((ctx) => {
77
+ if (import_lodash.default.isPlainObject(ctx.params) && ctx.params.own) {
78
+ ctx.params = import_lodash.default.merge(ctx.params, import_acl_available_strategy.predicate.own);
79
+ }
80
+ });
81
+ this.beforeGrantAction((ctx) => {
82
+ const actionName = this.resolveActionAlias(ctx.actionName);
83
+ if (import_lodash.default.isPlainObject(ctx.params)) {
84
+ if ((actionName === "create" || actionName === "update") && ctx.params.fields) {
85
+ ctx.params = {
86
+ ...import_lodash.default.omit(ctx.params, "fields"),
87
+ whitelist: ctx.params.fields
88
+ };
89
+ }
90
+ }
91
+ });
92
+ this.use(this.allowManager.aclMiddleware(), {
93
+ tag: "allow-manager",
94
+ before: "core"
95
+ });
96
+ this.addCoreMiddleware();
97
+ }
98
+ define(options) {
99
+ const roleName = options.role;
100
+ const role = new import_acl_role.ACLRole(this, roleName);
101
+ if (options.strategy) {
102
+ role.strategy = options.strategy;
103
+ }
104
+ const actions = options.actions || {};
105
+ for (const [actionName, actionParams] of Object.entries(actions)) {
106
+ role.grantAction(actionName, actionParams);
107
+ }
108
+ this.roles.set(roleName, role);
109
+ return role;
110
+ }
111
+ getRole(name) {
112
+ return this.roles.get(name);
113
+ }
114
+ removeRole(name) {
115
+ return this.roles.delete(name);
116
+ }
117
+ /**
118
+ * @internal
119
+ */
120
+ registerConfigResources(names) {
121
+ names.forEach((name) => this.registerConfigResource(name));
122
+ }
123
+ /**
124
+ * @internal
125
+ */
126
+ registerConfigResource(name) {
127
+ this.configResources.push(name);
128
+ }
129
+ /**
130
+ * @internal
131
+ */
132
+ isConfigResource(name) {
133
+ return this.configResources.includes(name);
134
+ }
135
+ setAvailableAction(name, options = {}) {
136
+ this.availableActions.set(name, new import_acl_available_action.ACLAvailableAction(name, options));
137
+ if (options.aliases) {
138
+ const aliases = import_lodash.default.isArray(options.aliases) ? options.aliases : [options.aliases];
139
+ for (const alias of aliases) {
140
+ this.actionAlias.set(alias, name);
141
+ }
142
+ }
143
+ }
144
+ getAvailableAction(name) {
145
+ const actionName = this.actionAlias.get(name) || name;
146
+ return this.availableActions.get(actionName);
147
+ }
148
+ getAvailableActions() {
149
+ return this.availableActions;
150
+ }
151
+ setAvailableStrategy(name, options) {
152
+ this.availableStrategy.set(name, new import_acl_available_strategy.ACLAvailableStrategy(this, options));
153
+ }
154
+ beforeGrantAction(listener) {
155
+ this.addListener("beforeGrantAction", listener);
156
+ }
157
+ can(options) {
158
+ const { role, resource, action } = options;
159
+ const aclRole = this.roles.get(role);
160
+ if (!aclRole) {
161
+ return null;
162
+ }
163
+ const snippetAllowed = aclRole.snippetAllowed(`${resource}:${action}`);
164
+ const fixedParams = this.fixedParamsManager.getParams(resource, action);
165
+ const mergeParams = /* @__PURE__ */ __name((result) => {
166
+ const params = result["params"] || {};
167
+ const mergedParams = (0, import_utils.assign)(params, fixedParams);
168
+ if (Object.keys(mergedParams).length) {
169
+ result["params"] = mergedParams;
170
+ } else {
171
+ delete result["params"];
172
+ }
173
+ return result;
174
+ }, "mergeParams");
175
+ const aclResource = aclRole.getResource(resource);
176
+ if (aclResource) {
177
+ const actionParams = aclResource.getAction(action);
178
+ if (actionParams) {
179
+ return mergeParams({
180
+ role,
181
+ resource,
182
+ action,
183
+ params: actionParams
184
+ });
185
+ } else {
186
+ return null;
187
+ }
188
+ }
189
+ const roleStrategy = aclRole.getStrategy();
190
+ if (!roleStrategy && !snippetAllowed) {
191
+ return null;
192
+ }
193
+ let roleStrategyParams = roleStrategy == null ? void 0 : roleStrategy.allow(resource, this.resolveActionAlias(action));
194
+ if (!roleStrategyParams && snippetAllowed) {
195
+ roleStrategyParams = {};
196
+ }
197
+ if (roleStrategyParams) {
198
+ const result = { role, resource, action, params: {} };
199
+ if (import_lodash.default.isPlainObject(roleStrategyParams)) {
200
+ result["params"] = roleStrategyParams;
201
+ }
202
+ return mergeParams(result);
203
+ }
204
+ return null;
205
+ }
206
+ /**
207
+ * @internal
208
+ */
209
+ resolveActionAlias(action) {
210
+ return this.actionAlias.get(action) ? this.actionAlias.get(action) : action;
211
+ }
212
+ use(fn, options) {
213
+ this.middlewareSourceMap.set(fn, (0, import_utils.getCurrentStacks)());
214
+ this.middlewares.add(fn, {
215
+ group: "prep",
216
+ ...options
217
+ });
218
+ }
219
+ allow(resourceName, actionNames, condition) {
220
+ return this.skip(resourceName, actionNames, condition);
221
+ }
222
+ /**
223
+ * @deprecated
224
+ */
225
+ skip(resourceName, actionNames, condition) {
226
+ if (!Array.isArray(actionNames)) {
227
+ actionNames = [actionNames];
228
+ }
229
+ for (const actionName of actionNames) {
230
+ this.allowManager.allow(resourceName, actionName, condition);
231
+ }
232
+ }
233
+ /**
234
+ * @internal
235
+ */
236
+ async parseJsonTemplate(json, ctx) {
237
+ var _a, _b, _c, _d, _e;
238
+ if (json.filter) {
239
+ (_b = (_a = ctx.logger) == null ? void 0 : _a.info) == null ? void 0 : _b.call(_a, "parseJsonTemplate.raw", JSON.parse(JSON.stringify(json.filter)));
240
+ const timezone = (_c = ctx == null ? void 0 : ctx.get) == null ? void 0 : _c.call(ctx, "x-timezone");
241
+ const state = JSON.parse(JSON.stringify(ctx.state));
242
+ const filter = await (0, import_utils.parseFilter)(json.filter, {
243
+ timezone,
244
+ now: (/* @__PURE__ */ new Date()).toISOString(),
245
+ vars: {
246
+ ctx: {
247
+ state
248
+ },
249
+ $user: getUser(ctx),
250
+ $nRole: /* @__PURE__ */ __name(() => state.currentRole, "$nRole")
251
+ }
252
+ });
253
+ json.filter = filter;
254
+ (_e = (_d = ctx.logger) == null ? void 0 : _d.info) == null ? void 0 : _e.call(_d, "parseJsonTemplate.parsed", filter);
255
+ }
256
+ return json;
257
+ }
258
+ middleware() {
259
+ const acl = this;
260
+ return /* @__PURE__ */ __name(async function ACLMiddleware(ctx, next) {
261
+ const roleName = ctx.state.currentRole || "anonymous";
262
+ const { resourceName, actionName } = ctx.action;
263
+ ctx.can = (options) => {
264
+ const canResult = acl.can({ role: roleName, ...options });
265
+ return canResult;
266
+ };
267
+ ctx.permission = {
268
+ can: ctx.can({ resource: resourceName, action: actionName })
269
+ };
270
+ return (0, import_koa_compose.default)(acl.middlewares.nodes)(ctx, next);
271
+ }, "ACLMiddleware");
272
+ }
273
+ /**
274
+ * @internal
275
+ */
276
+ async getActionParams(ctx) {
277
+ const roleName = ctx.state.currentRole || "anonymous";
278
+ const { resourceName, actionName } = ctx.action;
279
+ ctx.can = (options) => {
280
+ const can = this.can({ role: roleName, ...options });
281
+ if (!can) {
282
+ return null;
283
+ }
284
+ return import_lodash.default.cloneDeep(can);
285
+ };
286
+ ctx.permission = {
287
+ can: ctx.can({ resource: resourceName, action: actionName })
288
+ };
289
+ await (0, import_koa_compose.default)(this.middlewares.nodes)(ctx, async () => {
290
+ });
291
+ }
292
+ addFixedParams(resource, action, merger) {
293
+ this.fixedParamsManager.addParams(resource, action, merger);
294
+ }
295
+ registerSnippet(snippet) {
296
+ this.snippetManager.register(snippet);
297
+ }
298
+ /**
299
+ * @internal
300
+ */
301
+ filterParams(ctx, resourceName, params) {
302
+ var _a;
303
+ if ((_a = params == null ? void 0 : params.filter) == null ? void 0 : _a.createdById) {
304
+ const collection = ctx.db.getCollection(resourceName);
305
+ if (!collection || !collection.getField("createdById")) {
306
+ return import_lodash.default.omit(params, "filter.createdById");
307
+ }
308
+ }
309
+ return params;
310
+ }
311
+ addCoreMiddleware() {
312
+ const acl = this;
313
+ this.middlewares.add(
314
+ async (ctx, next) => {
315
+ var _a, _b, _c, _d;
316
+ const resourcerAction = ctx.action;
317
+ const { resourceName, actionName } = ctx.action;
318
+ const permission = ctx.permission;
319
+ ((_a = ctx.log) == null ? void 0 : _a.info) && ctx.log.info("ctx permission", permission);
320
+ if ((!permission.can || typeof permission.can !== "object") && !permission.skip) {
321
+ ctx.throw(403, "No permissions");
322
+ return;
323
+ }
324
+ const params = ((_b = permission.can) == null ? void 0 : _b.params) || acl.fixedParamsManager.getParams(resourceName, actionName);
325
+ ((_c = ctx.log) == null ? void 0 : _c.info) && ctx.log.info("acl params", params);
326
+ if (params && resourcerAction.mergeParams) {
327
+ const filteredParams = acl.filterParams(ctx, resourceName, params);
328
+ const parsedParams = await acl.parseJsonTemplate(filteredParams, ctx);
329
+ ctx.permission.parsedParams = parsedParams;
330
+ ((_d = ctx.log) == null ? void 0 : _d.info) && ctx.log.info("acl parsedParams", parsedParams);
331
+ ctx.permission.rawParams = import_lodash.default.cloneDeep(resourcerAction.params);
332
+ resourcerAction.mergeParams(parsedParams, {
333
+ appends: /* @__PURE__ */ __name((x, y) => {
334
+ if (!x) {
335
+ return [];
336
+ }
337
+ if (!y) {
338
+ return x;
339
+ }
340
+ return x.filter((i) => y.includes(i.split(".").shift()));
341
+ }, "appends")
342
+ });
343
+ ctx.permission.mergedParams = import_lodash.default.cloneDeep(resourcerAction.params);
344
+ }
345
+ await next();
346
+ },
347
+ {
348
+ tag: "core",
349
+ group: "core"
350
+ }
351
+ );
352
+ }
353
+ isAvailableAction(actionName) {
354
+ return this.availableActions.has(this.resolveActionAlias(actionName));
355
+ }
356
+ };
357
+ __name(_ACL, "ACL");
358
+ let ACL = _ACL;
359
+ function getUser(ctx) {
360
+ return async ({ fields }) => {
361
+ var _a, _b;
362
+ const userFields = fields.filter((f) => f && ctx.db.getFieldByPath("users." + f));
363
+ (_a = ctx.logger) == null ? void 0 : _a.info("filter-parse: ", { userFields });
364
+ if (!ctx.state.currentUser) {
365
+ return;
366
+ }
367
+ if (!userFields.length) {
368
+ return;
369
+ }
370
+ const user = await ctx.db.getRepository("users").findOne({
371
+ filterByTk: ctx.state.currentUser.id,
372
+ fields: userFields
373
+ });
374
+ (_b = ctx.logger) == null ? void 0 : _b.info("filter-parse: ", {
375
+ $user: user == null ? void 0 : user.toJSON()
376
+ });
377
+ return user;
378
+ };
379
+ }
380
+ __name(getUser, "getUser");
381
+ // Annotate the CommonJS export names for ESM import in node:
382
+ 0 && (module.exports = {
383
+ ACL
384
+ });
@@ -0,0 +1,13 @@
1
+ import { ACL } from './acl';
2
+ export type ConditionFunc = (ctx: any) => Promise<boolean> | boolean;
3
+ export declare class AllowManager {
4
+ acl: ACL;
5
+ protected skipActions: Map<string, Map<string, string | true | ConditionFunc>>;
6
+ protected registeredCondition: Map<string, ConditionFunc>;
7
+ constructor(acl: ACL);
8
+ allow(resourceName: string, actionName: string, condition?: string | ConditionFunc): void;
9
+ getAllowedConditions(resourceName: string, actionName: string): Array<ConditionFunc | true>;
10
+ registerAllowCondition(name: string, condition: ConditionFunc): void;
11
+ isAllowed(resourceName: string, actionName: string, ctx: any): Promise<boolean>;
12
+ aclMiddleware(): (ctx: any, next: any) => Promise<void>;
13
+ }