@authup/access 1.0.0-beta.33 → 1.0.0-beta.35

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 (51) hide show
  1. package/dist/index.d.mts +547 -0
  2. package/dist/index.d.mts.map +1 -0
  3. package/dist/index.mjs +980 -1149
  4. package/dist/index.mjs.map +1 -1
  5. package/dist/permission/evaluator/module.d.ts +3 -3
  6. package/dist/permission/evaluator/module.d.ts.map +1 -1
  7. package/dist/permission/evaluator/types.d.ts +1 -1
  8. package/dist/permission/evaluator/types.d.ts.map +1 -1
  9. package/dist/permission/helpers/equal.d.ts +2 -1
  10. package/dist/permission/helpers/equal.d.ts.map +1 -1
  11. package/dist/permission/helpers/index.d.ts +1 -1
  12. package/dist/permission/helpers/index.d.ts.map +1 -1
  13. package/dist/permission/helpers/key.d.ts +2 -1
  14. package/dist/permission/helpers/key.d.ts.map +1 -1
  15. package/dist/permission/helpers/merge.d.ts +2 -1
  16. package/dist/permission/helpers/merge.d.ts.map +1 -1
  17. package/dist/permission/provider/memory.d.ts +5 -5
  18. package/dist/permission/provider/memory.d.ts.map +1 -1
  19. package/dist/permission/provider/types.d.ts +2 -2
  20. package/dist/permission/provider/types.d.ts.map +1 -1
  21. package/dist/permission/types.d.ts +12 -1
  22. package/dist/permission/types.d.ts.map +1 -1
  23. package/dist/policy/built-in/attribute-names/types.d.ts +2 -2
  24. package/dist/policy/built-in/attribute-names/validator.d.ts.map +1 -1
  25. package/dist/policy/built-in/attributes/types.d.ts +2 -2
  26. package/dist/policy/built-in/attributes/validator.d.ts.map +1 -1
  27. package/dist/policy/built-in/composite/evaluator.d.ts.map +1 -1
  28. package/dist/policy/built-in/composite/types.d.ts +3 -3
  29. package/dist/policy/built-in/composite/types.d.ts.map +1 -1
  30. package/dist/policy/built-in/composite/validator.d.ts.map +1 -1
  31. package/dist/policy/built-in/date/types.d.ts +2 -2
  32. package/dist/policy/built-in/date/validator.d.ts.map +1 -1
  33. package/dist/policy/built-in/identity/data/validator.d.ts.map +1 -1
  34. package/dist/policy/built-in/identity/types.d.ts +2 -2
  35. package/dist/policy/built-in/identity/validator.d.ts +1 -1
  36. package/dist/policy/built-in/identity/validator.d.ts.map +1 -1
  37. package/dist/policy/built-in/permission-binding/types.d.ts +2 -2
  38. package/dist/policy/built-in/permission-binding/validator.d.ts +1 -1
  39. package/dist/policy/built-in/permission-binding/validator.d.ts.map +1 -1
  40. package/dist/policy/built-in/realm-match/types.d.ts +2 -2
  41. package/dist/policy/built-in/realm-match/validator.d.ts.map +1 -1
  42. package/dist/policy/built-in/time/evaluator.d.ts.map +1 -1
  43. package/dist/policy/built-in/time/types.d.ts +2 -2
  44. package/dist/policy/built-in/time/validator.d.ts.map +1 -1
  45. package/dist/policy/engine/module.d.ts +3 -3
  46. package/dist/policy/engine/module.d.ts.map +1 -1
  47. package/dist/policy/engine/types.d.ts +3 -3
  48. package/dist/policy/engine/types.d.ts.map +1 -1
  49. package/dist/policy/types.d.ts +6 -8
  50. package/dist/policy/types.d.ts.map +1 -1
  51. package/package.json +9 -12
package/dist/index.mjs CHANGED
@@ -1,1176 +1,1007 @@
1
- import { AuthupError, ErrorCode } from '@authup/errors';
2
- import { buildPermissionBindingKey, mergePermissionBindings } from '@authup/core-kit';
3
- export { buildPermissionBindingKey, isPermissionBindingEqual, mergePermissionBindings } from '@authup/core-kit';
4
- import { defineIssueItem, defineIssueGroup, Container } from 'validup';
5
- import { isObject, flattenObject, DecisionStrategy, hasOwnProperty } from '@authup/kit';
6
- export { DecisionStrategy } from '@authup/kit';
7
- import { createValidator } from '@validup/adapter-zod';
8
- import { z } from 'zod';
9
- import { guard } from '@ucast/mongo2js';
10
-
11
- class PermissionError extends AuthupError {
12
- constructor(options = {}){
13
- super({
14
- ...options,
15
- message: options.message || 'A permission error occurred.',
16
- statusCode: options.statusCode || 403
17
- });
18
- }
19
- addIssue(data) {
20
- this.issues.push(data);
21
- }
22
- addIssues(data) {
23
- this.issues.push(...data);
24
- }
25
- static notFound(name) {
26
- return new PermissionError({
27
- message: `The permission ${name} was not found.`,
28
- code: ErrorCode.PERMISSION_NOT_FOUND
29
- });
30
- }
31
- static denied(name) {
32
- return new PermissionError({
33
- message: `The permission ${name} has not been granted.`,
34
- code: ErrorCode.PERMISSION_DENIED
35
- });
36
- }
37
- static deniedAll(names) {
38
- return new PermissionError({
39
- message: `None of the permissions ${names.join(', ')} has been granted.`,
40
- code: ErrorCode.PERMISSION_DENIED
41
- });
42
- }
43
- static evaluationFailed(name) {
44
- if (Array.isArray(name)) {
45
- return new PermissionError({
46
- message: `The evaluation of permissions ${name.join(', ')} failed`,
47
- code: ErrorCode.PERMISSION_EVALUATION_FAILED
48
- });
49
- }
50
- return new PermissionError({
51
- message: `The evaluation of permission ${name} failed`,
52
- code: ErrorCode.PERMISSION_EVALUATION_FAILED
53
- });
54
- }
55
- }
56
-
57
- class PermissionMemoryProvider {
58
- items = {};
59
- constructor(items = []){
60
- this.setMany(items);
61
- }
62
- async findOne(options) {
63
- const entry = this.items[buildPermissionBindingKey({
64
- name: options.name,
65
- client_id: options.clientId,
66
- realm_id: options.realmId
67
- })];
68
- if (entry) {
69
- return entry;
70
- }
71
- return null;
72
- }
73
- setMany(input) {
74
- this.items = mergePermissionBindings(input).reduce((prev, current)=>{
75
- prev[buildPermissionBindingKey(current.permission)] = current;
76
- return prev;
77
- }, {});
78
- }
79
- }
80
-
81
- /*
82
- * Copyright (c) 2024-2024.
83
- * Author Peter Placzek (tada5hi)
84
- * For the full copyright and license information,
85
- * view the LICENSE file that was distributed with this source code.
86
- */ function maybeInvertPolicyOutcome(outcome, invert) {
87
- if (typeof invert === 'undefined') {
88
- return outcome;
89
- }
90
- if (typeof invert === 'function') {
91
- return invert(outcome);
92
- }
93
- if (!invert) {
94
- return outcome;
95
- }
96
- return !outcome;
97
- }
98
-
99
- class PolicyError extends AuthupError {
100
- constructor(message, code){
101
- super({
102
- message,
103
- code
104
- });
105
- }
106
- addIssue(data) {
107
- this.issues.push(data);
108
- }
109
- addIssues(data) {
110
- this.issues.push(...data);
111
- }
112
- static evaluatorNotFound(type) {
113
- return new PolicyError(`No evaluator is registered to handle the policy: ${type}`, ErrorCode.POLICY_EVALUATOR_NOT_FOUND);
114
- }
115
- static evaluatorNotProcessable() {
116
- return new PolicyError('The evaluator can not process the policy.', ErrorCode.POLICY_EVALUATOR_NOT_PROCESSABLE);
117
- }
118
- static evaluatorContextInvalid() {
119
- return new PolicyError('The evaluator context is not valid.', ErrorCode.POLICY_EVALUATOR_CONTEXT_INVALID);
120
- }
121
- }
122
-
1
+ import { AuthupError, ErrorCode } from "@authup/errors";
2
+ import { DecisionStrategy, DecisionStrategy as DecisionStrategy$1, flattenObject, hasOwnProperty, isObject } from "@authup/kit";
3
+ import { Container, defineIssueGroup, defineIssueItem } from "validup";
4
+ import { createValidator } from "@validup/adapter-zod";
5
+ import { z } from "zod";
6
+ import { guard } from "@ucast/mongo2js";
7
+ //#region src/permission/error/module.ts
8
+ var PermissionError = class PermissionError extends AuthupError {
9
+ constructor(options = {}) {
10
+ super({
11
+ ...options,
12
+ message: options.message || "A permission error occurred.",
13
+ statusCode: options.statusCode || 403
14
+ });
15
+ }
16
+ addIssue(data) {
17
+ this.issues.push(data);
18
+ }
19
+ addIssues(data) {
20
+ this.issues.push(...data);
21
+ }
22
+ static notFound(name) {
23
+ return new PermissionError({
24
+ message: `The permission ${name} was not found.`,
25
+ code: ErrorCode.PERMISSION_NOT_FOUND
26
+ });
27
+ }
28
+ static denied(name) {
29
+ return new PermissionError({
30
+ message: `The permission ${name} has not been granted.`,
31
+ code: ErrorCode.PERMISSION_DENIED
32
+ });
33
+ }
34
+ static deniedAll(names) {
35
+ return new PermissionError({
36
+ message: `None of the permissions ${names.join(", ")} has been granted.`,
37
+ code: ErrorCode.PERMISSION_DENIED
38
+ });
39
+ }
40
+ static evaluationFailed(name) {
41
+ if (Array.isArray(name)) return new PermissionError({
42
+ message: `The evaluation of permissions ${name.join(", ")} failed`,
43
+ code: ErrorCode.PERMISSION_EVALUATION_FAILED
44
+ });
45
+ return new PermissionError({
46
+ message: `The evaluation of permission ${name} failed`,
47
+ code: ErrorCode.PERMISSION_EVALUATION_FAILED
48
+ });
49
+ }
50
+ };
51
+ //#endregion
52
+ //#region src/permission/helpers/equal.ts
53
+ function isPermissionPolicyBindingEqual(a, b) {
54
+ if (a.permission.name !== b.permission.name) return false;
55
+ if ((a.permission.realm_id ?? null) !== (b.permission.realm_id ?? null)) return false;
56
+ if ((a.permission.client_id ?? null) !== (b.permission.client_id ?? null)) return false;
57
+ return true;
58
+ }
59
+ //#endregion
60
+ //#region src/permission/helpers/key.ts
61
+ function formatKeySegment(value) {
62
+ return value || "*";
63
+ }
64
+ function buildPermissionKey(input) {
65
+ return `${formatKeySegment(input.realm_id)}/${formatKeySegment(input.client_id)}/${input.name}`;
66
+ }
67
+ //#endregion
68
+ //#region src/permission/helpers/merge.ts
69
+ function mergePermissionPolicyBindings(input) {
70
+ const grouped = input.reduce((previous, current) => {
71
+ const key = buildPermissionKey(current.permission);
72
+ if (!previous[key]) previous[key] = [];
73
+ previous[key].push(current);
74
+ return previous;
75
+ }, {});
76
+ const output = [];
77
+ const keys = Object.keys(grouped);
78
+ for (const key of keys) {
79
+ const group = grouped[key];
80
+ const first = group[0];
81
+ if (group.length === 1) {
82
+ output.push(first);
83
+ continue;
84
+ }
85
+ const children = [];
86
+ for (const element of group) {
87
+ if (!element.policies || element.policies.length === 0) continue;
88
+ const policy = {
89
+ type: "composite",
90
+ decision_strategy: element.permission.decision_strategy || DecisionStrategy$1.UNANIMOUS,
91
+ children: element.policies
92
+ };
93
+ children.push(policy);
94
+ }
95
+ let mergedPolicies;
96
+ if (children.length > 0 && children.length === group.length) mergedPolicies = [{
97
+ type: "composite",
98
+ decision_strategy: DecisionStrategy$1.AFFIRMATIVE,
99
+ children
100
+ }];
101
+ output.push({
102
+ permission: {
103
+ ...first.permission,
104
+ decision_strategy: DecisionStrategy$1.AFFIRMATIVE
105
+ },
106
+ policies: mergedPolicies
107
+ });
108
+ }
109
+ return output;
110
+ }
111
+ //#endregion
112
+ //#region src/permission/provider/memory.ts
113
+ var PermissionMemoryProvider = class {
114
+ items = {};
115
+ constructor(items = []) {
116
+ this.setMany(items);
117
+ }
118
+ async findOne(options) {
119
+ const key = buildPermissionKey({
120
+ name: options.name,
121
+ client_id: options.clientId,
122
+ realm_id: options.realmId
123
+ });
124
+ const entry = this.items[key];
125
+ if (entry) return entry;
126
+ return null;
127
+ }
128
+ setMany(input) {
129
+ this.items = mergePermissionPolicyBindings(input).reduce((prev, current) => {
130
+ const key = buildPermissionKey(current.permission);
131
+ prev[key] = current;
132
+ return prev;
133
+ }, {});
134
+ }
135
+ };
136
+ //#endregion
137
+ //#region src/policy/helpers/invert.ts
138
+ function maybeInvertPolicyOutcome(outcome, invert) {
139
+ if (typeof invert === "undefined") return outcome;
140
+ if (typeof invert === "function") return invert(outcome);
141
+ if (!invert) return outcome;
142
+ return !outcome;
143
+ }
144
+ //#endregion
145
+ //#region src/policy/error/module.ts
146
+ var PolicyError = class PolicyError extends AuthupError {
147
+ constructor(message, code) {
148
+ super({
149
+ message,
150
+ code
151
+ });
152
+ }
153
+ addIssue(data) {
154
+ this.issues.push(data);
155
+ }
156
+ addIssues(data) {
157
+ this.issues.push(...data);
158
+ }
159
+ static evaluatorNotFound(type) {
160
+ return new PolicyError(`No evaluator is registered to handle the policy: ${type}`, ErrorCode.POLICY_EVALUATOR_NOT_FOUND);
161
+ }
162
+ static evaluatorNotProcessable() {
163
+ return new PolicyError("The evaluator can not process the policy.", ErrorCode.POLICY_EVALUATOR_NOT_PROCESSABLE);
164
+ }
165
+ static evaluatorContextInvalid() {
166
+ return new PolicyError("The evaluator context is not valid.", ErrorCode.POLICY_EVALUATOR_CONTEXT_INVALID);
167
+ }
168
+ };
169
+ //#endregion
170
+ //#region src/policy/engine/module.ts
123
171
  /**
124
- * The policy engine is a component that interprets defined policies and makes decisions
125
- * on whether to allow or deny a particular access.
126
- */ class PolicyEngine {
127
- evaluators;
128
- constructor(evaluators = {}){
129
- this.evaluators = evaluators;
130
- }
131
- registerEvaluator(type, evaluator) {
132
- this.evaluators[type] = evaluator;
133
- }
134
- registerEvaluators(evaluators) {
135
- const keys = Object.keys(evaluators);
136
- for (const key of keys){
137
- this.registerEvaluator(key, evaluators[key]);
138
- }
139
- }
140
- /**
141
- * @param policy
142
- * @param ctx
143
- */ async evaluate(policy, ctx) {
144
- if (ctx.exclude && ctx.exclude.length > 0 && ctx.exclude.includes(policy.type)) {
145
- return {
146
- success: maybeInvertPolicyOutcome(true, policy.invert)
147
- };
148
- }
149
- if (ctx.include && ctx.include.length > 0 && !ctx.include.includes(policy.type)) {
150
- return {
151
- success: maybeInvertPolicyOutcome(true, policy.invert)
152
- };
153
- }
154
- const issues = [];
155
- const evaluator = this.evaluators[policy.type];
156
- if (!evaluator) {
157
- // todo: add issue here instead + return false ?
158
- issues.push(defineIssueItem({
159
- path: [
160
- policy.type
161
- ],
162
- message: `The policy ${policy.type} can not be handled by any evaluator.`,
163
- code: ErrorCode.POLICY_EVALUATOR_NOT_FOUND
164
- }));
165
- return {
166
- success: maybeInvertPolicyOutcome(false, policy.invert),
167
- issues
168
- };
169
- }
170
- try {
171
- return await evaluator.evaluate(policy, {
172
- ...ctx,
173
- evaluators: {
174
- ...this.evaluators,
175
- ...ctx.evaluators || {}
176
- }
177
- });
178
- } catch {
179
- issues.push(defineIssueItem({
180
- path: [
181
- policy.type
182
- ],
183
- message: `The ${policy.type} evaluator can not process the policy specification.`,
184
- code: ErrorCode.POLICY_EVALUATOR_NOT_PROCESSABLE
185
- }));
186
- return {
187
- success: maybeInvertPolicyOutcome(false, policy.invert),
188
- issues
189
- };
190
- }
191
- }
192
- async evaluateOrFail(policy, ctx) {
193
- const issues = [];
194
- try {
195
- const outcome = await this.evaluate(policy, ctx);
196
- if (outcome.success) {
197
- return;
198
- }
199
- if (outcome.issues) {
200
- issues.push(...outcome.issues);
201
- }
202
- } catch (e) {
203
- if (e instanceof PolicyError) {
204
- throw e;
205
- }
206
- }
207
- const error = new PolicyError(`The policy ${policy.type} evaluation failed.`);
208
- error.addIssues(issues);
209
- throw error;
210
- }
211
- }
212
-
213
- /*
214
- * Copyright (c) 2026.
215
- * Author Peter Placzek (tada5hi)
216
- * For the full copyright and license information,
217
- * view the LICENSE file that was distributed with this source code.
218
- */ class PolicyData {
219
- data;
220
- validated;
221
- constructor(data = {}, validated = new Set()){
222
- this.data = data;
223
- this.validated = validated;
224
- }
225
- set(key, value) {
226
- this.data[key] = value;
227
- this.validated.delete(key);
228
- }
229
- get(key) {
230
- if (key in this.data) {
231
- return this.data[key];
232
- }
233
- throw new Error(`Policy data item ${key} does not exist.`);
234
- }
235
- has(key) {
236
- return key in this.data;
237
- }
238
- setValidated(key) {
239
- this.validated.add(key);
240
- }
241
- isValidated(key) {
242
- return this.validated.has(key);
243
- }
244
- clone() {
245
- return new PolicyData({
246
- ...this.data
247
- }, new Set(this.validated));
248
- }
249
- }
250
-
172
+ * The policy engine is a component that interprets defined policies and makes decisions
173
+ * on whether to allow or deny a particular access.
174
+ */
175
+ var PolicyEngine = class {
176
+ evaluators;
177
+ constructor(evaluators = {}) {
178
+ this.evaluators = evaluators;
179
+ }
180
+ registerEvaluator(type, evaluator) {
181
+ this.evaluators[type] = evaluator;
182
+ }
183
+ registerEvaluators(evaluators) {
184
+ const keys = Object.keys(evaluators);
185
+ for (const key of keys) this.registerEvaluator(key, evaluators[key]);
186
+ }
187
+ /**
188
+ * @param policy
189
+ * @param ctx
190
+ */
191
+ async evaluate(policy, ctx) {
192
+ if (!policy.type) return {
193
+ success: maybeInvertPolicyOutcome(false, policy.invert),
194
+ issues: [defineIssueItem({
195
+ path: [],
196
+ message: "The policy can not be handled by any evaluator.",
197
+ code: ErrorCode.POLICY_EVALUATOR_NOT_FOUND
198
+ })]
199
+ };
200
+ if (ctx.exclude && ctx.exclude.length > 0 && ctx.exclude.includes(policy.type)) return { success: maybeInvertPolicyOutcome(true, policy.invert) };
201
+ if (ctx.include && ctx.include.length > 0 && !ctx.include.includes(policy.type)) return { success: maybeInvertPolicyOutcome(true, policy.invert) };
202
+ const issues = [];
203
+ const evaluator = this.evaluators[policy.type];
204
+ if (!evaluator) {
205
+ issues.push(defineIssueItem({
206
+ path: [policy.type],
207
+ message: `The policy ${policy.type} can not be handled by any evaluator.`,
208
+ code: ErrorCode.POLICY_EVALUATOR_NOT_FOUND
209
+ }));
210
+ return {
211
+ success: maybeInvertPolicyOutcome(false, policy.invert),
212
+ issues
213
+ };
214
+ }
215
+ try {
216
+ return await evaluator.evaluate(policy, {
217
+ ...ctx,
218
+ evaluators: {
219
+ ...this.evaluators,
220
+ ...ctx.evaluators || {}
221
+ }
222
+ });
223
+ } catch {
224
+ issues.push(defineIssueItem({
225
+ path: [policy.type],
226
+ message: `The ${policy.type} evaluator can not process the policy specification.`,
227
+ code: ErrorCode.POLICY_EVALUATOR_NOT_PROCESSABLE
228
+ }));
229
+ return {
230
+ success: maybeInvertPolicyOutcome(false, policy.invert),
231
+ issues
232
+ };
233
+ }
234
+ }
235
+ async evaluateOrFail(policy, ctx) {
236
+ const issues = [];
237
+ try {
238
+ const outcome = await this.evaluate(policy, ctx);
239
+ if (outcome.success) return;
240
+ if (outcome.issues) issues.push(...outcome.issues);
241
+ } catch (e) {
242
+ if (e instanceof PolicyError) throw e;
243
+ }
244
+ const error = new PolicyError(`The policy ${policy.type} evaluation failed.`);
245
+ error.addIssues(issues);
246
+ throw error;
247
+ }
248
+ };
249
+ //#endregion
250
+ //#region src/policy/data.ts
251
+ var PolicyData = class PolicyData {
252
+ data;
253
+ validated;
254
+ constructor(data = {}, validated = /* @__PURE__ */ new Set()) {
255
+ this.data = data;
256
+ this.validated = validated;
257
+ }
258
+ set(key, value) {
259
+ this.data[key] = value;
260
+ this.validated.delete(key);
261
+ }
262
+ get(key) {
263
+ if (key in this.data) return this.data[key];
264
+ throw new Error(`Policy data item ${key} does not exist.`);
265
+ }
266
+ has(key) {
267
+ return key in this.data;
268
+ }
269
+ setValidated(key) {
270
+ this.validated.add(key);
271
+ }
272
+ isValidated(key) {
273
+ return this.validated.has(key);
274
+ }
275
+ clone() {
276
+ return new PolicyData({ ...this.data }, new Set(this.validated));
277
+ }
278
+ };
279
+ //#endregion
280
+ //#region src/policy/evaluation/context/define.ts
251
281
  function definePolicyEvaluationContext(input = {}) {
252
- return {
253
- evaluators: input.evaluators || {},
254
- path: input.path || [],
255
- data: input.data || new PolicyData(),
256
- include: input.include || [],
257
- exclude: input.exclude || []
258
- };
259
- }
260
-
261
- /*
262
- * Copyright (c) 2026-2026.
263
- * Author Peter Placzek (tada5hi)
264
- * For the full copyright and license information,
265
- * view the LICENSE file that was distributed with this source code.
266
- */ var PolicyIssueSeverity = /*#__PURE__*/ function(PolicyIssueSeverity) {
267
- PolicyIssueSeverity["WARNING"] = "warning";
268
- PolicyIssueSeverity["ERROR"] = "error";
269
- return PolicyIssueSeverity;
282
+ return {
283
+ evaluators: input.evaluators || {},
284
+ path: input.path || [],
285
+ data: input.data || new PolicyData(),
286
+ include: input.include || [],
287
+ exclude: input.exclude || []
288
+ };
289
+ }
290
+ //#endregion
291
+ //#region src/policy/issue/constants.ts
292
+ let PolicyIssueSeverity = /* @__PURE__ */ function(PolicyIssueSeverity) {
293
+ PolicyIssueSeverity["WARNING"] = "warning";
294
+ PolicyIssueSeverity["ERROR"] = "error";
295
+ return PolicyIssueSeverity;
270
296
  }({});
271
- var PolicyIssueCode = /*#__PURE__*/ function(PolicyIssueCode) {
272
- // Data/Input
273
- PolicyIssueCode["DATA_MISSING"] = "DATA_MISSING";
274
- PolicyIssueCode["DATA_INVALID"] = "DATA_INVALID";
275
- // Policy Spec / Config
276
- PolicyIssueCode["INVALID"] = "INVALID";
277
- PolicyIssueCode["TYPE_UNKNOWN"] = "TYPE_UNKNOWN";
278
- PolicyIssueCode["FIELD_MISSING"] = "FIELD_MISSING";
279
- PolicyIssueCode["FIELD_INVALID"] = "FIELD_INVALID";
280
- // Composite / Tree evaluation
281
- PolicyIssueCode["CHILD_INVALID"] = "CHILD_INVALID";
282
- PolicyIssueCode["CHILD_EVALUATION_FAILED"] = "CHILD_EVALUATION_FAILED";
283
- // Engine / Evaluator registry
284
- PolicyIssueCode["EVALUATION_DENIED"] = "EVALUATION_DENIED";
285
- PolicyIssueCode["EVALUATOR_NOT_FOUND"] = "EVALUATOR_NOT_FOUND";
286
- PolicyIssueCode["EVALUATOR_ERROR"] = "EVALUATOR_ERROR";
287
- // Execution control
288
- PolicyIssueCode["SKIPPED_EXCLUDED"] = "SKIPPED_EXCLUDED";
289
- PolicyIssueCode["SKIPPED_NOT_INCLUDED"] = "SKIPPED_NOT_INCLUDED";
290
- // Internal / unexpected
291
- PolicyIssueCode["INTERNAL_ERROR"] = "INTERNAL_ERROR";
292
- return PolicyIssueCode;
297
+ let PolicyIssueCode = /* @__PURE__ */ function(PolicyIssueCode) {
298
+ PolicyIssueCode["DATA_MISSING"] = "DATA_MISSING";
299
+ PolicyIssueCode["DATA_INVALID"] = "DATA_INVALID";
300
+ PolicyIssueCode["INVALID"] = "INVALID";
301
+ PolicyIssueCode["TYPE_UNKNOWN"] = "TYPE_UNKNOWN";
302
+ PolicyIssueCode["FIELD_MISSING"] = "FIELD_MISSING";
303
+ PolicyIssueCode["FIELD_INVALID"] = "FIELD_INVALID";
304
+ PolicyIssueCode["CHILD_INVALID"] = "CHILD_INVALID";
305
+ PolicyIssueCode["CHILD_EVALUATION_FAILED"] = "CHILD_EVALUATION_FAILED";
306
+ PolicyIssueCode["EVALUATION_DENIED"] = "EVALUATION_DENIED";
307
+ PolicyIssueCode["EVALUATOR_NOT_FOUND"] = "EVALUATOR_NOT_FOUND";
308
+ PolicyIssueCode["EVALUATOR_ERROR"] = "EVALUATOR_ERROR";
309
+ PolicyIssueCode["SKIPPED_EXCLUDED"] = "SKIPPED_EXCLUDED";
310
+ PolicyIssueCode["SKIPPED_NOT_INCLUDED"] = "SKIPPED_NOT_INCLUDED";
311
+ PolicyIssueCode["INTERNAL_ERROR"] = "INTERNAL_ERROR";
312
+ return PolicyIssueCode;
293
313
  }({});
294
-
314
+ //#endregion
315
+ //#region src/policy/issue/define.ts
295
316
  function definePolicyIssueItem(input) {
296
- return defineIssueItem(input);
317
+ return defineIssueItem(input);
297
318
  }
298
319
  function definePolicyIssueGroup(input) {
299
- return defineIssueGroup(input);
300
- }
301
-
302
- class AttributeNamesPolicyValidator extends Container {
303
- initialize() {
304
- super.initialize();
305
- this.mount('names', createValidator(z.array(z.string().min(3).max(128))));
306
- this.mount('invert', createValidator(z.boolean().or(z.null()).or(z.undefined()).optional()));
307
- }
308
- }
309
-
310
- /*
311
- * Copyright (c) 2025.
312
- * Author Peter Placzek (tada5hi)
313
- * For the full copyright and license information,
314
- * view the LICENSE file that was distributed with this source code.
315
- */ function defineAttributesPolicy(data) {
316
- return data;
317
- }
318
-
319
- /*
320
- * Copyright (c) 2024-2024.
321
- * Author Peter Placzek (tada5hi)
322
- * For the full copyright and license information,
323
- * view the LICENSE file that was distributed with this source code.
324
- */ var BuiltInPolicyType = /*#__PURE__*/ function(BuiltInPolicyType) {
325
- /**
326
- * Bundles different policies.
327
- */ BuiltInPolicyType["COMPOSITE"] = "composite";
328
- /**
329
- * Date Based Access Control (DBAC)
330
- */ BuiltInPolicyType["DATE"] = "date";
331
- /**
332
- * Time Based Access Control (TBAC)
333
- */ BuiltInPolicyType["TIME"] = "time";
334
- /**
335
- * Attribute Name Based Access Control (ANBAC)
336
- */ BuiltInPolicyType["ATTRIBUTE_NAMES"] = "attributeNames";
337
- /**
338
- * Attribute Based Access Control (ABAC)
339
- */ BuiltInPolicyType["ATTRIBUTES"] = "attributes";
340
- /**
341
- * Realm of Identity is for attribute realm.
342
- */ BuiltInPolicyType["REALM_MATCH"] = "realmMatch";
343
- /**
344
- * Restriction based on identity (type, id, ...)
345
- */ BuiltInPolicyType["IDENTITY"] = "identity";
346
- /**
347
- * Restriction based on a binding between identity <-> permission
348
- */ BuiltInPolicyType["PERMISSION_BINDING"] = "permissionBinding";
349
- return BuiltInPolicyType;
320
+ return defineIssueGroup(input);
321
+ }
322
+ //#endregion
323
+ //#region src/policy/built-in/attribute-names/validator.ts
324
+ var AttributeNamesPolicyValidator = class extends Container {
325
+ initialize() {
326
+ super.initialize();
327
+ this.mount("names", createValidator(z.array(z.string().min(3).max(128))));
328
+ this.mount("invert", createValidator(z.boolean().or(z.null()).or(z.undefined()).optional()));
329
+ }
330
+ };
331
+ //#endregion
332
+ //#region src/policy/built-in/attributes/define.ts
333
+ function defineAttributesPolicy(data) {
334
+ return data;
335
+ }
336
+ //#endregion
337
+ //#region src/policy/built-in/constants.ts
338
+ let BuiltInPolicyType = /* @__PURE__ */ function(BuiltInPolicyType) {
339
+ /**
340
+ * Bundles different policies.
341
+ */
342
+ BuiltInPolicyType["COMPOSITE"] = "composite";
343
+ /**
344
+ * Date Based Access Control (DBAC)
345
+ */
346
+ BuiltInPolicyType["DATE"] = "date";
347
+ /**
348
+ * Time Based Access Control (TBAC)
349
+ */
350
+ BuiltInPolicyType["TIME"] = "time";
351
+ /**
352
+ * Attribute Name Based Access Control (ANBAC)
353
+ */
354
+ BuiltInPolicyType["ATTRIBUTE_NAMES"] = "attributeNames";
355
+ /**
356
+ * Attribute Based Access Control (ABAC)
357
+ */
358
+ BuiltInPolicyType["ATTRIBUTES"] = "attributes";
359
+ /**
360
+ * Realm of Identity is for attribute realm.
361
+ */
362
+ BuiltInPolicyType["REALM_MATCH"] = "realmMatch";
363
+ /**
364
+ * Restriction based on identity (type, id, ...)
365
+ */
366
+ BuiltInPolicyType["IDENTITY"] = "identity";
367
+ /**
368
+ * Restriction based on a binding between identity <-> permission
369
+ */
370
+ BuiltInPolicyType["PERMISSION_BINDING"] = "permissionBinding";
371
+ return BuiltInPolicyType;
350
372
  }({});
351
373
  const SystemPolicyName = {
352
- DEFAULT: 'system.default',
353
- IDENTITY: 'system.identity',
354
- PERMISSION_BINDING: 'system.permission-binding',
355
- REALM_MATCH: 'system.realm-match',
356
- REALM_BOUND: 'system.realm-bound',
357
- REALM_OR_GLOBAL: 'system.realm-or-global'
374
+ DEFAULT: "system.default",
375
+ IDENTITY: "system.identity",
376
+ PERMISSION_BINDING: "system.permission-binding",
377
+ REALM_MATCH: "system.realm-match",
378
+ REALM_BOUND: "system.realm-bound",
379
+ REALM_OR_GLOBAL: "system.realm-or-global"
358
380
  };
359
-
360
- class AttributesPolicyValidator extends Container {
361
- initialize() {
362
- super.initialize();
363
- this.mount('query', createValidator(z.looseObject({})));
364
- this.mount('invert', createValidator(z.boolean().or(z.null()).or(z.undefined()).optional()));
365
- }
366
- }
367
-
368
- class AttributesPolicyEvaluator {
369
- validator;
370
- constructor(){
371
- this.validator = new AttributesPolicyValidator();
372
- }
373
- async accessData(ctx) {
374
- if (!ctx.data.has(BuiltInPolicyType.ATTRIBUTES)) {
375
- return null;
376
- }
377
- if (ctx.data.isValidated(BuiltInPolicyType.ATTRIBUTES)) {
378
- return ctx.data.get(BuiltInPolicyType.ATTRIBUTES);
379
- }
380
- // todo: run validator on attributes (isObject ...)
381
- const data = ctx.data.get(BuiltInPolicyType.ATTRIBUTES);
382
- ctx.data.set(BuiltInPolicyType.ATTRIBUTES, data);
383
- ctx.data.setValidated(BuiltInPolicyType.ATTRIBUTES);
384
- return data;
385
- }
386
- async evaluate(value, ctx) {
387
- // todo: catch errors + transform to issue(s)
388
- const policy = await this.validator.run(value);
389
- const data = await this.accessData(ctx);
390
- if (!data) {
391
- return {
392
- success: false,
393
- issues: [
394
- definePolicyIssueItem({
395
- code: PolicyIssueCode.DATA_MISSING,
396
- message: 'The data property attributes is missing',
397
- path: ctx.path
398
- })
399
- ]
400
- };
401
- }
402
- this.fixQuery(policy.query);
403
- const testIt = guard(policy.query);
404
- return {
405
- success: maybeInvertPolicyOutcome(testIt(data), policy.invert)
406
- };
407
- }
408
- fixQuery(query) {
409
- if (Array.isArray(query)) {
410
- for (const element of query){
411
- this.fixQuery(element);
412
- }
413
- return;
414
- }
415
- if (isObject(query)) {
416
- const keys = Object.keys(query);
417
- for (const key of keys){
418
- const value = query[key];
419
- if (isObject(value) || Array.isArray(value)) {
420
- this.fixQuery(value);
421
- continue;
422
- }
423
- if (key === '$regex' && typeof value === 'string') {
424
- const fragments = value.match(/\/(.*?)\/([a-z]*)?$/i);
425
- if (fragments) {
426
- query[key] = new RegExp(fragments[1], fragments[2]);
427
- }
428
- }
429
- }
430
- }
431
- }
432
- }
433
-
434
- class AttributeNamesPolicyEvaluator {
435
- validator;
436
- attributesEvaluator;
437
- constructor(){
438
- this.validator = new AttributeNamesPolicyValidator();
439
- this.attributesEvaluator = new AttributesPolicyEvaluator();
440
- }
441
- async evaluate(value, ctx) {
442
- // todo: catch errors + transform to issue(s)
443
- const policy = await this.validator.run(value);
444
- const data = await this.attributesEvaluator.accessData(ctx);
445
- if (!data) {
446
- return {
447
- success: false,
448
- issues: [
449
- definePolicyIssueItem({
450
- code: PolicyIssueCode.DATA_MISSING,
451
- message: 'The data property attributes is missing',
452
- path: ctx.path
453
- })
454
- ]
455
- };
456
- }
457
- const attributes = flattenObject(data);
458
- const keys = Object.keys(attributes);
459
- const issues = [];
460
- for (const key of keys){
461
- const index = policy.names.indexOf(key);
462
- if (index === -1) {
463
- issues.push(definePolicyIssueItem({
464
- code: PolicyIssueCode.EVALUATION_DENIED,
465
- message: `The attribute ${key} is not included`,
466
- path: [
467
- ...ctx.path,
468
- key
469
- ]
470
- }));
471
- }
472
- }
473
- return {
474
- success: maybeInvertPolicyOutcome(issues.length === 0, policy.invert),
475
- issues
476
- };
477
- }
478
- }
479
-
480
- class CompositePolicyValidator extends Container {
481
- initialize() {
482
- super.initialize();
483
- this.mount('decision_strategy', createValidator(z.enum(DecisionStrategy).or(z.null()).or(z.undefined()).optional()));
484
- this.mount('children', createValidator(z.array(z.looseObject({
485
- type: z.string().min(3)
486
- }))));
487
- this.mount('invert', createValidator(z.boolean().or(z.null()).or(z.undefined()).optional()));
488
- }
489
- }
490
-
491
- class CompositePolicyEvaluator {
492
- validator;
493
- constructor(){
494
- this.validator = new CompositePolicyValidator();
495
- }
496
- async evaluate(value, ctx) {
497
- // todo: catch errors + transform to issue(s)
498
- const policy = await this.validator.run(value);
499
- let count = 0;
500
- const decision_strategy = policy.decision_strategy ?? DecisionStrategy.UNANIMOUS;
501
- const engine = new PolicyEngine(ctx.evaluators);
502
- const issues = [];
503
- for(let i = 0; i < policy.children.length; i++){
504
- const childPolicy = policy.children[i];
505
- const path = [
506
- ...ctx.path || [],
507
- childPolicy.type
508
- ];
509
- const outcome = await engine.evaluate(childPolicy, {
510
- ...ctx,
511
- path
512
- });
513
- if (outcome.success) {
514
- if (decision_strategy === DecisionStrategy.AFFIRMATIVE) {
515
- return {
516
- success: maybeInvertPolicyOutcome(true, policy.invert),
517
- issues: []
518
- };
519
- }
520
- count++;
521
- } else {
522
- if (outcome.issues) {
523
- issues.push(defineIssueGroup({
524
- message: `The evaluation of child policy ${childPolicy.type} failed`,
525
- issues: outcome.issues || [],
526
- path
527
- }));
528
- }
529
- if (decision_strategy === DecisionStrategy.UNANIMOUS) {
530
- return {
531
- success: maybeInvertPolicyOutcome(false, policy.invert),
532
- issues: [
533
- defineIssueGroup({
534
- message: `The evaluation of composite policy failed (${DecisionStrategy.UNANIMOUS})`,
535
- issues,
536
- path: ctx.path
537
- })
538
- ]
539
- };
540
- }
541
- count--;
542
- }
543
- }
544
- if (count > 0) {
545
- return {
546
- success: maybeInvertPolicyOutcome(true, policy.invert)
547
- };
548
- }
549
- return {
550
- success: maybeInvertPolicyOutcome(false, policy.invert),
551
- issues: [
552
- defineIssueGroup({
553
- message: `The evaluation of composite policy failed (${DecisionStrategy.CONSENSUS})`,
554
- issues: issues || [],
555
- path: ctx.path
556
- })
557
- ]
558
- };
559
- }
560
- }
561
-
381
+ //#endregion
382
+ //#region src/policy/built-in/attributes/validator.ts
383
+ var AttributesPolicyValidator = class extends Container {
384
+ initialize() {
385
+ super.initialize();
386
+ this.mount("query", createValidator(z.looseObject({})));
387
+ this.mount("invert", createValidator(z.boolean().or(z.null()).or(z.undefined()).optional()));
388
+ }
389
+ };
390
+ //#endregion
391
+ //#region src/policy/built-in/attributes/evaluator.ts
392
+ var AttributesPolicyEvaluator = class {
393
+ validator;
394
+ constructor() {
395
+ this.validator = new AttributesPolicyValidator();
396
+ }
397
+ async accessData(ctx) {
398
+ if (!ctx.data.has(BuiltInPolicyType.ATTRIBUTES)) return null;
399
+ if (ctx.data.isValidated(BuiltInPolicyType.ATTRIBUTES)) return ctx.data.get(BuiltInPolicyType.ATTRIBUTES);
400
+ const data = ctx.data.get(BuiltInPolicyType.ATTRIBUTES);
401
+ ctx.data.set(BuiltInPolicyType.ATTRIBUTES, data);
402
+ ctx.data.setValidated(BuiltInPolicyType.ATTRIBUTES);
403
+ return data;
404
+ }
405
+ async evaluate(value, ctx) {
406
+ const policy = await this.validator.run(value);
407
+ const data = await this.accessData(ctx);
408
+ if (!data) return {
409
+ success: false,
410
+ issues: [definePolicyIssueItem({
411
+ code: PolicyIssueCode.DATA_MISSING,
412
+ message: "The data property attributes is missing",
413
+ path: ctx.path
414
+ })]
415
+ };
416
+ this.fixQuery(policy.query);
417
+ return { success: maybeInvertPolicyOutcome(guard(policy.query)(data), policy.invert) };
418
+ }
419
+ fixQuery(query) {
420
+ if (Array.isArray(query)) {
421
+ for (const element of query) this.fixQuery(element);
422
+ return;
423
+ }
424
+ if (isObject(query)) {
425
+ const keys = Object.keys(query);
426
+ for (const key of keys) {
427
+ const value = query[key];
428
+ if (isObject(value) || Array.isArray(value)) {
429
+ this.fixQuery(value);
430
+ continue;
431
+ }
432
+ if (key === "$regex" && typeof value === "string") {
433
+ const fragments = value.match(/\/(.*?)\/([a-z]*)?$/i);
434
+ if (fragments && fragments[1] !== void 0) query[key] = new RegExp(fragments[1], fragments[2] || "");
435
+ }
436
+ }
437
+ }
438
+ }
439
+ };
440
+ //#endregion
441
+ //#region src/policy/built-in/attribute-names/evaluator.ts
442
+ var AttributeNamesPolicyEvaluator = class {
443
+ validator;
444
+ attributesEvaluator;
445
+ constructor() {
446
+ this.validator = new AttributeNamesPolicyValidator();
447
+ this.attributesEvaluator = new AttributesPolicyEvaluator();
448
+ }
449
+ async evaluate(value, ctx) {
450
+ const policy = await this.validator.run(value);
451
+ const data = await this.attributesEvaluator.accessData(ctx);
452
+ if (!data) return {
453
+ success: false,
454
+ issues: [definePolicyIssueItem({
455
+ code: PolicyIssueCode.DATA_MISSING,
456
+ message: "The data property attributes is missing",
457
+ path: ctx.path
458
+ })]
459
+ };
460
+ const attributes = flattenObject(data);
461
+ const keys = Object.keys(attributes);
462
+ const issues = [];
463
+ for (const key of keys) if (policy.names.indexOf(key) === -1) issues.push(definePolicyIssueItem({
464
+ code: PolicyIssueCode.EVALUATION_DENIED,
465
+ message: `The attribute ${key} is not included`,
466
+ path: [...ctx.path, key]
467
+ }));
468
+ return {
469
+ success: maybeInvertPolicyOutcome(issues.length === 0, policy.invert),
470
+ issues
471
+ };
472
+ }
473
+ };
474
+ //#endregion
475
+ //#region src/policy/built-in/composite/validator.ts
476
+ var CompositePolicyValidator = class extends Container {
477
+ initialize() {
478
+ super.initialize();
479
+ this.mount("decision_strategy", createValidator(z.enum(DecisionStrategy).or(z.null()).or(z.undefined()).optional()));
480
+ this.mount("children", createValidator(z.array(z.looseObject({ type: z.string().min(3) }))));
481
+ this.mount("invert", createValidator(z.boolean().or(z.null()).or(z.undefined()).optional()));
482
+ }
483
+ };
484
+ //#endregion
485
+ //#region src/policy/built-in/composite/evaluator.ts
486
+ var CompositePolicyEvaluator = class {
487
+ validator;
488
+ constructor() {
489
+ this.validator = new CompositePolicyValidator();
490
+ }
491
+ async evaluate(value, ctx) {
492
+ const policy = await this.validator.run(value);
493
+ let count = 0;
494
+ const decision_strategy = policy.decision_strategy ?? DecisionStrategy.UNANIMOUS;
495
+ const engine = new PolicyEngine(ctx.evaluators);
496
+ const issues = [];
497
+ for (const childPolicy of policy.children) {
498
+ const path = [...ctx.path || [], ...childPolicy.type ? [childPolicy.type] : []];
499
+ const outcome = await engine.evaluate(childPolicy, {
500
+ ...ctx,
501
+ path
502
+ });
503
+ if (outcome.success) {
504
+ if (decision_strategy === DecisionStrategy.AFFIRMATIVE) return {
505
+ success: maybeInvertPolicyOutcome(true, policy.invert),
506
+ issues: []
507
+ };
508
+ count++;
509
+ } else {
510
+ if (outcome.issues) issues.push(defineIssueGroup({
511
+ message: `The evaluation of child policy ${childPolicy.type} failed`,
512
+ issues: outcome.issues || [],
513
+ path
514
+ }));
515
+ if (decision_strategy === DecisionStrategy.UNANIMOUS) return {
516
+ success: maybeInvertPolicyOutcome(false, policy.invert),
517
+ issues: [defineIssueGroup({
518
+ message: `The evaluation of composite policy failed (${DecisionStrategy.UNANIMOUS})`,
519
+ issues,
520
+ path: ctx.path
521
+ })]
522
+ };
523
+ count--;
524
+ }
525
+ }
526
+ if (count > 0) return { success: maybeInvertPolicyOutcome(true, policy.invert) };
527
+ return {
528
+ success: maybeInvertPolicyOutcome(false, policy.invert),
529
+ issues: [defineIssueGroup({
530
+ message: `The evaluation of composite policy failed (${DecisionStrategy.CONSENSUS})`,
531
+ issues: issues || [],
532
+ path: ctx.path
533
+ })]
534
+ };
535
+ }
536
+ };
537
+ //#endregion
538
+ //#region src/policy/built-in/composite/helper.ts
562
539
  function isCompositePolicy(input) {
563
- return input.type === BuiltInPolicyType.COMPOSITE;
564
- }
565
-
566
- class DatePolicyValidator extends Container {
567
- initialize() {
568
- super.initialize();
569
- this.mount('start', createValidator(z.date().or(z.iso.date()).or(z.number()).or(z.null()).or(z.undefined()).optional()));
570
- this.mount('end', createValidator(z.date().or(z.iso.date()).or(z.number()).or(z.null()).or(z.undefined()).optional()));
571
- this.mount('invert', createValidator(z.boolean().or(z.undefined()).or(z.null()).optional()));
572
- }
573
- }
574
-
540
+ return input.type === BuiltInPolicyType.COMPOSITE;
541
+ }
542
+ //#endregion
543
+ //#region src/policy/built-in/date/validator.ts
544
+ var DatePolicyValidator = class extends Container {
545
+ initialize() {
546
+ super.initialize();
547
+ this.mount("start", createValidator(z.date().or(z.iso.date()).or(z.number()).or(z.null()).or(z.undefined()).optional()));
548
+ this.mount("end", createValidator(z.date().or(z.iso.date()).or(z.number()).or(z.null()).or(z.undefined()).optional()));
549
+ this.mount("invert", createValidator(z.boolean().or(z.undefined()).or(z.null()).optional()));
550
+ }
551
+ };
552
+ //#endregion
553
+ //#region src/policy/built-in/date/evaluator.ts
575
554
  function normalizeDate$1(input) {
576
- return new Date(input.getFullYear(), input.getMonth(), input.getDate());
555
+ return new Date(input.getFullYear(), input.getMonth(), input.getDate());
577
556
  }
578
557
  function toDate$1(input) {
579
- if (typeof input === 'string') {
580
- return new Date(input);
581
- }
582
- if (typeof input === 'number') {
583
- return new Date(input);
584
- }
585
- return input;
586
- }
587
- class DatePolicyEvaluator {
588
- validator;
589
- constructor(){
590
- this.validator = new DatePolicyValidator();
591
- }
592
- async evaluate(value, ctx) {
593
- // todo: catch errors + transform to issue(s)
594
- const policy = await this.validator.run(value);
595
- let now;
596
- if (ctx.data.has(BuiltInPolicyType.DATE)) {
597
- if (ctx.data.isValidated(BuiltInPolicyType.DATE)) {
598
- now = ctx.data.get(BuiltInPolicyType.DATE);
599
- } else {
600
- // todo: run validator on attributes (isObject ...)
601
- now = normalizeDate$1(toDate$1(ctx.data.get(BuiltInPolicyType.DATE)));
602
- ctx.data.set(BuiltInPolicyType.DATE, now);
603
- ctx.data.setValidated(BuiltInPolicyType.DATE);
604
- }
605
- } else {
606
- now = normalizeDate$1(new Date());
607
- }
608
- if (policy.start) {
609
- const start = normalizeDate$1(toDate$1(policy.start));
610
- if (now < start) {
611
- return {
612
- success: maybeInvertPolicyOutcome(false, policy.invert)
613
- };
614
- }
615
- }
616
- if (policy.end) {
617
- const end = normalizeDate$1(toDate$1(policy.end));
618
- if (now > end) {
619
- return {
620
- success: maybeInvertPolicyOutcome(false, policy.invert)
621
- };
622
- }
623
- }
624
- return {
625
- success: maybeInvertPolicyOutcome(true, policy.invert)
626
- };
627
- }
628
- }
629
-
630
- class PolicyIdentityDataValidator extends Container {
631
- initialize() {
632
- super.initialize();
633
- this.mount('type', createValidator(z.string().min(3).max(128)));
634
- this.mount('id', createValidator(z.uuid()));
635
- this.mount('clientId', createValidator(z.uuid().or(z.null()).or(z.undefined()).optional()));
636
- this.mount('realmId', createValidator(z.uuid().or(z.null()).or(z.undefined()).optional()));
637
- this.mount('realmName', createValidator(z.string().min(3).max(128).or(z.null()).or(z.undefined()).optional()));
638
- }
639
- }
640
-
641
- class IdentityPolicyValidator extends Container {
642
- initialize() {
643
- this.mount('types', createValidator(z.array(z.string()).or(z.null()).or(z.undefined()).optional()));
644
- this.mount('invert', createValidator(z.boolean().or(z.null()).or(z.undefined()).optional()));
645
- }
646
- }
647
-
648
- class IdentityPolicyEvaluator {
649
- validator;
650
- dataValidator;
651
- constructor(){
652
- this.validator = new IdentityPolicyValidator();
653
- this.dataValidator = new PolicyIdentityDataValidator();
654
- }
655
- async accessData(ctx) {
656
- if (!ctx.data.has('identity')) {
657
- return null;
658
- }
659
- if (ctx.data.isValidated('identity')) {
660
- return ctx.data.get('identity');
661
- }
662
- const data = await this.dataValidator.run(ctx.data.get('identity'));
663
- ctx.data.set('identity', data);
664
- ctx.data.setValidated('identity');
665
- return data;
666
- }
667
- async evaluate(value, ctx) {
668
- // todo: catch errors + transform to issue(s)
669
- const policy = await this.validator.run(value);
670
- const data = await this.accessData(ctx);
671
- if (!data) {
672
- return {
673
- success: false,
674
- issues: [
675
- definePolicyIssueItem({
676
- code: PolicyIssueCode.DATA_MISSING,
677
- message: 'The data property identity is missing',
678
- path: ctx.path
679
- })
680
- ]
681
- };
682
- }
683
- if (!policy.types || policy.types.length === 0) {
684
- return {
685
- success: maybeInvertPolicyOutcome(true, policy.invert)
686
- };
687
- }
688
- const typeAllowed = policy.types.includes(data.type);
689
- if (typeAllowed) {
690
- return {
691
- success: maybeInvertPolicyOutcome(typeAllowed, policy.invert)
692
- };
693
- }
694
- return {
695
- success: maybeInvertPolicyOutcome(typeAllowed, policy.invert),
696
- issues: [
697
- definePolicyIssueItem({
698
- code: PolicyIssueCode.EVALUATION_DENIED,
699
- message: `The type ${data.type} is not covered by the policy configuration`,
700
- path: ctx.path
701
- })
702
- ]
703
- };
704
- }
705
- }
706
-
707
- class PermissionBindingPolicyValidator extends Container {
708
- initialize() {}
709
- }
710
-
711
- class PermissionBindingPolicyEvaluator {
712
- validator;
713
- constructor(){
714
- this.validator = new PermissionBindingPolicyValidator();
715
- }
716
- async evaluate(value) {
717
- const policy = await this.validator.run(value);
718
- // todo: this must be changed when the permission-checker not only checks owned permissions.
719
- return {
720
- success: maybeInvertPolicyOutcome(true, policy.invert)
721
- };
722
- }
723
- }
724
-
725
- class RealmMatchPolicyValidator extends Container {
726
- initialize() {
727
- super.initialize();
728
- this.mount('decision_strategy', createValidator(z.enum(DecisionStrategy).or(z.null()).or(z.undefined()).optional()));
729
- this.mount('attribute_name', createValidator(z.string().min(3).or(z.array(z.string().min(3))).or(z.null()).or(z.undefined()).optional()));
730
- this.mount('attribute_name_strict', createValidator(z.boolean().or(z.null()).or(z.undefined()).optional()));
731
- this.mount('attribute_null_match_all', createValidator(z.boolean().or(z.null()).or(z.undefined()).optional()));
732
- this.mount('identity_master_match_all', createValidator(z.boolean().or(z.null()).or(z.undefined()).optional()));
733
- this.mount('invert', createValidator(z.boolean().or(z.null()).or(z.undefined()).optional()));
734
- }
735
- }
736
-
737
- class RealmMatchPolicyEvaluator {
738
- validator;
739
- identityEvaluator;
740
- attributesEvaluator;
741
- constructor(){
742
- this.validator = new RealmMatchPolicyValidator();
743
- this.identityEvaluator = new IdentityPolicyEvaluator();
744
- this.attributesEvaluator = new AttributesPolicyEvaluator();
745
- }
746
- async evaluate(value, ctx) {
747
- // todo: catch errors + transform to issue(s)
748
- const policy = await this.validator.run(value);
749
- const identity = await this.identityEvaluator.accessData(ctx);
750
- if (!identity) {
751
- return {
752
- success: false,
753
- issues: [
754
- definePolicyIssueItem({
755
- code: PolicyIssueCode.DATA_MISSING,
756
- message: 'The data property identity is missing',
757
- path: ctx.path
758
- })
759
- ]
760
- };
761
- }
762
- const attributes = await this.attributesEvaluator.accessData(ctx);
763
- if (!attributes) {
764
- return {
765
- success: false,
766
- issues: [
767
- definePolicyIssueItem({
768
- code: PolicyIssueCode.DATA_MISSING,
769
- message: 'The data property attributes is missing',
770
- path: ctx.path
771
- })
772
- ]
773
- };
774
- }
775
- const identityMasterMatchAll = policy.identity_master_match_all ?? true;
776
- if (identityMasterMatchAll && identity.realmName && identity.realmName === 'master') {
777
- return {
778
- success: maybeInvertPolicyOutcome(true, policy.invert)
779
- };
780
- }
781
- let keys;
782
- if (policy.attribute_name) {
783
- if (Array.isArray(policy.attribute_name)) {
784
- keys = policy.attribute_name;
785
- } else {
786
- keys = [
787
- policy.attribute_name
788
- ];
789
- }
790
- } else {
791
- keys = [
792
- 'realm_id',
793
- 'realm_name',
794
- 'realmId',
795
- 'realmName'
796
- ];
797
- policy.decision_strategy = DecisionStrategy.CONSENSUS;
798
- }
799
- const attribute_name_strict = policy.attribute_name_strict ?? true;
800
- if (!attribute_name_strict) {
801
- const resourceKeys = Object.keys(attributes);
802
- const keysToAdd = [];
803
- for (const resourceKey of resourceKeys){
804
- let contains = false;
805
- for (const key of keys){
806
- if (resourceKey !== key && resourceKey.includes(key)) {
807
- contains = true;
808
- break;
809
- }
810
- }
811
- if (contains) {
812
- keysToAdd.push(resourceKey);
813
- }
814
- }
815
- if (keysToAdd.length > 0) {
816
- keys.push(...keysToAdd);
817
- }
818
- }
819
- let count = 0;
820
- let evaluated = false;
821
- for (const key of keys){
822
- if (!hasOwnProperty(attributes, key)) {
823
- continue;
824
- }
825
- evaluated = true;
826
- let outcome = false;
827
- const attributeValue = attributes[key];
828
- if (attributeValue === null && policy.attribute_null_match_all) {
829
- outcome = true;
830
- } else if (attributeValue === identity.realmId || attributeValue === identity.realmName) {
831
- outcome = true;
832
- }
833
- if (outcome) {
834
- if (policy.decision_strategy === DecisionStrategy.AFFIRMATIVE) {
835
- return {
836
- success: maybeInvertPolicyOutcome(true, policy.invert)
837
- };
838
- }
839
- count++;
840
- } else {
841
- if (policy.decision_strategy === DecisionStrategy.UNANIMOUS) {
842
- return {
843
- success: maybeInvertPolicyOutcome(false, policy.invert)
844
- };
845
- }
846
- count--;
847
- }
848
- }
849
- if (!evaluated) {
850
- return {
851
- success: maybeInvertPolicyOutcome(true, policy.invert)
852
- };
853
- }
854
- return {
855
- success: maybeInvertPolicyOutcome(count > 0, policy.invert)
856
- };
857
- }
858
- }
859
-
860
- /*
861
- * Copyright (c) 2024-2024.
862
- * Author Peter Placzek (tada5hi)
863
- * For the full copyright and license information,
864
- * view the LICENSE file that was distributed with this source code.
865
- */ var TimePolicyInterval = /*#__PURE__*/ function(TimePolicyInterval) {
866
- TimePolicyInterval["DAILY"] = "daily";
867
- TimePolicyInterval["WEEKLY"] = "weekly";
868
- TimePolicyInterval["MONTHLY"] = "monthly";
869
- TimePolicyInterval["YEARLY"] = "yearly";
870
- return TimePolicyInterval;
558
+ if (typeof input === "string") return new Date(input);
559
+ if (typeof input === "number") return new Date(input);
560
+ return input;
561
+ }
562
+ var DatePolicyEvaluator = class {
563
+ validator;
564
+ constructor() {
565
+ this.validator = new DatePolicyValidator();
566
+ }
567
+ async evaluate(value, ctx) {
568
+ const policy = await this.validator.run(value);
569
+ let now;
570
+ if (ctx.data.has(BuiltInPolicyType.DATE)) if (ctx.data.isValidated(BuiltInPolicyType.DATE)) now = ctx.data.get(BuiltInPolicyType.DATE);
571
+ else {
572
+ now = normalizeDate$1(toDate$1(ctx.data.get(BuiltInPolicyType.DATE)));
573
+ ctx.data.set(BuiltInPolicyType.DATE, now);
574
+ ctx.data.setValidated(BuiltInPolicyType.DATE);
575
+ }
576
+ else now = normalizeDate$1(/* @__PURE__ */ new Date());
577
+ if (policy.start) {
578
+ const start = normalizeDate$1(toDate$1(policy.start));
579
+ if (now < start) return { success: maybeInvertPolicyOutcome(false, policy.invert) };
580
+ }
581
+ if (policy.end) {
582
+ const end = normalizeDate$1(toDate$1(policy.end));
583
+ if (now > end) return { success: maybeInvertPolicyOutcome(false, policy.invert) };
584
+ }
585
+ return { success: maybeInvertPolicyOutcome(true, policy.invert) };
586
+ }
587
+ };
588
+ //#endregion
589
+ //#region src/policy/built-in/identity/data/validator.ts
590
+ var PolicyIdentityDataValidator = class extends Container {
591
+ initialize() {
592
+ super.initialize();
593
+ this.mount("type", createValidator(z.string().min(3).max(128)));
594
+ this.mount("id", createValidator(z.uuid()));
595
+ this.mount("clientId", createValidator(z.uuid().or(z.null()).or(z.undefined()).optional()));
596
+ this.mount("realmId", createValidator(z.uuid().or(z.null()).or(z.undefined()).optional()));
597
+ this.mount("realmName", createValidator(z.string().min(3).max(128).or(z.null()).or(z.undefined()).optional()));
598
+ }
599
+ };
600
+ //#endregion
601
+ //#region src/policy/built-in/identity/validator.ts
602
+ var IdentityPolicyValidator = class extends Container {
603
+ initialize() {
604
+ this.mount("types", createValidator(z.array(z.string()).or(z.null()).or(z.undefined()).optional()));
605
+ this.mount("invert", createValidator(z.boolean().or(z.null()).or(z.undefined()).optional()));
606
+ }
607
+ };
608
+ //#endregion
609
+ //#region src/policy/built-in/identity/evaluator.ts
610
+ var IdentityPolicyEvaluator = class {
611
+ validator;
612
+ dataValidator;
613
+ constructor() {
614
+ this.validator = new IdentityPolicyValidator();
615
+ this.dataValidator = new PolicyIdentityDataValidator();
616
+ }
617
+ async accessData(ctx) {
618
+ if (!ctx.data.has("identity")) return null;
619
+ if (ctx.data.isValidated("identity")) return ctx.data.get("identity");
620
+ const data = await this.dataValidator.run(ctx.data.get("identity"));
621
+ ctx.data.set("identity", data);
622
+ ctx.data.setValidated("identity");
623
+ return data;
624
+ }
625
+ async evaluate(value, ctx) {
626
+ const policy = await this.validator.run(value);
627
+ const data = await this.accessData(ctx);
628
+ if (!data) return {
629
+ success: false,
630
+ issues: [definePolicyIssueItem({
631
+ code: PolicyIssueCode.DATA_MISSING,
632
+ message: "The data property identity is missing",
633
+ path: ctx.path
634
+ })]
635
+ };
636
+ if (!policy.types || policy.types.length === 0) return { success: maybeInvertPolicyOutcome(true, policy.invert) };
637
+ const typeAllowed = policy.types.includes(data.type);
638
+ if (typeAllowed) return { success: maybeInvertPolicyOutcome(typeAllowed, policy.invert) };
639
+ return {
640
+ success: maybeInvertPolicyOutcome(typeAllowed, policy.invert),
641
+ issues: [definePolicyIssueItem({
642
+ code: PolicyIssueCode.EVALUATION_DENIED,
643
+ message: `The type ${data.type} is not covered by the policy configuration`,
644
+ path: ctx.path
645
+ })]
646
+ };
647
+ }
648
+ };
649
+ //#endregion
650
+ //#region src/policy/built-in/permission-binding/validator.ts
651
+ var PermissionBindingPolicyValidator = class extends Container {
652
+ initialize() {}
653
+ };
654
+ //#endregion
655
+ //#region src/policy/built-in/permission-binding/module.ts
656
+ var PermissionBindingPolicyEvaluator = class {
657
+ validator;
658
+ constructor() {
659
+ this.validator = new PermissionBindingPolicyValidator();
660
+ }
661
+ async evaluate(value) {
662
+ return { success: maybeInvertPolicyOutcome(true, (await this.validator.run(value)).invert) };
663
+ }
664
+ };
665
+ //#endregion
666
+ //#region src/policy/built-in/realm-match/validator.ts
667
+ var RealmMatchPolicyValidator = class extends Container {
668
+ initialize() {
669
+ super.initialize();
670
+ this.mount("decision_strategy", createValidator(z.enum(DecisionStrategy).or(z.null()).or(z.undefined()).optional()));
671
+ this.mount("attribute_name", createValidator(z.string().min(3).or(z.array(z.string().min(3))).or(z.null()).or(z.undefined()).optional()));
672
+ this.mount("attribute_name_strict", createValidator(z.boolean().or(z.null()).or(z.undefined()).optional()));
673
+ this.mount("attribute_null_match_all", createValidator(z.boolean().or(z.null()).or(z.undefined()).optional()));
674
+ this.mount("identity_master_match_all", createValidator(z.boolean().or(z.null()).or(z.undefined()).optional()));
675
+ this.mount("invert", createValidator(z.boolean().or(z.null()).or(z.undefined()).optional()));
676
+ }
677
+ };
678
+ //#endregion
679
+ //#region src/policy/built-in/realm-match/evaluator.ts
680
+ var RealmMatchPolicyEvaluator = class {
681
+ validator;
682
+ identityEvaluator;
683
+ attributesEvaluator;
684
+ constructor() {
685
+ this.validator = new RealmMatchPolicyValidator();
686
+ this.identityEvaluator = new IdentityPolicyEvaluator();
687
+ this.attributesEvaluator = new AttributesPolicyEvaluator();
688
+ }
689
+ async evaluate(value, ctx) {
690
+ const policy = await this.validator.run(value);
691
+ const identity = await this.identityEvaluator.accessData(ctx);
692
+ if (!identity) return {
693
+ success: false,
694
+ issues: [definePolicyIssueItem({
695
+ code: PolicyIssueCode.DATA_MISSING,
696
+ message: "The data property identity is missing",
697
+ path: ctx.path
698
+ })]
699
+ };
700
+ const attributes = await this.attributesEvaluator.accessData(ctx);
701
+ if (!attributes) return {
702
+ success: false,
703
+ issues: [definePolicyIssueItem({
704
+ code: PolicyIssueCode.DATA_MISSING,
705
+ message: "The data property attributes is missing",
706
+ path: ctx.path
707
+ })]
708
+ };
709
+ if ((policy.identity_master_match_all ?? true) && identity.realmName && identity.realmName === "master") return { success: maybeInvertPolicyOutcome(true, policy.invert) };
710
+ let keys;
711
+ if (policy.attribute_name) if (Array.isArray(policy.attribute_name)) keys = policy.attribute_name;
712
+ else keys = [policy.attribute_name];
713
+ else {
714
+ keys = [
715
+ "realm_id",
716
+ "realm_name",
717
+ "realmId",
718
+ "realmName"
719
+ ];
720
+ policy.decision_strategy = DecisionStrategy.CONSENSUS;
721
+ }
722
+ if (!(policy.attribute_name_strict ?? true)) {
723
+ const resourceKeys = Object.keys(attributes);
724
+ const keysToAdd = [];
725
+ for (const resourceKey of resourceKeys) {
726
+ let contains = false;
727
+ for (const key of keys) if (resourceKey !== key && resourceKey.includes(key)) {
728
+ contains = true;
729
+ break;
730
+ }
731
+ if (contains) keysToAdd.push(resourceKey);
732
+ }
733
+ if (keysToAdd.length > 0) keys.push(...keysToAdd);
734
+ }
735
+ let count = 0;
736
+ let evaluated = false;
737
+ for (const key of keys) {
738
+ if (!hasOwnProperty(attributes, key)) continue;
739
+ evaluated = true;
740
+ let outcome = false;
741
+ const attributeValue = attributes[key];
742
+ if (attributeValue === null && policy.attribute_null_match_all) outcome = true;
743
+ else if (attributeValue === identity.realmId || attributeValue === identity.realmName) outcome = true;
744
+ if (outcome) {
745
+ if (policy.decision_strategy === DecisionStrategy.AFFIRMATIVE) return { success: maybeInvertPolicyOutcome(true, policy.invert) };
746
+ count++;
747
+ } else {
748
+ if (policy.decision_strategy === DecisionStrategy.UNANIMOUS) return { success: maybeInvertPolicyOutcome(false, policy.invert) };
749
+ count--;
750
+ }
751
+ }
752
+ if (!evaluated) return { success: maybeInvertPolicyOutcome(true, policy.invert) };
753
+ return { success: maybeInvertPolicyOutcome(count > 0, policy.invert) };
754
+ }
755
+ };
756
+ //#endregion
757
+ //#region src/policy/built-in/time/constants.ts
758
+ let TimePolicyInterval = /* @__PURE__ */ function(TimePolicyInterval) {
759
+ TimePolicyInterval["DAILY"] = "daily";
760
+ TimePolicyInterval["WEEKLY"] = "weekly";
761
+ TimePolicyInterval["MONTHLY"] = "monthly";
762
+ TimePolicyInterval["YEARLY"] = "yearly";
763
+ return TimePolicyInterval;
871
764
  }({});
872
-
765
+ //#endregion
766
+ //#region src/policy/built-in/time/helpers.ts
873
767
  function isIntervalForDayOfWeek(interval) {
874
- return interval === TimePolicyInterval.WEEKLY || interval === TimePolicyInterval.MONTHLY || interval === TimePolicyInterval.YEARLY;
768
+ return interval === TimePolicyInterval.WEEKLY || interval === TimePolicyInterval.MONTHLY || interval === TimePolicyInterval.YEARLY;
875
769
  }
876
770
  function isIntervalForDayOfMonth(interval) {
877
- return interval === TimePolicyInterval.MONTHLY || interval === TimePolicyInterval.YEARLY;
771
+ return interval === TimePolicyInterval.MONTHLY || interval === TimePolicyInterval.YEARLY;
878
772
  }
879
773
  function isIntervalForDayOfYear(interval) {
880
- return interval === TimePolicyInterval.YEARLY;
881
- }
882
-
883
- class TimePolicyValidator extends Container {
884
- initialize() {
885
- super.initialize();
886
- this.mount('day_of_week', createValidator(z.number().min(0).max(6).or(z.null()).or(z.undefined()).optional()));
887
- this.mount('day_of_month', createValidator(z.number().min(1).max(31).or(z.null()).or(z.undefined()).optional()));
888
- this.mount('day_of_year', createValidator(z.number().min(1).max(365).or(z.null()).or(z.undefined()).optional()));
889
- this.mount('start', createValidator(z.date().or(z.iso.datetime()).or(z.iso.time()).or(z.number()).or(z.null()).or(z.undefined()).optional()));
890
- this.mount('end', createValidator(z.date().or(z.iso.datetime()).or(z.iso.time()).or(z.number()).or(z.null()).or(z.undefined()).optional()));
891
- this.mount('interval', createValidator(z.enum(TimePolicyInterval).or(z.null()).or(z.undefined()).optional()));
892
- this.mount('invert', createValidator(z.boolean().or(z.undefined()).or(z.null()).optional()));
893
- }
894
- }
895
-
774
+ return interval === TimePolicyInterval.YEARLY;
775
+ }
776
+ //#endregion
777
+ //#region src/policy/built-in/time/validator.ts
778
+ var TimePolicyValidator = class extends Container {
779
+ initialize() {
780
+ super.initialize();
781
+ this.mount("day_of_week", createValidator(z.number().min(0).max(6).or(z.null()).or(z.undefined()).optional()));
782
+ this.mount("day_of_month", createValidator(z.number().min(1).max(31).or(z.null()).or(z.undefined()).optional()));
783
+ this.mount("day_of_year", createValidator(z.number().min(1).max(365).or(z.null()).or(z.undefined()).optional()));
784
+ this.mount("start", createValidator(z.date().or(z.iso.datetime()).or(z.iso.time()).or(z.number()).or(z.null()).or(z.undefined()).optional()));
785
+ this.mount("end", createValidator(z.date().or(z.iso.datetime()).or(z.iso.time()).or(z.number()).or(z.null()).or(z.undefined()).optional()));
786
+ this.mount("interval", createValidator(z.enum(TimePolicyInterval).or(z.null()).or(z.undefined()).optional()));
787
+ this.mount("invert", createValidator(z.boolean().or(z.undefined()).or(z.null()).optional()));
788
+ }
789
+ };
790
+ //#endregion
791
+ //#region src/policy/built-in/time/evaluator.ts
896
792
  const timeRegex = /^(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d)?$/;
897
793
  function normalizeDate(input, dateRef) {
898
- const date = dateRef ? new Date(dateRef) : new Date();
899
- date.setHours(input.getHours(), input.getMinutes());
900
- return date;
794
+ const date = dateRef ? new Date(dateRef) : /* @__PURE__ */ new Date();
795
+ date.setHours(input.getHours(), input.getMinutes());
796
+ return date;
901
797
  }
902
798
  function toDate(input, dateRef) {
903
- if (typeof input === 'string') {
904
- if (timeRegex.test(input)) {
905
- const [startHours, startMinutes] = input.split(':').map(Number);
906
- const date = dateRef ? new Date(dateRef) : new Date();
907
- date.setHours(startHours, startMinutes);
908
- return date;
909
- }
910
- return new Date(input);
911
- }
912
- if (typeof input === 'number') {
913
- return new Date(input);
914
- }
915
- return input;
916
- }
917
- class TimePolicyEvaluator {
918
- validator;
919
- constructor(){
920
- this.validator = new TimePolicyValidator();
921
- }
922
- async evaluate(value, ctx) {
923
- // todo: catch errors + transform to issue(s)
924
- const policy = await this.validator.run(value);
925
- let now;
926
- if (ctx.data.has(BuiltInPolicyType.TIME)) {
927
- if (ctx.data.isValidated(BuiltInPolicyType.TIME)) {
928
- now = ctx.data.get(BuiltInPolicyType.TIME);
929
- } else {
930
- // todo: run validator on attributes (isObject ...)
931
- now = toDate(ctx.data.get(BuiltInPolicyType.TIME));
932
- ctx.data.set(BuiltInPolicyType.TIME, now);
933
- ctx.data.setValidated(BuiltInPolicyType.TIME);
934
- }
935
- } else {
936
- now = new Date();
937
- }
938
- if (policy.start) {
939
- const start = normalizeDate(toDate(policy.start, now), now);
940
- if (now < start) {
941
- return {
942
- success: maybeInvertPolicyOutcome(false, policy.invert)
943
- };
944
- }
945
- }
946
- if (policy.end) {
947
- const end = normalizeDate(toDate(policy.end, now), now);
948
- if (now > end) {
949
- return {
950
- success: maybeInvertPolicyOutcome(false, policy.invert)
951
- };
952
- }
953
- }
954
- if (policy.interval) {
955
- if (isIntervalForDayOfWeek(policy.interval) && policy.day_of_week) {
956
- if (now.getDay() !== policy.day_of_week) {
957
- return {
958
- success: maybeInvertPolicyOutcome(false, policy.invert)
959
- };
960
- }
961
- }
962
- if (isIntervalForDayOfMonth(policy.interval) && policy.day_of_month) {
963
- if (now.getDate() !== policy.day_of_month) {
964
- return {
965
- success: maybeInvertPolicyOutcome(false, policy.invert)
966
- };
967
- }
968
- }
969
- if (isIntervalForDayOfYear(policy.interval) && policy.day_of_year) {
970
- const start = new Date(now.getFullYear(), 0, 0);
971
- const diff = now.getTime() - start.getTime() + (start.getTimezoneOffset() - now.getTimezoneOffset()) * 60 * 1000;
972
- const oneDay = 1000 * 60 * 60 * 24;
973
- const dayOfYear = Math.floor(diff / oneDay);
974
- if (dayOfYear !== policy.day_of_year) {
975
- return {
976
- success: maybeInvertPolicyOutcome(false, policy.invert)
977
- };
978
- }
979
- }
980
- }
981
- return {
982
- success: maybeInvertPolicyOutcome(true, policy.invert)
983
- };
984
- }
985
- }
986
-
987
- /*
988
- * Copyright (c) 2025.
989
- * Author Peter Placzek (tada5hi)
990
- * For the full copyright and license information,
991
- * view the LICENSE file that was distributed with this source code.
992
- */ function definePolicyWithType(type, data) {
993
- return {
994
- ...data,
995
- type
996
- };
997
- }
998
-
799
+ if (typeof input === "string") {
800
+ if (timeRegex.test(input)) {
801
+ const parts = input.split(":");
802
+ const startHours = Number(parts[0]);
803
+ const startMinutes = Number(parts[1]);
804
+ const startSeconds = parts[2] !== void 0 ? Number(parts[2]) : 0;
805
+ if (Number.isFinite(startHours) && Number.isFinite(startMinutes) && Number.isFinite(startSeconds)) {
806
+ const date = dateRef ? new Date(dateRef) : /* @__PURE__ */ new Date();
807
+ date.setHours(startHours, startMinutes, startSeconds, 0);
808
+ return date;
809
+ }
810
+ }
811
+ return new Date(input);
812
+ }
813
+ if (typeof input === "number") return new Date(input);
814
+ return input;
815
+ }
816
+ var TimePolicyEvaluator = class {
817
+ validator;
818
+ constructor() {
819
+ this.validator = new TimePolicyValidator();
820
+ }
821
+ async evaluate(value, ctx) {
822
+ const policy = await this.validator.run(value);
823
+ let now;
824
+ if (ctx.data.has(BuiltInPolicyType.TIME)) if (ctx.data.isValidated(BuiltInPolicyType.TIME)) now = ctx.data.get(BuiltInPolicyType.TIME);
825
+ else {
826
+ now = toDate(ctx.data.get(BuiltInPolicyType.TIME));
827
+ ctx.data.set(BuiltInPolicyType.TIME, now);
828
+ ctx.data.setValidated(BuiltInPolicyType.TIME);
829
+ }
830
+ else now = /* @__PURE__ */ new Date();
831
+ if (policy.start) {
832
+ const start = normalizeDate(toDate(policy.start, now), now);
833
+ if (now < start) return { success: maybeInvertPolicyOutcome(false, policy.invert) };
834
+ }
835
+ if (policy.end) {
836
+ const end = normalizeDate(toDate(policy.end, now), now);
837
+ if (now > end) return { success: maybeInvertPolicyOutcome(false, policy.invert) };
838
+ }
839
+ if (policy.interval) {
840
+ if (isIntervalForDayOfWeek(policy.interval) && policy.day_of_week) {
841
+ if (now.getDay() !== policy.day_of_week) return { success: maybeInvertPolicyOutcome(false, policy.invert) };
842
+ }
843
+ if (isIntervalForDayOfMonth(policy.interval) && policy.day_of_month) {
844
+ if (now.getDate() !== policy.day_of_month) return { success: maybeInvertPolicyOutcome(false, policy.invert) };
845
+ }
846
+ if (isIntervalForDayOfYear(policy.interval) && policy.day_of_year) {
847
+ const start = new Date(now.getFullYear(), 0, 0);
848
+ const diff = now.getTime() - start.getTime() + (start.getTimezoneOffset() - now.getTimezoneOffset()) * 60 * 1e3;
849
+ if (Math.floor(diff / (1e3 * 60 * 60 * 24)) !== policy.day_of_year) return { success: maybeInvertPolicyOutcome(false, policy.invert) };
850
+ }
851
+ }
852
+ return { success: maybeInvertPolicyOutcome(true, policy.invert) };
853
+ }
854
+ };
855
+ //#endregion
856
+ //#region src/policy/built-in/define.ts
857
+ function definePolicyWithType(type, data) {
858
+ return {
859
+ ...data,
860
+ type
861
+ };
862
+ }
863
+ //#endregion
864
+ //#region src/policy/constants.ts
999
865
  const PolicyDefaultEvaluators = {
1000
- [BuiltInPolicyType.COMPOSITE]: new CompositePolicyEvaluator(),
1001
- [BuiltInPolicyType.ATTRIBUTES]: new AttributesPolicyEvaluator(),
1002
- [BuiltInPolicyType.ATTRIBUTE_NAMES]: new AttributeNamesPolicyEvaluator(),
1003
- [BuiltInPolicyType.DATE]: new DatePolicyEvaluator(),
1004
- [BuiltInPolicyType.IDENTITY]: new IdentityPolicyEvaluator(),
1005
- [BuiltInPolicyType.PERMISSION_BINDING]: new PermissionBindingPolicyEvaluator(),
1006
- [BuiltInPolicyType.REALM_MATCH]: new RealmMatchPolicyEvaluator(),
1007
- [BuiltInPolicyType.TIME]: new TimePolicyEvaluator()
866
+ [BuiltInPolicyType.COMPOSITE]: new CompositePolicyEvaluator(),
867
+ [BuiltInPolicyType.ATTRIBUTES]: new AttributesPolicyEvaluator(),
868
+ [BuiltInPolicyType.ATTRIBUTE_NAMES]: new AttributeNamesPolicyEvaluator(),
869
+ [BuiltInPolicyType.DATE]: new DatePolicyEvaluator(),
870
+ [BuiltInPolicyType.IDENTITY]: new IdentityPolicyEvaluator(),
871
+ [BuiltInPolicyType.PERMISSION_BINDING]: new PermissionBindingPolicyEvaluator(),
872
+ [BuiltInPolicyType.REALM_MATCH]: new RealmMatchPolicyEvaluator(),
873
+ [BuiltInPolicyType.TIME]: new TimePolicyEvaluator()
1008
874
  };
875
+ //#endregion
876
+ //#region src/permission/evaluator/module.ts
877
+ var PermissionEvaluator = class {
878
+ provider;
879
+ policyEngine;
880
+ clientId;
881
+ realmId;
882
+ constructor(options) {
883
+ this.provider = options.provider;
884
+ this.clientId = options.clientId || null;
885
+ this.realmId = options.realmId || null;
886
+ if (options.policyEngine) this.policyEngine = options.policyEngine;
887
+ else this.policyEngine = new PolicyEngine(PolicyDefaultEvaluators);
888
+ }
889
+ async findOne(input, overrides = {}) {
890
+ return this.provider.findOne({
891
+ name: input,
892
+ clientId: overrides.clientId ?? this.clientId,
893
+ realmId: overrides.realmId ?? this.realmId
894
+ });
895
+ }
896
+ async evaluate(ctx) {
897
+ if (!Array.isArray(ctx.name)) {
898
+ await this.evaluate({
899
+ ...ctx,
900
+ name: [ctx.name]
901
+ });
902
+ return;
903
+ }
904
+ const { options = {} } = ctx;
905
+ const decisionStrategy = options.decisionStrategy ?? DecisionStrategy.UNANIMOUS;
906
+ const issues = [];
907
+ let count = 0;
908
+ const dataBase = ctx.input || new PolicyData();
909
+ for (const name of ctx.name) {
910
+ const binding = await this.findOne(name, {
911
+ realmId: ctx.realmId,
912
+ clientId: ctx.clientId
913
+ });
914
+ if (!binding) {
915
+ issues.push(defineIssueItem({
916
+ code: ErrorCode.PERMISSION_NOT_FOUND,
917
+ message: `The ${name} permission could not be resolved`,
918
+ path: [name]
919
+ }));
920
+ if (decisionStrategy === DecisionStrategy.UNANIMOUS) {
921
+ const error = PermissionError.evaluationFailed(ctx.name);
922
+ error.addIssues(issues);
923
+ throw error;
924
+ }
925
+ continue;
926
+ }
927
+ const policies = binding.policies ?? [];
928
+ if (policies.length === 0) {
929
+ if (decisionStrategy === DecisionStrategy.AFFIRMATIVE) return;
930
+ count++;
931
+ continue;
932
+ }
933
+ const data = dataBase.clone();
934
+ data.set(BuiltInPolicyType.PERMISSION_BINDING, binding);
935
+ const policyDecisionStrategy = binding.permission.decision_strategy ?? DecisionStrategy.UNANIMOUS;
936
+ const compositePolicy = {
937
+ type: BuiltInPolicyType.COMPOSITE,
938
+ decision_strategy: policyDecisionStrategy,
939
+ children: policies
940
+ };
941
+ const evaluationResult = await this.policyEngine.evaluate(compositePolicy, definePolicyEvaluationContext({
942
+ include: options.policiesIncluded,
943
+ exclude: options.policiesExcluded,
944
+ data
945
+ }));
946
+ if (evaluationResult.success) {
947
+ if (decisionStrategy === DecisionStrategy.AFFIRMATIVE) return;
948
+ count++;
949
+ } else {
950
+ issues.push(definePolicyIssueGroup({
951
+ code: ErrorCode.PERMISSION_EVALUATION_FAILED,
952
+ issues: evaluationResult.issues || [],
953
+ message: `The ${binding.permission.name} permissions policy evaluation failed`,
954
+ path: [binding.permission.name]
955
+ }));
956
+ if (decisionStrategy === DecisionStrategy.UNANIMOUS) {
957
+ const error = PermissionError.evaluationFailed(binding.permission.name);
958
+ error.addIssues(issues);
959
+ throw error;
960
+ }
961
+ count--;
962
+ }
963
+ }
964
+ if (count > 0) return;
965
+ if (issues.length === 0) throw PermissionError.deniedAll(ctx.name);
966
+ else {
967
+ const error = PermissionError.evaluationFailed(ctx.name);
968
+ error.addIssues(issues);
969
+ throw error;
970
+ }
971
+ }
972
+ async evaluateOneOf(ctx) {
973
+ return this.evaluate({
974
+ ...ctx,
975
+ options: {
976
+ ...ctx.options || {},
977
+ decisionStrategy: DecisionStrategy.AFFIRMATIVE
978
+ }
979
+ });
980
+ }
981
+ async preEvaluate(ctx) {
982
+ return this.evaluate({
983
+ ...ctx,
984
+ options: {
985
+ ...ctx.options || {},
986
+ policiesExcluded: [
987
+ BuiltInPolicyType.ATTRIBUTES,
988
+ BuiltInPolicyType.ATTRIBUTE_NAMES,
989
+ BuiltInPolicyType.REALM_MATCH
990
+ ]
991
+ }
992
+ });
993
+ }
994
+ async preEvaluateOneOf(ctx) {
995
+ return this.preEvaluate({
996
+ ...ctx,
997
+ options: {
998
+ ...ctx.options || {},
999
+ decisionStrategy: DecisionStrategy.AFFIRMATIVE
1000
+ }
1001
+ });
1002
+ }
1003
+ };
1004
+ //#endregion
1005
+ export { AttributeNamesPolicyEvaluator, AttributeNamesPolicyValidator, AttributesPolicyEvaluator, AttributesPolicyValidator, BuiltInPolicyType, CompositePolicyEvaluator, CompositePolicyValidator, DatePolicyEvaluator, DatePolicyValidator, DecisionStrategy, IdentityPolicyEvaluator, IdentityPolicyValidator, PermissionBindingPolicyEvaluator, PermissionBindingPolicyValidator, PermissionError, PermissionEvaluator, PermissionMemoryProvider, PolicyData, PolicyDefaultEvaluators, PolicyEngine, PolicyError, PolicyIssueCode, PolicyIssueSeverity, RealmMatchPolicyEvaluator, RealmMatchPolicyValidator, SystemPolicyName, TimePolicyEvaluator, TimePolicyInterval, TimePolicyValidator, buildPermissionKey, defineAttributesPolicy, definePolicyEvaluationContext, definePolicyIssueGroup, definePolicyIssueItem, definePolicyWithType, isCompositePolicy, isIntervalForDayOfMonth, isIntervalForDayOfWeek, isIntervalForDayOfYear, isPermissionPolicyBindingEqual, maybeInvertPolicyOutcome, mergePermissionPolicyBindings };
1009
1006
 
1010
- class PermissionEvaluator {
1011
- provider;
1012
- policyEngine;
1013
- clientId;
1014
- realmId;
1015
- // ----------------------------------------------
1016
- constructor(options = {}){
1017
- if (options.provider) {
1018
- this.provider = options.provider;
1019
- } else {
1020
- this.provider = new PermissionMemoryProvider();
1021
- }
1022
- if (typeof options.clientId !== 'undefined') {
1023
- this.clientId = options.clientId;
1024
- }
1025
- if (typeof options.realmId !== 'undefined') {
1026
- this.realmId = options.realmId;
1027
- }
1028
- if (options.policyEngine) {
1029
- this.policyEngine = options.policyEngine;
1030
- } else {
1031
- this.policyEngine = new PolicyEngine(PolicyDefaultEvaluators);
1032
- }
1033
- }
1034
- // ----------------------------------------------
1035
- async findOne(input, overrides) {
1036
- const options = {
1037
- name: input
1038
- };
1039
- if (typeof overrides?.clientId !== 'undefined') {
1040
- options.clientId = overrides.clientId;
1041
- } else if (typeof this.clientId !== 'undefined') {
1042
- options.clientId = this.clientId;
1043
- }
1044
- if (typeof overrides?.realmId !== 'undefined') {
1045
- options.realmId = overrides.realmId;
1046
- } else if (typeof this.realmId !== 'undefined') {
1047
- options.realmId = this.realmId;
1048
- }
1049
- return this.provider.findOne(options);
1050
- }
1051
- // ----------------------------------------------
1052
- async evaluate(ctx) {
1053
- if (!Array.isArray(ctx.name)) {
1054
- await this.evaluate({
1055
- ...ctx,
1056
- name: [
1057
- ctx.name
1058
- ]
1059
- });
1060
- return;
1061
- }
1062
- const { options = {} } = ctx;
1063
- const decisionStrategy = options.decisionStrategy ?? DecisionStrategy.UNANIMOUS;
1064
- const issues = [];
1065
- let count = 0;
1066
- const dataBase = ctx.input || new PolicyData();
1067
- for(let i = 0; i < ctx.name.length; i++){
1068
- const binding = await this.findOne(ctx.name[i], {
1069
- realmId: ctx.realmId,
1070
- clientId: ctx.clientId
1071
- });
1072
- if (!binding) {
1073
- issues.push(defineIssueItem({
1074
- code: ErrorCode.PERMISSION_NOT_FOUND,
1075
- message: `The ${ctx.name[i]} permission could not be resolved`,
1076
- path: [
1077
- ctx.name[i]
1078
- ]
1079
- }));
1080
- if (decisionStrategy === DecisionStrategy.UNANIMOUS) {
1081
- const error = PermissionError.evaluationFailed(ctx.name);
1082
- error.addIssues(issues);
1083
- throw error;
1084
- }
1085
- continue;
1086
- }
1087
- const policies = binding.policies ?? [];
1088
- if (policies.length === 0) {
1089
- if (decisionStrategy === DecisionStrategy.AFFIRMATIVE) {
1090
- return;
1091
- }
1092
- count++;
1093
- continue;
1094
- }
1095
- const data = dataBase.clone();
1096
- data.set(BuiltInPolicyType.PERMISSION_BINDING, binding);
1097
- const policyDecisionStrategy = binding.permission.decision_strategy ?? DecisionStrategy.UNANIMOUS;
1098
- const compositePolicy = {
1099
- type: BuiltInPolicyType.COMPOSITE,
1100
- decision_strategy: policyDecisionStrategy,
1101
- children: policies
1102
- };
1103
- const evaluationResult = await this.policyEngine.evaluate(compositePolicy, definePolicyEvaluationContext({
1104
- include: options.policiesIncluded,
1105
- exclude: options.policiesExcluded,
1106
- data
1107
- }));
1108
- if (evaluationResult.success) {
1109
- if (decisionStrategy === DecisionStrategy.AFFIRMATIVE) {
1110
- return;
1111
- }
1112
- count++;
1113
- } else {
1114
- issues.push(definePolicyIssueGroup({
1115
- code: ErrorCode.PERMISSION_EVALUATION_FAILED,
1116
- issues: evaluationResult.issues || [],
1117
- message: `The ${binding.permission.name} permissions policy evaluation failed`,
1118
- path: [
1119
- binding.permission.name
1120
- ]
1121
- }));
1122
- if (decisionStrategy === DecisionStrategy.UNANIMOUS) {
1123
- const error = PermissionError.evaluationFailed(binding.permission.name);
1124
- error.addIssues(issues);
1125
- throw error;
1126
- }
1127
- count--;
1128
- }
1129
- }
1130
- if (count > 0) {
1131
- return;
1132
- }
1133
- if (issues.length === 0) {
1134
- throw PermissionError.deniedAll(ctx.name);
1135
- } else {
1136
- const error = PermissionError.evaluationFailed(ctx.name);
1137
- error.addIssues(issues);
1138
- throw error;
1139
- }
1140
- }
1141
- async evaluateOneOf(ctx) {
1142
- return this.evaluate({
1143
- ...ctx,
1144
- options: {
1145
- ...ctx.options || {},
1146
- decisionStrategy: DecisionStrategy.AFFIRMATIVE
1147
- }
1148
- });
1149
- }
1150
- // ----------------------------------------------
1151
- async preEvaluate(ctx) {
1152
- return this.evaluate({
1153
- ...ctx,
1154
- options: {
1155
- ...ctx.options || {},
1156
- policiesExcluded: [
1157
- BuiltInPolicyType.ATTRIBUTES,
1158
- BuiltInPolicyType.ATTRIBUTE_NAMES,
1159
- BuiltInPolicyType.REALM_MATCH
1160
- ]
1161
- }
1162
- });
1163
- }
1164
- async preEvaluateOneOf(ctx) {
1165
- return this.preEvaluate({
1166
- ...ctx,
1167
- options: {
1168
- ...ctx.options || {},
1169
- decisionStrategy: DecisionStrategy.AFFIRMATIVE
1170
- }
1171
- });
1172
- }
1173
- }
1174
-
1175
- export { AttributeNamesPolicyEvaluator, AttributeNamesPolicyValidator, AttributesPolicyEvaluator, AttributesPolicyValidator, BuiltInPolicyType, CompositePolicyEvaluator, CompositePolicyValidator, DatePolicyEvaluator, DatePolicyValidator, IdentityPolicyEvaluator, IdentityPolicyValidator, PermissionBindingPolicyEvaluator, PermissionBindingPolicyValidator, PermissionError, PermissionEvaluator, PermissionMemoryProvider, PolicyData, PolicyDefaultEvaluators, PolicyEngine, PolicyError, PolicyIssueCode, PolicyIssueSeverity, RealmMatchPolicyEvaluator, RealmMatchPolicyValidator, SystemPolicyName, TimePolicyEvaluator, TimePolicyInterval, TimePolicyValidator, defineAttributesPolicy, definePolicyEvaluationContext, definePolicyIssueGroup, definePolicyIssueItem, definePolicyWithType, isCompositePolicy, isIntervalForDayOfMonth, isIntervalForDayOfWeek, isIntervalForDayOfYear, maybeInvertPolicyOutcome };
1176
- //# sourceMappingURL=index.mjs.map
1007
+ //# sourceMappingURL=index.mjs.map