velocious 1.0.201 → 1.0.203

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.
Files changed (44) hide show
  1. package/README.md +88 -0
  2. package/build/src/authorization/ability.d.ts +167 -0
  3. package/build/src/authorization/ability.d.ts.map +1 -0
  4. package/build/src/authorization/ability.js +216 -0
  5. package/build/src/authorization/base-resource.d.ts +58 -0
  6. package/build/src/authorization/base-resource.d.ts.map +1 -0
  7. package/build/src/authorization/base-resource.js +66 -0
  8. package/build/src/cli/commands/db/schema/dump.d.ts +2 -10
  9. package/build/src/cli/commands/db/schema/dump.d.ts.map +1 -1
  10. package/build/src/cli/commands/db/schema/dump.js +3 -29
  11. package/build/src/cli/commands/generate/frontend-models.d.ts +7 -0
  12. package/build/src/cli/commands/generate/frontend-models.d.ts.map +1 -0
  13. package/build/src/cli/commands/generate/frontend-models.js +9 -0
  14. package/build/src/configuration-types.d.ts +73 -0
  15. package/build/src/configuration-types.d.ts.map +1 -1
  16. package/build/src/configuration-types.js +23 -1
  17. package/build/src/configuration.d.ts +45 -2
  18. package/build/src/configuration.d.ts.map +1 -1
  19. package/build/src/configuration.js +60 -2
  20. package/build/src/controller.d.ts +2 -0
  21. package/build/src/controller.d.ts.map +1 -1
  22. package/build/src/controller.js +5 -1
  23. package/build/src/database/record/index.d.ts +14 -0
  24. package/build/src/database/record/index.d.ts.map +1 -1
  25. package/build/src/database/record/index.js +28 -1
  26. package/build/src/environment-handlers/base.d.ts +26 -0
  27. package/build/src/environment-handlers/base.d.ts.map +1 -1
  28. package/build/src/environment-handlers/base.js +42 -1
  29. package/build/src/environment-handlers/node/cli/commands/db/schema/dump.d.ts +15 -0
  30. package/build/src/environment-handlers/node/cli/commands/db/schema/dump.d.ts.map +1 -0
  31. package/build/src/environment-handlers/node/cli/commands/db/schema/dump.js +35 -0
  32. package/build/src/environment-handlers/node/cli/commands/generate/frontend-models.d.ts +32 -0
  33. package/build/src/environment-handlers/node/cli/commands/generate/frontend-models.d.ts.map +1 -0
  34. package/build/src/environment-handlers/node/cli/commands/generate/frontend-models.js +117 -0
  35. package/build/src/environment-handlers/node.d.ts +2 -1
  36. package/build/src/environment-handlers/node.d.ts.map +1 -1
  37. package/build/src/environment-handlers/node.js +72 -4
  38. package/build/src/frontend-models/base.d.ts +95 -0
  39. package/build/src/frontend-models/base.d.ts.map +1 -0
  40. package/build/src/frontend-models/base.js +169 -0
  41. package/build/src/routes/resolver.d.ts.map +1 -1
  42. package/build/src/routes/resolver.js +10 -3
  43. package/build/tsconfig.tsbuildinfo +1 -1
  44. package/package.json +1 -1
package/README.md CHANGED
@@ -243,6 +243,43 @@ npx velocious g:model Account
243
243
  npx velocious g:model Task
244
244
  ```
245
245
 
246
+ ## Frontend models from backend resources
247
+
248
+ You can generate lightweight frontend model classes from resource definitions in your configuration.
249
+
250
+ ```js
251
+ export default new Configuration({
252
+ // ...
253
+ backendProjects: [
254
+ {
255
+ path: "/path/to/backend-project",
256
+ resources: {
257
+ User: {
258
+ attributes: ["id", "name", "email"],
259
+ commands: {find: "find", update: "update", destroy: "destroy"},
260
+ path: "/api/frontend-models/users",
261
+ primaryKey: "id"
262
+ }
263
+ }
264
+ }
265
+ ]
266
+ })
267
+ ```
268
+
269
+ Generate classes:
270
+
271
+ ```bash
272
+ npx velocious g:frontend-models
273
+ ```
274
+
275
+ This creates `src/frontend-models/user.js` (and one file per configured resource). Generated classes support:
276
+
277
+ - `await User.find(5)`
278
+ - `await user.update({...})`
279
+ - `await user.destroy()`
280
+ - Attribute methods like `user.name()` and `user.setName(...)`
281
+
282
+
246
283
  ```js
247
284
  import Record from "velocious/build/src/database/record/index.js"
248
285
 
@@ -1159,3 +1196,54 @@ If a handed-off job does not report back within 2 hours, it is marked orphaned a
1159
1196
  ```bash
1160
1197
  npx velocious server --host 0.0.0.0 --port 8082
1161
1198
  ```
1199
+
1200
+ # Authorization (CanCan-style)
1201
+
1202
+ Define resource classes with an `abilities()` method and use `can` / `cannot` rules to constrain model access.
1203
+
1204
+ ```js
1205
+ import Ability from "velocious/build/src/authorization/ability.js"
1206
+ import BaseResource from "velocious/build/src/authorization/base-resource.js"
1207
+ import User from "@/src/models/user"
1208
+
1209
+ class UserResource extends BaseResource {
1210
+ static ModelClass = User
1211
+
1212
+ abilities() {
1213
+ const currentUser = this.currentUser()
1214
+
1215
+ if (currentUser) {
1216
+ this.can("read", User, {id: currentUser.id()})
1217
+ }
1218
+ }
1219
+ }
1220
+
1221
+ export default new Configuration({
1222
+ // ...
1223
+ abilityResolver: ({configuration, params, request, response}) => {
1224
+ return new Ability({
1225
+ context: {
1226
+ configuration,
1227
+ currentUser: undefined, // set from your auth/session layer
1228
+ params,
1229
+ request,
1230
+ response
1231
+ },
1232
+ resources: [UserResource]
1233
+ })
1234
+ }
1235
+ })
1236
+ ```
1237
+
1238
+ Then query through authorization rules:
1239
+
1240
+ ```js
1241
+ const users = await User.accessible().toArray()
1242
+ ```
1243
+
1244
+ You can also pass an ability explicitly:
1245
+
1246
+ ```js
1247
+ const ability = new Ability({context: {currentUser}, resources: [UserResource]})
1248
+ const users = await User.accessible(ability).toArray()
1249
+ ```
@@ -0,0 +1,167 @@
1
+ /** @typedef {Record<string, any> | string | ((query: import("../database/query/model-class-query.js").default<any>, args: {ability: VelociousAuthorizationAbility, action: string, modelClass: typeof import("../database/record/index.js").default}) => void | import("../database/query/model-class-query.js").default<any>)} AbilityConditionsType */
2
+ /**
3
+ * @typedef {object} AbilityRuleType
4
+ * @property {string[]} actions - Actions covered by rule.
5
+ * @property {typeof import("../database/record/index.js").default} modelClass - Model class.
6
+ * @property {AbilityConditionsType | undefined} conditions - Conditions.
7
+ * @property {"allow" | "deny"} effect - Rule effect.
8
+ */
9
+ /** CanCan-style ability object for query-level access control. */
10
+ export default class VelociousAuthorizationAbility {
11
+ /** @type {string[]} */
12
+ static CREATE: string[];
13
+ /** @type {string[]} */
14
+ static READ: string[];
15
+ /** @type {string[]} */
16
+ static UPDATE: string[];
17
+ /** @type {string[]} */
18
+ static DESTROY: string[];
19
+ /** @type {string[]} */
20
+ static CRUD: string[];
21
+ /**
22
+ * @param {object} args - Ability args.
23
+ * @param {Record<string, any>} [args.context] - Ability context.
24
+ * @param {Record<string, any>} [args.locals] - Ability locals.
25
+ * @param {Array<typeof BaseResource>} [args.resources] - Resource classes.
26
+ */
27
+ constructor({ context, locals, resources }?: {
28
+ context?: Record<string, any>;
29
+ locals?: Record<string, any>;
30
+ resources?: Array<typeof BaseResource>;
31
+ });
32
+ context: Record<string, any>;
33
+ locals: Record<string, any>;
34
+ resources: (typeof BaseResource)[];
35
+ /** @type {AbilityRuleType[]} */
36
+ rules: AbilityRuleType[];
37
+ /** @type {Record<string, boolean>} */
38
+ loadedModelClassAbilities: Record<string, boolean>;
39
+ /** @returns {Record<string, any>} - Context. */
40
+ getContext(): Record<string, any>;
41
+ /** @returns {Record<string, any>} - Locals. */
42
+ getLocals(): Record<string, any>;
43
+ /** @returns {any} - Current user from context. */
44
+ currentUser(): any;
45
+ /**
46
+ * @param {string | string[]} actions - Action(s).
47
+ * @param {typeof import("../database/record/index.js").default} modelClass - Model class.
48
+ * @param {AbilityConditionsType} [conditions] - Conditions.
49
+ * @returns {void} - No return value.
50
+ */
51
+ can(actions: string | string[], modelClass: typeof import("../database/record/index.js").default, conditions?: AbilityConditionsType): void;
52
+ /**
53
+ * @param {string | string[]} actions - Action(s).
54
+ * @param {typeof import("../database/record/index.js").default} modelClass - Model class.
55
+ * @param {AbilityConditionsType} [conditions] - Conditions.
56
+ * @returns {void} - No return value.
57
+ */
58
+ cannot(actions: string | string[], modelClass: typeof import("../database/record/index.js").default, conditions?: AbilityConditionsType): void;
59
+ /**
60
+ * @param {object} args - Rule args.
61
+ * @param {string | string[]} args.actions - Action(s).
62
+ * @param {AbilityConditionsType} [args.conditions] - Conditions.
63
+ * @param {"allow" | "deny"} args.effect - Effect.
64
+ * @param {typeof import("../database/record/index.js").default} args.modelClass - Model class.
65
+ * @returns {void} - No return value.
66
+ */
67
+ addRule({ actions, conditions, effect, modelClass }: {
68
+ actions: string | string[];
69
+ conditions?: AbilityConditionsType;
70
+ effect: "allow" | "deny";
71
+ modelClass: typeof import("../database/record/index.js").default;
72
+ }): void;
73
+ /**
74
+ * @param {typeof import("../database/record/index.js").default} modelClass - Model class.
75
+ * @returns {void} - No return value.
76
+ */
77
+ loadAbilitiesForModelClass(modelClass: typeof import("../database/record/index.js").default): void;
78
+ /**
79
+ * @param {object} args - Query args.
80
+ * @param {string} args.action - Requested action.
81
+ * @param {typeof import("../database/record/index.js").default} args.modelClass - Model class.
82
+ * @param {import("../database/query/model-class-query.js").default<any>} args.query - Query.
83
+ * @returns {import("../database/query/model-class-query.js").default<any>} - Authorized query.
84
+ */
85
+ applyToQuery({ action, modelClass, query }: {
86
+ action: string;
87
+ modelClass: typeof import("../database/record/index.js").default;
88
+ query: import("../database/query/model-class-query.js").default<any>;
89
+ }): import("../database/query/model-class-query.js").default<any>;
90
+ /**
91
+ * @param {object} args - Rule lookup args.
92
+ * @param {string} args.action - Action.
93
+ * @param {typeof import("../database/record/index.js").default} args.modelClass - Model class.
94
+ * @returns {AbilityRuleType[]} - Matching rules.
95
+ */
96
+ rulesFor({ action, modelClass }: {
97
+ action: string;
98
+ modelClass: typeof import("../database/record/index.js").default;
99
+ }): AbilityRuleType[];
100
+ /**
101
+ * @param {object} args - SQL args.
102
+ * @param {string} args.action - Action.
103
+ * @param {typeof import("../database/record/index.js").default} args.modelClass - Model class.
104
+ * @param {import("../database/query/model-class-query.js").default<any>} args.query - Base query.
105
+ * @param {AbilityRuleType[]} args.rules - Rules.
106
+ * @returns {string[]} - SQL condition parts.
107
+ */
108
+ conditionSqlParts({ action, modelClass, query, rules }: {
109
+ action: string;
110
+ modelClass: typeof import("../database/record/index.js").default;
111
+ query: import("../database/query/model-class-query.js").default<any>;
112
+ rules: AbilityRuleType[];
113
+ }): string[];
114
+ /**
115
+ * @param {object} args - Deny args.
116
+ * @param {string} args.action - Action.
117
+ * @param {AbilityRuleType[]} args.denyRules - Deny rules.
118
+ * @param {typeof import("../database/record/index.js").default} args.modelClass - Model class.
119
+ * @param {import("../database/query/model-class-query.js").default<any>} args.query - Query.
120
+ * @returns {void} - No return value.
121
+ */
122
+ applyDenyRules({ action, denyRules, modelClass, query }: {
123
+ action: string;
124
+ denyRules: AbilityRuleType[];
125
+ modelClass: typeof import("../database/record/index.js").default;
126
+ query: import("../database/query/model-class-query.js").default<any>;
127
+ }): void;
128
+ /**
129
+ * @param {object} args - Condition args.
130
+ * @param {string} args.action - Action.
131
+ * @param {AbilityConditionsType} args.conditions - Rule conditions.
132
+ * @param {typeof import("../database/record/index.js").default} args.modelClass - Model class.
133
+ * @param {import("../database/query/model-class-query.js").default<any>} args.query - Query.
134
+ * @returns {void | import("../database/query/model-class-query.js").default<any>} - Optional replacement query.
135
+ */
136
+ applyRuleCondition({ action, conditions, modelClass, query }: {
137
+ action: string;
138
+ conditions: AbilityConditionsType;
139
+ modelClass: typeof import("../database/record/index.js").default;
140
+ query: import("../database/query/model-class-query.js").default<any>;
141
+ }): void | import("../database/query/model-class-query.js").default<any>;
142
+ }
143
+ export type AbilityConditionsType = Record<string, any> | string | ((query: import("../database/query/model-class-query.js").default<any>, args: {
144
+ ability: VelociousAuthorizationAbility;
145
+ action: string;
146
+ modelClass: typeof import("../database/record/index.js").default;
147
+ }) => void | import("../database/query/model-class-query.js").default<any>);
148
+ export type AbilityRuleType = {
149
+ /**
150
+ * - Actions covered by rule.
151
+ */
152
+ actions: string[];
153
+ /**
154
+ * - Model class.
155
+ */
156
+ modelClass: typeof import("../database/record/index.js").default;
157
+ /**
158
+ * - Conditions.
159
+ */
160
+ conditions: AbilityConditionsType | undefined;
161
+ /**
162
+ * - Rule effect.
163
+ */
164
+ effect: "allow" | "deny";
165
+ };
166
+ import BaseResource from "./base-resource.js";
167
+ //# sourceMappingURL=ability.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ability.d.ts","sourceRoot":"","sources":["../../../src/authorization/ability.js"],"names":[],"mappings":"AAIA,yVAAyV;AAEzV;;;;;;GAMG;AAEH,kEAAkE;AAClE;IACE,uBAAuB;IACvB,eADW,MAAM,EAAE,CACO;IAE1B,uBAAuB;IACvB,aADW,MAAM,EAAE,CACG;IAEtB,uBAAuB;IACvB,eADW,MAAM,EAAE,CACO;IAE1B,uBAAuB;IACvB,gBADW,MAAM,EAAE,CACS;IAE5B,uBAAuB;IACvB,aADW,MAAM,EAAE,CACkC;IAErD;;;;;OAKG;IACH,6CAJG;QAAmC,OAAO,GAAlC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;QACQ,MAAM,GAAjC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;QACe,SAAS,GAA3C,KAAK,CAAC,OAAO,YAAY,CAAC;KACpC,EAWA;IATC,6BAAsB;IACtB,4BAAoB;IACpB,mCAA0B;IAE1B,gCAAgC;IAChC,OADW,eAAe,EAAE,CACb;IAEf,sCAAsC;IACtC,2BADW,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CACC;IAGrC,gDAAgD;IAChD,cADc,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAGhC;IAED,+CAA+C;IAC/C,aADc,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAGhC;IAED,kDAAkD;IAClD,eADc,GAAG,CAGhB;IAED;;;;;OAKG;IACH,aALW,MAAM,GAAG,MAAM,EAAE,cACjB,cAAc,6BAA6B,EAAE,OAAO,eACpD,qBAAqB,GACnB,IAAI,CAIhB;IAED;;;;;OAKG;IACH,gBALW,MAAM,GAAG,MAAM,EAAE,cACjB,cAAc,6BAA6B,EAAE,OAAO,eACpD,qBAAqB,GACnB,IAAI,CAIhB;IAED;;;;;;;OAOG;IACH,qDANG;QAAgC,OAAO,EAA/B,MAAM,GAAG,MAAM,EAAE;QACY,UAAU,GAAvC,qBAAqB;QACE,MAAM,EAA7B,OAAO,GAAG,MAAM;QAC2C,UAAU,EAArE,cAAc,6BAA6B,EAAE,OAAO;KAC5D,GAAU,IAAI,CAMhB;IAED;;;OAGG;IACH,uCAHW,cAAc,6BAA6B,EAAE,OAAO,GAClD,IAAI,CAuBhB;IAED;;;;;;OAMG;IACH,4CALG;QAAqB,MAAM,EAAnB,MAAM;QACqD,UAAU,EAArE,cAAc,6BAA6B,EAAE,OAAO;QACgB,KAAK,EAAzE,OAAO,wCAAwC,EAAE,OAAO,CAAC,GAAG,CAAC;KACrE,GAAU,OAAO,wCAAwC,EAAE,OAAO,CAAC,GAAG,CAAC,CA4BzE;IAED;;;;;OAKG;IACH,iCAJG;QAAqB,MAAM,EAAnB,MAAM;QACqD,UAAU,EAArE,cAAc,6BAA6B,EAAE,OAAO;KAC5D,GAAU,eAAe,EAAE,CAQ7B;IAED;;;;;;;OAOG;IACH,wDANG;QAAqB,MAAM,EAAnB,MAAM;QACqD,UAAU,EAArE,cAAc,6BAA6B,EAAE,OAAO;QACgB,KAAK,EAAzE,OAAO,wCAAwC,EAAE,OAAO,CAAC,GAAG,CAAC;QACrC,KAAK,EAA7B,eAAe,EAAE;KACzB,GAAU,MAAM,EAAE,CA2BpB;IAED;;;;;;;OAOG;IACH,yDANG;QAAqB,MAAM,EAAnB,MAAM;QACkB,SAAS,EAAjC,eAAe,EAAE;QAC0C,UAAU,EAArE,cAAc,6BAA6B,EAAE,OAAO;QACgB,KAAK,EAAzE,OAAO,wCAAwC,EAAE,OAAO,CAAC,GAAG,CAAC;KACrE,GAAU,IAAI,CAehB;IAED;;;;;;;OAOG;IACH,8DANG;QAAqB,MAAM,EAAnB,MAAM;QACsB,UAAU,EAAtC,qBAAqB;QACsC,UAAU,EAArE,cAAc,6BAA6B,EAAE,OAAO;QACgB,KAAK,EAAzE,OAAO,wCAAwC,EAAE,OAAO,CAAC,GAAG,CAAC;KACrE,GAAU,IAAI,GAAG,OAAO,wCAAwC,EAAE,OAAO,CAAC,GAAG,CAAC,CAiBhF;CACF;oCA5Pa,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE,OAAO,wCAAwC,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE;IAAC,OAAO,EAAE,6BAA6B,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,cAAc,6BAA6B,EAAE,OAAO,CAAA;CAAC,KAAK,IAAI,GAAG,OAAO,wCAAwC,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;;;;;aAIjT,MAAM,EAAE;;;;gBACR,cAAc,6BAA6B,EAAE,OAAO;;;;gBACpD,qBAAqB,GAAG,SAAS;;;;YACjC,OAAO,GAAG,MAAM;;yBATL,oBAAoB"}
@@ -0,0 +1,216 @@
1
+ // @ts-check
2
+ import BaseResource from "./base-resource.js";
3
+ /** @typedef {Record<string, any> | string | ((query: import("../database/query/model-class-query.js").default<any>, args: {ability: VelociousAuthorizationAbility, action: string, modelClass: typeof import("../database/record/index.js").default}) => void | import("../database/query/model-class-query.js").default<any>)} AbilityConditionsType */
4
+ /**
5
+ * @typedef {object} AbilityRuleType
6
+ * @property {string[]} actions - Actions covered by rule.
7
+ * @property {typeof import("../database/record/index.js").default} modelClass - Model class.
8
+ * @property {AbilityConditionsType | undefined} conditions - Conditions.
9
+ * @property {"allow" | "deny"} effect - Rule effect.
10
+ */
11
+ /** CanCan-style ability object for query-level access control. */
12
+ export default class VelociousAuthorizationAbility {
13
+ /** @type {string[]} */
14
+ static CREATE = ["create"];
15
+ /** @type {string[]} */
16
+ static READ = ["read"];
17
+ /** @type {string[]} */
18
+ static UPDATE = ["update"];
19
+ /** @type {string[]} */
20
+ static DESTROY = ["destroy"];
21
+ /** @type {string[]} */
22
+ static CRUD = ["create", "read", "update", "destroy"];
23
+ /**
24
+ * @param {object} args - Ability args.
25
+ * @param {Record<string, any>} [args.context] - Ability context.
26
+ * @param {Record<string, any>} [args.locals] - Ability locals.
27
+ * @param {Array<typeof BaseResource>} [args.resources] - Resource classes.
28
+ */
29
+ constructor({ context = {}, locals = {}, resources = [] } = {}) {
30
+ this.context = context;
31
+ this.locals = locals;
32
+ this.resources = resources;
33
+ /** @type {AbilityRuleType[]} */
34
+ this.rules = [];
35
+ /** @type {Record<string, boolean>} */
36
+ this.loadedModelClassAbilities = {};
37
+ }
38
+ /** @returns {Record<string, any>} - Context. */
39
+ getContext() {
40
+ return this.context;
41
+ }
42
+ /** @returns {Record<string, any>} - Locals. */
43
+ getLocals() {
44
+ return this.locals;
45
+ }
46
+ /** @returns {any} - Current user from context. */
47
+ currentUser() {
48
+ return this.context.currentUser;
49
+ }
50
+ /**
51
+ * @param {string | string[]} actions - Action(s).
52
+ * @param {typeof import("../database/record/index.js").default} modelClass - Model class.
53
+ * @param {AbilityConditionsType} [conditions] - Conditions.
54
+ * @returns {void} - No return value.
55
+ */
56
+ can(actions, modelClass, conditions) {
57
+ this.addRule({ actions, conditions, effect: "allow", modelClass });
58
+ }
59
+ /**
60
+ * @param {string | string[]} actions - Action(s).
61
+ * @param {typeof import("../database/record/index.js").default} modelClass - Model class.
62
+ * @param {AbilityConditionsType} [conditions] - Conditions.
63
+ * @returns {void} - No return value.
64
+ */
65
+ cannot(actions, modelClass, conditions) {
66
+ this.addRule({ actions, conditions, effect: "deny", modelClass });
67
+ }
68
+ /**
69
+ * @param {object} args - Rule args.
70
+ * @param {string | string[]} args.actions - Action(s).
71
+ * @param {AbilityConditionsType} [args.conditions] - Conditions.
72
+ * @param {"allow" | "deny"} args.effect - Effect.
73
+ * @param {typeof import("../database/record/index.js").default} args.modelClass - Model class.
74
+ * @returns {void} - No return value.
75
+ */
76
+ addRule({ actions, conditions, effect, modelClass }) {
77
+ const normalizedActions = Array.isArray(actions) ? actions : [actions];
78
+ this.rules.push({ actions: normalizedActions, conditions, effect, modelClass });
79
+ }
80
+ /**
81
+ * @param {typeof import("../database/record/index.js").default} modelClass - Model class.
82
+ * @returns {void} - No return value.
83
+ */
84
+ loadAbilitiesForModelClass(modelClass) {
85
+ const key = modelClass.name;
86
+ if (this.loadedModelClassAbilities[key])
87
+ return;
88
+ this.loadedModelClassAbilities[key] = true;
89
+ for (const ResourceClass of this.resources) {
90
+ const resourceModelClass = ResourceClass.modelClass();
91
+ if (!resourceModelClass)
92
+ continue;
93
+ if (resourceModelClass !== modelClass)
94
+ continue;
95
+ const resourceInstance = new ResourceClass({
96
+ ability: this,
97
+ context: this.context,
98
+ locals: this.locals
99
+ });
100
+ resourceInstance.abilities();
101
+ }
102
+ }
103
+ /**
104
+ * @param {object} args - Query args.
105
+ * @param {string} args.action - Requested action.
106
+ * @param {typeof import("../database/record/index.js").default} args.modelClass - Model class.
107
+ * @param {import("../database/query/model-class-query.js").default<any>} args.query - Query.
108
+ * @returns {import("../database/query/model-class-query.js").default<any>} - Authorized query.
109
+ */
110
+ applyToQuery({ action, modelClass, query }) {
111
+ this.loadAbilitiesForModelClass(modelClass);
112
+ const applicableRules = this.rulesFor({ action, modelClass });
113
+ const allowRules = applicableRules.filter((rule) => rule.effect === "allow");
114
+ const denyRules = applicableRules.filter((rule) => rule.effect === "deny");
115
+ if (allowRules.length === 0) {
116
+ return query.where("1=0");
117
+ }
118
+ if (allowRules.some((rule) => !rule.conditions)) {
119
+ this.applyDenyRules({ action, denyRules, modelClass, query });
120
+ return query;
121
+ }
122
+ const allowSqlParts = this.conditionSqlParts({ action, modelClass, query, rules: allowRules });
123
+ if (allowSqlParts.length === 0) {
124
+ return query.where("1=0");
125
+ }
126
+ query.where(`(${allowSqlParts.join(" OR ")})`);
127
+ this.applyDenyRules({ action, denyRules, modelClass, query });
128
+ return query;
129
+ }
130
+ /**
131
+ * @param {object} args - Rule lookup args.
132
+ * @param {string} args.action - Action.
133
+ * @param {typeof import("../database/record/index.js").default} args.modelClass - Model class.
134
+ * @returns {AbilityRuleType[]} - Matching rules.
135
+ */
136
+ rulesFor({ action, modelClass }) {
137
+ return this.rules.filter((rule) => {
138
+ if (rule.modelClass !== modelClass)
139
+ return false;
140
+ return rule.actions.includes(action) || rule.actions.includes("manage");
141
+ });
142
+ }
143
+ /**
144
+ * @param {object} args - SQL args.
145
+ * @param {string} args.action - Action.
146
+ * @param {typeof import("../database/record/index.js").default} args.modelClass - Model class.
147
+ * @param {import("../database/query/model-class-query.js").default<any>} args.query - Base query.
148
+ * @param {AbilityRuleType[]} args.rules - Rules.
149
+ * @returns {string[]} - SQL condition parts.
150
+ */
151
+ conditionSqlParts({ action, modelClass, query, rules }) {
152
+ const pk = modelClass.primaryKey();
153
+ const quotedBaseTable = query.driver.quoteTable(modelClass.tableName());
154
+ const quotedPk = query.driver.quoteColumn(pk);
155
+ const sqlParts = [];
156
+ for (const rule of rules) {
157
+ if (!rule.conditions)
158
+ continue;
159
+ const scopedQuery = modelClass._newQuery();
160
+ const resultQuery = this.applyRuleCondition({
161
+ action,
162
+ conditions: rule.conditions,
163
+ modelClass,
164
+ query: scopedQuery
165
+ });
166
+ const finalQuery = resultQuery || scopedQuery;
167
+ const selectedPkSql = `${quotedBaseTable}.${quotedPk}`;
168
+ finalQuery.select(selectedPkSql);
169
+ sqlParts.push(`${quotedBaseTable}.${quotedPk} IN (${finalQuery.toSql()})`);
170
+ }
171
+ return sqlParts;
172
+ }
173
+ /**
174
+ * @param {object} args - Deny args.
175
+ * @param {string} args.action - Action.
176
+ * @param {AbilityRuleType[]} args.denyRules - Deny rules.
177
+ * @param {typeof import("../database/record/index.js").default} args.modelClass - Model class.
178
+ * @param {import("../database/query/model-class-query.js").default<any>} args.query - Query.
179
+ * @returns {void} - No return value.
180
+ */
181
+ applyDenyRules({ action, denyRules, modelClass, query }) {
182
+ if (denyRules.length === 0)
183
+ return;
184
+ if (denyRules.some((rule) => !rule.conditions)) {
185
+ query.where("1=0");
186
+ return;
187
+ }
188
+ const denySqlParts = this.conditionSqlParts({ action, modelClass, query, rules: denyRules });
189
+ if (denySqlParts.length > 0) {
190
+ query.where(`NOT (${denySqlParts.join(" OR ")})`);
191
+ }
192
+ }
193
+ /**
194
+ * @param {object} args - Condition args.
195
+ * @param {string} args.action - Action.
196
+ * @param {AbilityConditionsType} args.conditions - Rule conditions.
197
+ * @param {typeof import("../database/record/index.js").default} args.modelClass - Model class.
198
+ * @param {import("../database/query/model-class-query.js").default<any>} args.query - Query.
199
+ * @returns {void | import("../database/query/model-class-query.js").default<any>} - Optional replacement query.
200
+ */
201
+ applyRuleCondition({ action, conditions, modelClass, query }) {
202
+ if (typeof conditions === "string") {
203
+ query.where(conditions);
204
+ return;
205
+ }
206
+ if (typeof conditions === "function") {
207
+ return conditions(query, {
208
+ ability: this,
209
+ action,
210
+ modelClass
211
+ });
212
+ }
213
+ query.where(conditions);
214
+ }
215
+ }
216
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWJpbGl0eS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9hdXRob3JpemF0aW9uL2FiaWxpdHkuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsWUFBWTtBQUVaLE9BQU8sWUFBWSxNQUFNLG9CQUFvQixDQUFBO0FBRTdDLHlWQUF5VjtBQUV6Vjs7Ozs7O0dBTUc7QUFFSCxrRUFBa0U7QUFDbEUsTUFBTSxDQUFDLE9BQU8sT0FBTyw2QkFBNkI7SUFDaEQsdUJBQXVCO0lBQ3ZCLE1BQU0sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQTtJQUUxQix1QkFBdUI7SUFDdkIsTUFBTSxDQUFDLElBQUksR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFBO0lBRXRCLHVCQUF1QjtJQUN2QixNQUFNLENBQUMsTUFBTSxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUE7SUFFMUIsdUJBQXVCO0lBQ3ZCLE1BQU0sQ0FBQyxPQUFPLEdBQUcsQ0FBQyxTQUFTLENBQUMsQ0FBQTtJQUU1Qix1QkFBdUI7SUFDdkIsTUFBTSxDQUFDLElBQUksR0FBRyxDQUFDLFFBQVEsRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFLFNBQVMsQ0FBQyxDQUFBO0lBRXJEOzs7OztPQUtHO0lBQ0gsWUFBWSxFQUFDLE9BQU8sR0FBRyxFQUFFLEVBQUUsTUFBTSxHQUFHLEVBQUUsRUFBRSxTQUFTLEdBQUcsRUFBRSxFQUFDLEdBQUcsRUFBRTtRQUMxRCxJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQTtRQUN0QixJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQTtRQUNwQixJQUFJLENBQUMsU0FBUyxHQUFHLFNBQVMsQ0FBQTtRQUUxQixnQ0FBZ0M7UUFDaEMsSUFBSSxDQUFDLEtBQUssR0FBRyxFQUFFLENBQUE7UUFFZixzQ0FBc0M7UUFDdEMsSUFBSSxDQUFDLHlCQUF5QixHQUFHLEVBQUUsQ0FBQTtJQUNyQyxDQUFDO0lBRUQsZ0RBQWdEO0lBQ2hELFVBQVU7UUFDUixPQUFPLElBQUksQ0FBQyxPQUFPLENBQUE7SUFDckIsQ0FBQztJQUVELCtDQUErQztJQUMvQyxTQUFTO1FBQ1AsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFBO0lBQ3BCLENBQUM7SUFFRCxrREFBa0Q7SUFDbEQsV0FBVztRQUNULE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxXQUFXLENBQUE7SUFDakMsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsR0FBRyxDQUFDLE9BQU8sRUFBRSxVQUFVLEVBQUUsVUFBVTtRQUNqQyxJQUFJLENBQUMsT0FBTyxDQUFDLEVBQUMsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLFVBQVUsRUFBQyxDQUFDLENBQUE7SUFDbEUsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsTUFBTSxDQUFDLE9BQU8sRUFBRSxVQUFVLEVBQUUsVUFBVTtRQUNwQyxJQUFJLENBQUMsT0FBTyxDQUFDLEVBQUMsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBQyxDQUFDLENBQUE7SUFDakUsQ0FBQztJQUVEOzs7Ozs7O09BT0c7SUFDSCxPQUFPLENBQUMsRUFBQyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUM7UUFDL0MsTUFBTSxpQkFBaUIsR0FBRyxLQUFLLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUE7UUFFdEUsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsRUFBQyxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUMsQ0FBQyxDQUFBO0lBQy9FLENBQUM7SUFFRDs7O09BR0c7SUFDSCwwQkFBMEIsQ0FBQyxVQUFVO1FBQ25DLE1BQU0sR0FBRyxHQUFHLFVBQVUsQ0FBQyxJQUFJLENBQUE7UUFFM0IsSUFBSSxJQUFJLENBQUMseUJBQXlCLENBQUMsR0FBRyxDQUFDO1lBQUUsT0FBTTtRQUUvQyxJQUFJLENBQUMseUJBQXlCLENBQUMsR0FBRyxDQUFDLEdBQUcsSUFBSSxDQUFBO1FBRTFDLEtBQUssTUFBTSxhQUFhLElBQUksSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQzNDLE1BQU0sa0JBQWtCLEdBQUcsYUFBYSxDQUFDLFVBQVUsRUFBRSxDQUFBO1lBRXJELElBQUksQ0FBQyxrQkFBa0I7Z0JBQUUsU0FBUTtZQUNqQyxJQUFJLGtCQUFrQixLQUFLLFVBQVU7Z0JBQUUsU0FBUTtZQUUvQyxNQUFNLGdCQUFnQixHQUFHLElBQUksYUFBYSxDQUFDO2dCQUN6QyxPQUFPLEVBQUUsSUFBSTtnQkFDYixPQUFPLEVBQUUsSUFBSSxDQUFDLE9BQU87Z0JBQ3JCLE1BQU0sRUFBRSxJQUFJLENBQUMsTUFBTTthQUNwQixDQUFDLENBQUE7WUFFRixnQkFBZ0IsQ0FBQyxTQUFTLEVBQUUsQ0FBQTtRQUM5QixDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7Ozs7T0FNRztJQUNILFlBQVksQ0FBQyxFQUFDLE1BQU0sRUFBRSxVQUFVLEVBQUUsS0FBSyxFQUFDO1FBQ3RDLElBQUksQ0FBQywwQkFBMEIsQ0FBQyxVQUFVLENBQUMsQ0FBQTtRQUUzQyxNQUFNLGVBQWUsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLEVBQUMsTUFBTSxFQUFFLFVBQVUsRUFBQyxDQUFDLENBQUE7UUFDM0QsTUFBTSxVQUFVLEdBQUcsZUFBZSxDQUFDLE1BQU0sQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLE1BQU0sS0FBSyxPQUFPLENBQUMsQ0FBQTtRQUM1RSxNQUFNLFNBQVMsR0FBRyxlQUFlLENBQUMsTUFBTSxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsTUFBTSxLQUFLLE1BQU0sQ0FBQyxDQUFBO1FBRTFFLElBQUksVUFBVSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUM1QixPQUFPLEtBQUssQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUE7UUFDM0IsQ0FBQztRQUVELElBQUksVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQztZQUNoRCxJQUFJLENBQUMsY0FBYyxDQUFDLEVBQUMsTUFBTSxFQUFFLFNBQVMsRUFBRSxVQUFVLEVBQUUsS0FBSyxFQUFDLENBQUMsQ0FBQTtZQUMzRCxPQUFPLEtBQUssQ0FBQTtRQUNkLENBQUM7UUFFRCxNQUFNLGFBQWEsR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUMsRUFBQyxNQUFNLEVBQUUsVUFBVSxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsVUFBVSxFQUFDLENBQUMsQ0FBQTtRQUU1RixJQUFJLGFBQWEsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDL0IsT0FBTyxLQUFLLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFBO1FBQzNCLENBQUM7UUFFRCxLQUFLLENBQUMsS0FBSyxDQUFDLElBQUksYUFBYSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUE7UUFDOUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxFQUFDLE1BQU0sRUFBRSxTQUFTLEVBQUUsVUFBVSxFQUFFLEtBQUssRUFBQyxDQUFDLENBQUE7UUFFM0QsT0FBTyxLQUFLLENBQUE7SUFDZCxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSCxRQUFRLENBQUMsRUFBQyxNQUFNLEVBQUUsVUFBVSxFQUFDO1FBQzNCLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRTtZQUNoQyxJQUFJLElBQUksQ0FBQyxVQUFVLEtBQUssVUFBVTtnQkFBRSxPQUFPLEtBQUssQ0FBQTtZQUVoRCxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxJQUFJLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxDQUFBO1FBQ3pFLENBQUMsQ0FBQyxDQUFBO0lBQ0osQ0FBQztJQUVEOzs7Ozs7O09BT0c7SUFDSCxpQkFBaUIsQ0FBQyxFQUFDLE1BQU0sRUFBRSxVQUFVLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBQztRQUNsRCxNQUFNLEVBQUUsR0FBRyxVQUFVLENBQUMsVUFBVSxFQUFFLENBQUE7UUFDbEMsTUFBTSxlQUFlLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLFNBQVMsRUFBRSxDQUFDLENBQUE7UUFDdkUsTUFBTSxRQUFRLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDLENBQUE7UUFDN0MsTUFBTSxRQUFRLEdBQUcsRUFBRSxDQUFBO1FBRW5CLEtBQUssTUFBTSxJQUFJLElBQUksS0FBSyxFQUFFLENBQUM7WUFDekIsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVO2dCQUFFLFNBQVE7WUFFOUIsTUFBTSxXQUFXLEdBQUcsVUFBVSxDQUFDLFNBQVMsRUFBRSxDQUFBO1lBQzFDLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxrQkFBa0IsQ0FBQztnQkFDMUMsTUFBTTtnQkFDTixVQUFVLEVBQUUsSUFBSSxDQUFDLFVBQVU7Z0JBQzNCLFVBQVU7Z0JBQ1YsS0FBSyxFQUFFLFdBQVc7YUFDbkIsQ0FBQyxDQUFBO1lBQ0YsTUFBTSxVQUFVLEdBQUcsV0FBVyxJQUFJLFdBQVcsQ0FBQTtZQUM3QyxNQUFNLGFBQWEsR0FBRyxHQUFHLGVBQWUsSUFBSSxRQUFRLEVBQUUsQ0FBQTtZQUV0RCxVQUFVLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxDQUFBO1lBRWhDLFFBQVEsQ0FBQyxJQUFJLENBQUMsR0FBRyxlQUFlLElBQUksUUFBUSxRQUFRLFVBQVUsQ0FBQyxLQUFLLEVBQUUsR0FBRyxDQUFDLENBQUE7UUFDNUUsQ0FBQztRQUVELE9BQU8sUUFBUSxDQUFBO0lBQ2pCLENBQUM7SUFFRDs7Ozs7OztPQU9HO0lBQ0gsY0FBYyxDQUFDLEVBQUMsTUFBTSxFQUFFLFNBQVMsRUFBRSxVQUFVLEVBQUUsS0FBSyxFQUFDO1FBQ25ELElBQUksU0FBUyxDQUFDLE1BQU0sS0FBSyxDQUFDO1lBQUUsT0FBTTtRQUVsQyxJQUFJLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUM7WUFDL0MsS0FBSyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQTtZQUNsQixPQUFNO1FBQ1IsQ0FBQztRQUVELE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxFQUFDLE1BQU0sRUFBRSxVQUFVLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUMsQ0FBQyxDQUFBO1FBRTFGLElBQUksWUFBWSxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUM1QixLQUFLLENBQUMsS0FBSyxDQUFDLFFBQVEsWUFBWSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUE7UUFDbkQsQ0FBQztJQUNILENBQUM7SUFFRDs7Ozs7OztPQU9HO0lBQ0gsa0JBQWtCLENBQUMsRUFBQyxNQUFNLEVBQUUsVUFBVSxFQUFFLFVBQVUsRUFBRSxLQUFLLEVBQUM7UUFDeEQsSUFBSSxPQUFPLFVBQVUsS0FBSyxRQUFRLEVBQUUsQ0FBQztZQUNuQyxLQUFLLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxDQUFBO1lBQ3ZCLE9BQU07UUFDUixDQUFDO1FBRUQsSUFBSSxPQUFPLFVBQVUsS0FBSyxVQUFVLEVBQUUsQ0FBQztZQUNyQyxPQUFPLFVBQVUsQ0FBQyxLQUFLLEVBQUU7Z0JBQ3ZCLE9BQU8sRUFBRSxJQUFJO2dCQUNiLE1BQU07Z0JBQ04sVUFBVTthQUNYLENBQUMsQ0FBQTtRQUNKLENBQUM7UUFFRCxLQUFLLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxDQUFBO0lBQ3pCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAdHMtY2hlY2tcblxuaW1wb3J0IEJhc2VSZXNvdXJjZSBmcm9tIFwiLi9iYXNlLXJlc291cmNlLmpzXCJcblxuLyoqIEB0eXBlZGVmIHtSZWNvcmQ8c3RyaW5nLCBhbnk+IHwgc3RyaW5nIHwgKChxdWVyeTogaW1wb3J0KFwiLi4vZGF0YWJhc2UvcXVlcnkvbW9kZWwtY2xhc3MtcXVlcnkuanNcIikuZGVmYXVsdDxhbnk+LCBhcmdzOiB7YWJpbGl0eTogVmVsb2Npb3VzQXV0aG9yaXphdGlvbkFiaWxpdHksIGFjdGlvbjogc3RyaW5nLCBtb2RlbENsYXNzOiB0eXBlb2YgaW1wb3J0KFwiLi4vZGF0YWJhc2UvcmVjb3JkL2luZGV4LmpzXCIpLmRlZmF1bHR9KSA9PiB2b2lkIHwgaW1wb3J0KFwiLi4vZGF0YWJhc2UvcXVlcnkvbW9kZWwtY2xhc3MtcXVlcnkuanNcIikuZGVmYXVsdDxhbnk+KX0gQWJpbGl0eUNvbmRpdGlvbnNUeXBlICovXG5cbi8qKlxuICogQHR5cGVkZWYge29iamVjdH0gQWJpbGl0eVJ1bGVUeXBlXG4gKiBAcHJvcGVydHkge3N0cmluZ1tdfSBhY3Rpb25zIC0gQWN0aW9ucyBjb3ZlcmVkIGJ5IHJ1bGUuXG4gKiBAcHJvcGVydHkge3R5cGVvZiBpbXBvcnQoXCIuLi9kYXRhYmFzZS9yZWNvcmQvaW5kZXguanNcIikuZGVmYXVsdH0gbW9kZWxDbGFzcyAtIE1vZGVsIGNsYXNzLlxuICogQHByb3BlcnR5IHtBYmlsaXR5Q29uZGl0aW9uc1R5cGUgfCB1bmRlZmluZWR9IGNvbmRpdGlvbnMgLSBDb25kaXRpb25zLlxuICogQHByb3BlcnR5IHtcImFsbG93XCIgfCBcImRlbnlcIn0gZWZmZWN0IC0gUnVsZSBlZmZlY3QuXG4gKi9cblxuLyoqIENhbkNhbi1zdHlsZSBhYmlsaXR5IG9iamVjdCBmb3IgcXVlcnktbGV2ZWwgYWNjZXNzIGNvbnRyb2wuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBWZWxvY2lvdXNBdXRob3JpemF0aW9uQWJpbGl0eSB7XG4gIC8qKiBAdHlwZSB7c3RyaW5nW119ICovXG4gIHN0YXRpYyBDUkVBVEUgPSBbXCJjcmVhdGVcIl1cblxuICAvKiogQHR5cGUge3N0cmluZ1tdfSAqL1xuICBzdGF0aWMgUkVBRCA9IFtcInJlYWRcIl1cblxuICAvKiogQHR5cGUge3N0cmluZ1tdfSAqL1xuICBzdGF0aWMgVVBEQVRFID0gW1widXBkYXRlXCJdXG5cbiAgLyoqIEB0eXBlIHtzdHJpbmdbXX0gKi9cbiAgc3RhdGljIERFU1RST1kgPSBbXCJkZXN0cm95XCJdXG5cbiAgLyoqIEB0eXBlIHtzdHJpbmdbXX0gKi9cbiAgc3RhdGljIENSVUQgPSBbXCJjcmVhdGVcIiwgXCJyZWFkXCIsIFwidXBkYXRlXCIsIFwiZGVzdHJveVwiXVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge29iamVjdH0gYXJncyAtIEFiaWxpdHkgYXJncy5cbiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBhbnk+fSBbYXJncy5jb250ZXh0XSAtIEFiaWxpdHkgY29udGV4dC5cbiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBhbnk+fSBbYXJncy5sb2NhbHNdIC0gQWJpbGl0eSBsb2NhbHMuXG4gICAqIEBwYXJhbSB7QXJyYXk8dHlwZW9mIEJhc2VSZXNvdXJjZT59IFthcmdzLnJlc291cmNlc10gLSBSZXNvdXJjZSBjbGFzc2VzLlxuICAgKi9cbiAgY29uc3RydWN0b3Ioe2NvbnRleHQgPSB7fSwgbG9jYWxzID0ge30sIHJlc291cmNlcyA9IFtdfSA9IHt9KSB7XG4gICAgdGhpcy5jb250ZXh0ID0gY29udGV4dFxuICAgIHRoaXMubG9jYWxzID0gbG9jYWxzXG4gICAgdGhpcy5yZXNvdXJjZXMgPSByZXNvdXJjZXNcblxuICAgIC8qKiBAdHlwZSB7QWJpbGl0eVJ1bGVUeXBlW119ICovXG4gICAgdGhpcy5ydWxlcyA9IFtdXG5cbiAgICAvKiogQHR5cGUge1JlY29yZDxzdHJpbmcsIGJvb2xlYW4+fSAqL1xuICAgIHRoaXMubG9hZGVkTW9kZWxDbGFzc0FiaWxpdGllcyA9IHt9XG4gIH1cblxuICAvKiogQHJldHVybnMge1JlY29yZDxzdHJpbmcsIGFueT59IC0gQ29udGV4dC4gKi9cbiAgZ2V0Q29udGV4dCgpIHtcbiAgICByZXR1cm4gdGhpcy5jb250ZXh0XG4gIH1cblxuICAvKiogQHJldHVybnMge1JlY29yZDxzdHJpbmcsIGFueT59IC0gTG9jYWxzLiAqL1xuICBnZXRMb2NhbHMoKSB7XG4gICAgcmV0dXJuIHRoaXMubG9jYWxzXG4gIH1cblxuICAvKiogQHJldHVybnMge2FueX0gLSBDdXJyZW50IHVzZXIgZnJvbSBjb250ZXh0LiAqL1xuICBjdXJyZW50VXNlcigpIHtcbiAgICByZXR1cm4gdGhpcy5jb250ZXh0LmN1cnJlbnRVc2VyXG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtzdHJpbmcgfCBzdHJpbmdbXX0gYWN0aW9ucyAtIEFjdGlvbihzKS5cbiAgICogQHBhcmFtIHt0eXBlb2YgaW1wb3J0KFwiLi4vZGF0YWJhc2UvcmVjb3JkL2luZGV4LmpzXCIpLmRlZmF1bHR9IG1vZGVsQ2xhc3MgLSBNb2RlbCBjbGFzcy5cbiAgICogQHBhcmFtIHtBYmlsaXR5Q29uZGl0aW9uc1R5cGV9IFtjb25kaXRpb25zXSAtIENvbmRpdGlvbnMuXG4gICAqIEByZXR1cm5zIHt2b2lkfSAtIE5vIHJldHVybiB2YWx1ZS5cbiAgICovXG4gIGNhbihhY3Rpb25zLCBtb2RlbENsYXNzLCBjb25kaXRpb25zKSB7XG4gICAgdGhpcy5hZGRSdWxlKHthY3Rpb25zLCBjb25kaXRpb25zLCBlZmZlY3Q6IFwiYWxsb3dcIiwgbW9kZWxDbGFzc30pXG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtzdHJpbmcgfCBzdHJpbmdbXX0gYWN0aW9ucyAtIEFjdGlvbihzKS5cbiAgICogQHBhcmFtIHt0eXBlb2YgaW1wb3J0KFwiLi4vZGF0YWJhc2UvcmVjb3JkL2luZGV4LmpzXCIpLmRlZmF1bHR9IG1vZGVsQ2xhc3MgLSBNb2RlbCBjbGFzcy5cbiAgICogQHBhcmFtIHtBYmlsaXR5Q29uZGl0aW9uc1R5cGV9IFtjb25kaXRpb25zXSAtIENvbmRpdGlvbnMuXG4gICAqIEByZXR1cm5zIHt2b2lkfSAtIE5vIHJldHVybiB2YWx1ZS5cbiAgICovXG4gIGNhbm5vdChhY3Rpb25zLCBtb2RlbENsYXNzLCBjb25kaXRpb25zKSB7XG4gICAgdGhpcy5hZGRSdWxlKHthY3Rpb25zLCBjb25kaXRpb25zLCBlZmZlY3Q6IFwiZGVueVwiLCBtb2RlbENsYXNzfSlcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge29iamVjdH0gYXJncyAtIFJ1bGUgYXJncy5cbiAgICogQHBhcmFtIHtzdHJpbmcgfCBzdHJpbmdbXX0gYXJncy5hY3Rpb25zIC0gQWN0aW9uKHMpLlxuICAgKiBAcGFyYW0ge0FiaWxpdHlDb25kaXRpb25zVHlwZX0gW2FyZ3MuY29uZGl0aW9uc10gLSBDb25kaXRpb25zLlxuICAgKiBAcGFyYW0ge1wiYWxsb3dcIiB8IFwiZGVueVwifSBhcmdzLmVmZmVjdCAtIEVmZmVjdC5cbiAgICogQHBhcmFtIHt0eXBlb2YgaW1wb3J0KFwiLi4vZGF0YWJhc2UvcmVjb3JkL2luZGV4LmpzXCIpLmRlZmF1bHR9IGFyZ3MubW9kZWxDbGFzcyAtIE1vZGVsIGNsYXNzLlxuICAgKiBAcmV0dXJucyB7dm9pZH0gLSBObyByZXR1cm4gdmFsdWUuXG4gICAqL1xuICBhZGRSdWxlKHthY3Rpb25zLCBjb25kaXRpb25zLCBlZmZlY3QsIG1vZGVsQ2xhc3N9KSB7XG4gICAgY29uc3Qgbm9ybWFsaXplZEFjdGlvbnMgPSBBcnJheS5pc0FycmF5KGFjdGlvbnMpID8gYWN0aW9ucyA6IFthY3Rpb25zXVxuXG4gICAgdGhpcy5ydWxlcy5wdXNoKHthY3Rpb25zOiBub3JtYWxpemVkQWN0aW9ucywgY29uZGl0aW9ucywgZWZmZWN0LCBtb2RlbENsYXNzfSlcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge3R5cGVvZiBpbXBvcnQoXCIuLi9kYXRhYmFzZS9yZWNvcmQvaW5kZXguanNcIikuZGVmYXVsdH0gbW9kZWxDbGFzcyAtIE1vZGVsIGNsYXNzLlxuICAgKiBAcmV0dXJucyB7dm9pZH0gLSBObyByZXR1cm4gdmFsdWUuXG4gICAqL1xuICBsb2FkQWJpbGl0aWVzRm9yTW9kZWxDbGFzcyhtb2RlbENsYXNzKSB7XG4gICAgY29uc3Qga2V5ID0gbW9kZWxDbGFzcy5uYW1lXG5cbiAgICBpZiAodGhpcy5sb2FkZWRNb2RlbENsYXNzQWJpbGl0aWVzW2tleV0pIHJldHVyblxuXG4gICAgdGhpcy5sb2FkZWRNb2RlbENsYXNzQWJpbGl0aWVzW2tleV0gPSB0cnVlXG5cbiAgICBmb3IgKGNvbnN0IFJlc291cmNlQ2xhc3Mgb2YgdGhpcy5yZXNvdXJjZXMpIHtcbiAgICAgIGNvbnN0IHJlc291cmNlTW9kZWxDbGFzcyA9IFJlc291cmNlQ2xhc3MubW9kZWxDbGFzcygpXG5cbiAgICAgIGlmICghcmVzb3VyY2VNb2RlbENsYXNzKSBjb250aW51ZVxuICAgICAgaWYgKHJlc291cmNlTW9kZWxDbGFzcyAhPT0gbW9kZWxDbGFzcykgY29udGludWVcblxuICAgICAgY29uc3QgcmVzb3VyY2VJbnN0YW5jZSA9IG5ldyBSZXNvdXJjZUNsYXNzKHtcbiAgICAgICAgYWJpbGl0eTogdGhpcyxcbiAgICAgICAgY29udGV4dDogdGhpcy5jb250ZXh0LFxuICAgICAgICBsb2NhbHM6IHRoaXMubG9jYWxzXG4gICAgICB9KVxuXG4gICAgICByZXNvdXJjZUluc3RhbmNlLmFiaWxpdGllcygpXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gUXVlcnkgYXJncy5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGFyZ3MuYWN0aW9uIC0gUmVxdWVzdGVkIGFjdGlvbi5cbiAgICogQHBhcmFtIHt0eXBlb2YgaW1wb3J0KFwiLi4vZGF0YWJhc2UvcmVjb3JkL2luZGV4LmpzXCIpLmRlZmF1bHR9IGFyZ3MubW9kZWxDbGFzcyAtIE1vZGVsIGNsYXNzLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2RhdGFiYXNlL3F1ZXJ5L21vZGVsLWNsYXNzLXF1ZXJ5LmpzXCIpLmRlZmF1bHQ8YW55Pn0gYXJncy5xdWVyeSAtIFF1ZXJ5LlxuICAgKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vZGF0YWJhc2UvcXVlcnkvbW9kZWwtY2xhc3MtcXVlcnkuanNcIikuZGVmYXVsdDxhbnk+fSAtIEF1dGhvcml6ZWQgcXVlcnkuXG4gICAqL1xuICBhcHBseVRvUXVlcnkoe2FjdGlvbiwgbW9kZWxDbGFzcywgcXVlcnl9KSB7XG4gICAgdGhpcy5sb2FkQWJpbGl0aWVzRm9yTW9kZWxDbGFzcyhtb2RlbENsYXNzKVxuXG4gICAgY29uc3QgYXBwbGljYWJsZVJ1bGVzID0gdGhpcy5ydWxlc0Zvcih7YWN0aW9uLCBtb2RlbENsYXNzfSlcbiAgICBjb25zdCBhbGxvd1J1bGVzID0gYXBwbGljYWJsZVJ1bGVzLmZpbHRlcigocnVsZSkgPT4gcnVsZS5lZmZlY3QgPT09IFwiYWxsb3dcIilcbiAgICBjb25zdCBkZW55UnVsZXMgPSBhcHBsaWNhYmxlUnVsZXMuZmlsdGVyKChydWxlKSA9PiBydWxlLmVmZmVjdCA9PT0gXCJkZW55XCIpXG5cbiAgICBpZiAoYWxsb3dSdWxlcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiBxdWVyeS53aGVyZShcIjE9MFwiKVxuICAgIH1cblxuICAgIGlmIChhbGxvd1J1bGVzLnNvbWUoKHJ1bGUpID0+ICFydWxlLmNvbmRpdGlvbnMpKSB7XG4gICAgICB0aGlzLmFwcGx5RGVueVJ1bGVzKHthY3Rpb24sIGRlbnlSdWxlcywgbW9kZWxDbGFzcywgcXVlcnl9KVxuICAgICAgcmV0dXJuIHF1ZXJ5XG4gICAgfVxuXG4gICAgY29uc3QgYWxsb3dTcWxQYXJ0cyA9IHRoaXMuY29uZGl0aW9uU3FsUGFydHMoe2FjdGlvbiwgbW9kZWxDbGFzcywgcXVlcnksIHJ1bGVzOiBhbGxvd1J1bGVzfSlcblxuICAgIGlmIChhbGxvd1NxbFBhcnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIHF1ZXJ5LndoZXJlKFwiMT0wXCIpXG4gICAgfVxuXG4gICAgcXVlcnkud2hlcmUoYCgke2FsbG93U3FsUGFydHMuam9pbihcIiBPUiBcIil9KWApXG4gICAgdGhpcy5hcHBseURlbnlSdWxlcyh7YWN0aW9uLCBkZW55UnVsZXMsIG1vZGVsQ2xhc3MsIHF1ZXJ5fSlcblxuICAgIHJldHVybiBxdWVyeVxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gUnVsZSBsb29rdXAgYXJncy5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGFyZ3MuYWN0aW9uIC0gQWN0aW9uLlxuICAgKiBAcGFyYW0ge3R5cGVvZiBpbXBvcnQoXCIuLi9kYXRhYmFzZS9yZWNvcmQvaW5kZXguanNcIikuZGVmYXVsdH0gYXJncy5tb2RlbENsYXNzIC0gTW9kZWwgY2xhc3MuXG4gICAqIEByZXR1cm5zIHtBYmlsaXR5UnVsZVR5cGVbXX0gLSBNYXRjaGluZyBydWxlcy5cbiAgICovXG4gIHJ1bGVzRm9yKHthY3Rpb24sIG1vZGVsQ2xhc3N9KSB7XG4gICAgcmV0dXJuIHRoaXMucnVsZXMuZmlsdGVyKChydWxlKSA9PiB7XG4gICAgICBpZiAocnVsZS5tb2RlbENsYXNzICE9PSBtb2RlbENsYXNzKSByZXR1cm4gZmFsc2VcblxuICAgICAgcmV0dXJuIHJ1bGUuYWN0aW9ucy5pbmNsdWRlcyhhY3Rpb24pIHx8IHJ1bGUuYWN0aW9ucy5pbmNsdWRlcyhcIm1hbmFnZVwiKVxuICAgIH0pXG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtvYmplY3R9IGFyZ3MgLSBTUUwgYXJncy5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGFyZ3MuYWN0aW9uIC0gQWN0aW9uLlxuICAgKiBAcGFyYW0ge3R5cGVvZiBpbXBvcnQoXCIuLi9kYXRhYmFzZS9yZWNvcmQvaW5kZXguanNcIikuZGVmYXVsdH0gYXJncy5tb2RlbENsYXNzIC0gTW9kZWwgY2xhc3MuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vZGF0YWJhc2UvcXVlcnkvbW9kZWwtY2xhc3MtcXVlcnkuanNcIikuZGVmYXVsdDxhbnk+fSBhcmdzLnF1ZXJ5IC0gQmFzZSBxdWVyeS5cbiAgICogQHBhcmFtIHtBYmlsaXR5UnVsZVR5cGVbXX0gYXJncy5ydWxlcyAtIFJ1bGVzLlxuICAgKiBAcmV0dXJucyB7c3RyaW5nW119IC0gU1FMIGNvbmRpdGlvbiBwYXJ0cy5cbiAgICovXG4gIGNvbmRpdGlvblNxbFBhcnRzKHthY3Rpb24sIG1vZGVsQ2xhc3MsIHF1ZXJ5LCBydWxlc30pIHtcbiAgICBjb25zdCBwayA9IG1vZGVsQ2xhc3MucHJpbWFyeUtleSgpXG4gICAgY29uc3QgcXVvdGVkQmFzZVRhYmxlID0gcXVlcnkuZHJpdmVyLnF1b3RlVGFibGUobW9kZWxDbGFzcy50YWJsZU5hbWUoKSlcbiAgICBjb25zdCBxdW90ZWRQayA9IHF1ZXJ5LmRyaXZlci5xdW90ZUNvbHVtbihwaylcbiAgICBjb25zdCBzcWxQYXJ0cyA9IFtdXG5cbiAgICBmb3IgKGNvbnN0IHJ1bGUgb2YgcnVsZXMpIHtcbiAgICAgIGlmICghcnVsZS5jb25kaXRpb25zKSBjb250aW51ZVxuXG4gICAgICBjb25zdCBzY29wZWRRdWVyeSA9IG1vZGVsQ2xhc3MuX25ld1F1ZXJ5KClcbiAgICAgIGNvbnN0IHJlc3VsdFF1ZXJ5ID0gdGhpcy5hcHBseVJ1bGVDb25kaXRpb24oe1xuICAgICAgICBhY3Rpb24sXG4gICAgICAgIGNvbmRpdGlvbnM6IHJ1bGUuY29uZGl0aW9ucyxcbiAgICAgICAgbW9kZWxDbGFzcyxcbiAgICAgICAgcXVlcnk6IHNjb3BlZFF1ZXJ5XG4gICAgICB9KVxuICAgICAgY29uc3QgZmluYWxRdWVyeSA9IHJlc3VsdFF1ZXJ5IHx8IHNjb3BlZFF1ZXJ5XG4gICAgICBjb25zdCBzZWxlY3RlZFBrU3FsID0gYCR7cXVvdGVkQmFzZVRhYmxlfS4ke3F1b3RlZFBrfWBcblxuICAgICAgZmluYWxRdWVyeS5zZWxlY3Qoc2VsZWN0ZWRQa1NxbClcblxuICAgICAgc3FsUGFydHMucHVzaChgJHtxdW90ZWRCYXNlVGFibGV9LiR7cXVvdGVkUGt9IElOICgke2ZpbmFsUXVlcnkudG9TcWwoKX0pYClcbiAgICB9XG5cbiAgICByZXR1cm4gc3FsUGFydHNcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge29iamVjdH0gYXJncyAtIERlbnkgYXJncy5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGFyZ3MuYWN0aW9uIC0gQWN0aW9uLlxuICAgKiBAcGFyYW0ge0FiaWxpdHlSdWxlVHlwZVtdfSBhcmdzLmRlbnlSdWxlcyAtIERlbnkgcnVsZXMuXG4gICAqIEBwYXJhbSB7dHlwZW9mIGltcG9ydChcIi4uL2RhdGFiYXNlL3JlY29yZC9pbmRleC5qc1wiKS5kZWZhdWx0fSBhcmdzLm1vZGVsQ2xhc3MgLSBNb2RlbCBjbGFzcy5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9kYXRhYmFzZS9xdWVyeS9tb2RlbC1jbGFzcy1xdWVyeS5qc1wiKS5kZWZhdWx0PGFueT59IGFyZ3MucXVlcnkgLSBRdWVyeS5cbiAgICogQHJldHVybnMge3ZvaWR9IC0gTm8gcmV0dXJuIHZhbHVlLlxuICAgKi9cbiAgYXBwbHlEZW55UnVsZXMoe2FjdGlvbiwgZGVueVJ1bGVzLCBtb2RlbENsYXNzLCBxdWVyeX0pIHtcbiAgICBpZiAoZGVueVJ1bGVzLmxlbmd0aCA9PT0gMCkgcmV0dXJuXG5cbiAgICBpZiAoZGVueVJ1bGVzLnNvbWUoKHJ1bGUpID0+ICFydWxlLmNvbmRpdGlvbnMpKSB7XG4gICAgICBxdWVyeS53aGVyZShcIjE9MFwiKVxuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgY29uc3QgZGVueVNxbFBhcnRzID0gdGhpcy5jb25kaXRpb25TcWxQYXJ0cyh7YWN0aW9uLCBtb2RlbENsYXNzLCBxdWVyeSwgcnVsZXM6IGRlbnlSdWxlc30pXG5cbiAgICBpZiAoZGVueVNxbFBhcnRzLmxlbmd0aCA+IDApIHtcbiAgICAgIHF1ZXJ5LndoZXJlKGBOT1QgKCR7ZGVueVNxbFBhcnRzLmpvaW4oXCIgT1IgXCIpfSlgKVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge29iamVjdH0gYXJncyAtIENvbmRpdGlvbiBhcmdzLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gYXJncy5hY3Rpb24gLSBBY3Rpb24uXG4gICAqIEBwYXJhbSB7QWJpbGl0eUNvbmRpdGlvbnNUeXBlfSBhcmdzLmNvbmRpdGlvbnMgLSBSdWxlIGNvbmRpdGlvbnMuXG4gICAqIEBwYXJhbSB7dHlwZW9mIGltcG9ydChcIi4uL2RhdGFiYXNlL3JlY29yZC9pbmRleC5qc1wiKS5kZWZhdWx0fSBhcmdzLm1vZGVsQ2xhc3MgLSBNb2RlbCBjbGFzcy5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9kYXRhYmFzZS9xdWVyeS9tb2RlbC1jbGFzcy1xdWVyeS5qc1wiKS5kZWZhdWx0PGFueT59IGFyZ3MucXVlcnkgLSBRdWVyeS5cbiAgICogQHJldHVybnMge3ZvaWQgfCBpbXBvcnQoXCIuLi9kYXRhYmFzZS9xdWVyeS9tb2RlbC1jbGFzcy1xdWVyeS5qc1wiKS5kZWZhdWx0PGFueT59IC0gT3B0aW9uYWwgcmVwbGFjZW1lbnQgcXVlcnkuXG4gICAqL1xuICBhcHBseVJ1bGVDb25kaXRpb24oe2FjdGlvbiwgY29uZGl0aW9ucywgbW9kZWxDbGFzcywgcXVlcnl9KSB7XG4gICAgaWYgKHR5cGVvZiBjb25kaXRpb25zID09PSBcInN0cmluZ1wiKSB7XG4gICAgICBxdWVyeS53aGVyZShjb25kaXRpb25zKVxuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBjb25kaXRpb25zID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgIHJldHVybiBjb25kaXRpb25zKHF1ZXJ5LCB7XG4gICAgICAgIGFiaWxpdHk6IHRoaXMsXG4gICAgICAgIGFjdGlvbixcbiAgICAgICAgbW9kZWxDbGFzc1xuICAgICAgfSlcbiAgICB9XG5cbiAgICBxdWVyeS53aGVyZShjb25kaXRpb25zKVxuICB9XG59XG4iXX0=
@@ -0,0 +1,58 @@
1
+ /** Base class for authorization resources defining abilities for a model. */
2
+ export default class AuthorizationBaseResource {
3
+ /** @type {typeof import("../database/record/index.js").default | undefined} */
4
+ static ModelClass: typeof import("../database/record/index.js").default | undefined;
5
+ /**
6
+ * @returns {typeof import("../database/record/index.js").default | undefined} - Model class handled by this resource.
7
+ */
8
+ static modelClass(): typeof import("../database/record/index.js").default | undefined;
9
+ /**
10
+ * @param {object} args - Resource args.
11
+ * @param {import("./ability.js").default} args.ability - Ability instance.
12
+ * @param {Record<string, any>} [args.context] - Ability context.
13
+ * @param {Record<string, any>} [args.locals] - Ability locals.
14
+ */
15
+ constructor({ ability, context, locals }: {
16
+ ability: import("./ability.js").default;
17
+ context?: Record<string, any>;
18
+ locals?: Record<string, any>;
19
+ });
20
+ ability: import("./ability.js").default;
21
+ context: Record<string, any>;
22
+ locals: Record<string, any>;
23
+ /**
24
+ * @param {string | string[]} actions - Ability action(s).
25
+ * @param {typeof import("../database/record/index.js").default} modelClass - Model class.
26
+ * @param {Record<string, any> | string | ((query: import("../database/query/model-class-query.js").default<any>, args: {ability: import("./ability.js").default, action: string, modelClass: typeof import("../database/record/index.js").default}) => void | import("../database/query/model-class-query.js").default<any>)} [conditions] - Conditions.
27
+ * @returns {void} - No return value.
28
+ */
29
+ can(actions: string | string[], modelClass: typeof import("../database/record/index.js").default, conditions?: Record<string, any> | string | ((query: import("../database/query/model-class-query.js").default<any>, args: {
30
+ ability: import("./ability.js").default;
31
+ action: string;
32
+ modelClass: typeof import("../database/record/index.js").default;
33
+ }) => void | import("../database/query/model-class-query.js").default<any>)): void;
34
+ /**
35
+ * @param {string | string[]} actions - Ability action(s).
36
+ * @param {typeof import("../database/record/index.js").default} modelClass - Model class.
37
+ * @param {Record<string, any> | string | ((query: import("../database/query/model-class-query.js").default<any>, args: {ability: import("./ability.js").default, action: string, modelClass: typeof import("../database/record/index.js").default}) => void | import("../database/query/model-class-query.js").default<any>)} [conditions] - Conditions.
38
+ * @returns {void} - No return value.
39
+ */
40
+ cannot(actions: string | string[], modelClass: typeof import("../database/record/index.js").default, conditions?: Record<string, any> | string | ((query: import("../database/query/model-class-query.js").default<any>, args: {
41
+ ability: import("./ability.js").default;
42
+ action: string;
43
+ modelClass: typeof import("../database/record/index.js").default;
44
+ }) => void | import("../database/query/model-class-query.js").default<any>)): void;
45
+ /** @returns {Record<string, any>} - Ability context. */
46
+ getContext(): Record<string, any>;
47
+ /** @returns {Record<string, any>} - Ability locals. */
48
+ getLocals(): Record<string, any>;
49
+ /** @returns {any} - Current user from context. */
50
+ currentUser(): any;
51
+ /** @returns {import("../http-server/client/request.js").default | import("../http-server/client/websocket-request.js").default | undefined} - Request from context. */
52
+ request(): import("../http-server/client/request.js").default | import("../http-server/client/websocket-request.js").default | undefined;
53
+ /** @returns {Record<string, any> | undefined} - Params from context. */
54
+ params(): Record<string, any> | undefined;
55
+ /** @returns {void} - Implement in subclasses to define abilities. */
56
+ abilities(): void;
57
+ }
58
+ //# sourceMappingURL=base-resource.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-resource.d.ts","sourceRoot":"","sources":["../../../src/authorization/base-resource.js"],"names":[],"mappings":"AAEA,6EAA6E;AAC7E;IACE,+EAA+E;IAC/E,mBADW,cAAc,6BAA6B,EAAE,OAAO,GAAG,SAAS,CAC9C;IAc7B;;OAEG;IACH,qBAFa,cAAc,6BAA6B,EAAE,OAAO,GAAG,SAAS,CAI5E;IAjBD;;;;;OAKG;IACH,0CAJG;QAA6C,OAAO,EAA5C,OAAO,cAAc,EAAE,OAAO;QACH,OAAO,GAAlC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;QACQ,MAAM,GAAjC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;KAC7B,EAKA;IAHC,wCAAsB;IACtB,6BAAsB;IACtB,4BAAoB;IAUtB;;;;;OAKG;IACH,aALW,MAAM,GAAG,MAAM,EAAE,cACjB,cAAc,6BAA6B,EAAE,OAAO,eACpD,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE,OAAO,wCAAwC,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE;QAAC,OAAO,EAAE,OAAO,cAAc,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,cAAc,6BAA6B,EAAE,OAAO,CAAA;KAAC,KAAK,IAAI,GAAG,OAAO,wCAAwC,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,GAChT,IAAI,CAIhB;IAED;;;;;OAKG;IACH,gBALW,MAAM,GAAG,MAAM,EAAE,cACjB,cAAc,6BAA6B,EAAE,OAAO,eACpD,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE,OAAO,wCAAwC,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE;QAAC,OAAO,EAAE,OAAO,cAAc,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,cAAc,6BAA6B,EAAE,OAAO,CAAA;KAAC,KAAK,IAAI,GAAG,OAAO,wCAAwC,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,GAChT,IAAI,CAIhB;IAED,wDAAwD;IACxD,cADc,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAGhC;IAED,uDAAuD;IACvD,aADc,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAGhC;IAED,kDAAkD;IAClD,eADc,GAAG,CAGhB;IAED,uKAAuK;IACvK,WADc,OAAO,kCAAkC,EAAE,OAAO,GAAG,OAAO,4CAA4C,EAAE,OAAO,GAAG,SAAS,CAG1I;IAED,wEAAwE;IACxE,UADc,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,CAG5C;IAED,qEAAqE;IACrE,aADc,IAAI,CAGjB;CACF"}