@vertesia/studio-utils 1.4.0-dev.20260615.051508Z → 1.4.0
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.
- package/lib/conditions/index.d.ts +2 -0
- package/lib/conditions/index.d.ts.map +1 -0
- package/lib/conditions/index.js +2 -0
- package/lib/conditions/index.js.map +1 -0
- package/lib/conditions/match.d.ts +54 -0
- package/lib/conditions/match.d.ts.map +1 -0
- package/lib/conditions/match.js +156 -0
- package/lib/conditions/match.js.map +1 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/lib/logger.d.ts +6 -0
- package/lib/logger.d.ts.map +1 -0
- package/lib/logger.js +15 -0
- package/lib/logger.js.map +1 -0
- package/lib/roles/classes.d.ts +59 -0
- package/lib/roles/classes.d.ts.map +1 -0
- package/lib/roles/classes.js +60 -0
- package/lib/roles/classes.js.map +1 -0
- package/lib/roles/content.d.ts +13 -0
- package/lib/roles/content.d.ts.map +1 -0
- package/lib/roles/content.js +39 -0
- package/lib/roles/content.js.map +1 -0
- package/lib/roles/index.d.ts +37 -0
- package/lib/roles/index.d.ts.map +1 -0
- package/lib/roles/index.js +87 -0
- package/lib/roles/index.js.map +1 -0
- package/lib/roles/system.d.ts +3 -0
- package/lib/roles/system.d.ts.map +1 -0
- package/lib/roles/system.js +187 -0
- package/lib/roles/system.js.map +1 -0
- package/lib/vertesia-studio-utils.js +1 -1
- package/lib/vertesia-studio-utils.js.map +1 -1
- package/package.json +26 -9
- package/src/conditions/index.ts +1 -0
- package/src/conditions/match.test.ts +75 -0
- package/src/conditions/match.ts +146 -0
- package/src/index.ts +1 -0
- package/src/logger.ts +25 -0
- package/src/roles/classes.ts +78 -0
- package/src/roles/content.ts +46 -0
- package/src/roles/index.test.ts +206 -0
- package/src/roles/index.ts +96 -0
- package/src/roles/system.ts +204 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/conditions/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/conditions/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { PropertyConditions } from '@vertesia/common';
|
|
2
|
+
/**
|
|
3
|
+
* Resolve a property path against a context object.
|
|
4
|
+
*
|
|
5
|
+
* Supports:
|
|
6
|
+
* - `clearance` → obj.clearance
|
|
7
|
+
* - `email` → obj.email
|
|
8
|
+
* - `properties.department` → obj.properties.department (one nested level under `properties`)
|
|
9
|
+
*
|
|
10
|
+
* Returns `undefined` if any segment is missing or non-traversable.
|
|
11
|
+
*/
|
|
12
|
+
export declare function resolvePath(obj: Record<string, unknown>, path: string): unknown;
|
|
13
|
+
/**
|
|
14
|
+
* Match a wildcard pattern against a string value.
|
|
15
|
+
*
|
|
16
|
+
* Supports `*` as wildcard:
|
|
17
|
+
* - `"*@domain.com"` — ends with
|
|
18
|
+
* - `"bogdan.*"` — starts with
|
|
19
|
+
* - `"bogdan+*@vertesia.com"` — contains
|
|
20
|
+
* - `"*"` — match all
|
|
21
|
+
*
|
|
22
|
+
* Case-insensitive. Non-string `value` always returns `false`.
|
|
23
|
+
*/
|
|
24
|
+
export declare function matchLike(value: unknown, pattern: string): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Evaluate a PropertyConditions object against a set of properties (JS-side, in-memory).
|
|
27
|
+
*
|
|
28
|
+
* Supports the MongoDB query syntax subset shared across token-server (principal property
|
|
29
|
+
* matching at JWT-mint time) and zeno-server (write-path ABAC permission checks against an
|
|
30
|
+
* in-memory document):
|
|
31
|
+
*
|
|
32
|
+
* - Direct value match (`{ field: literal }`)
|
|
33
|
+
* - `$eq`, `$ne`, `$gt`, `$gte`, `$lt`, `$lte`
|
|
34
|
+
* - `$in`, `$nin` (against array `expected`)
|
|
35
|
+
* - `$exists` (boolean)
|
|
36
|
+
* - `$empty` (boolean) — true for undefined/null/empty-string/empty-array
|
|
37
|
+
* - `$like` (wildcard string, see {@link matchLike})
|
|
38
|
+
*
|
|
39
|
+
* All field-level conditions are AND'd (every field must match). Within a single field, all
|
|
40
|
+
* operators are AND'd.
|
|
41
|
+
*
|
|
42
|
+
* Mirrors the Mongo-side filter built by `conditionsToMongoFilter` (zeno-server utils.ts) and
|
|
43
|
+
* the ES-side filter built by `conditionsToEsQuery`. Use this when conditions need to be
|
|
44
|
+
* evaluated against a single hydrated document instead of pushed down as a query.
|
|
45
|
+
*
|
|
46
|
+
* Unknown operators emit a warning via the studio-utils logger and return false — surfacing
|
|
47
|
+
* misconfiguration loudly without breaking the surrounding token mint or permission check.
|
|
48
|
+
*
|
|
49
|
+
* `$principal.X` substitutions in conditions are expected to have already been resolved at
|
|
50
|
+
* JWT-mint time by `resolveConditions` in token-server; values reaching this function are
|
|
51
|
+
* concrete.
|
|
52
|
+
*/
|
|
53
|
+
export declare function matchConditions(conditions: PropertyConditions, properties: Record<string, unknown>): boolean;
|
|
54
|
+
//# sourceMappingURL=match.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"match.d.ts","sourceRoot":"","sources":["../../src/conditions/match.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAG3D;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAQ/E;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAKlE;AAmBD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CA2D5G"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { getStudioUtilsLogger } from '../logger.js';
|
|
2
|
+
/**
|
|
3
|
+
* Resolve a property path against a context object.
|
|
4
|
+
*
|
|
5
|
+
* Supports:
|
|
6
|
+
* - `clearance` → obj.clearance
|
|
7
|
+
* - `email` → obj.email
|
|
8
|
+
* - `properties.department` → obj.properties.department (one nested level under `properties`)
|
|
9
|
+
*
|
|
10
|
+
* Returns `undefined` if any segment is missing or non-traversable.
|
|
11
|
+
*/
|
|
12
|
+
export function resolvePath(obj, path) {
|
|
13
|
+
if (path.startsWith('properties.')) {
|
|
14
|
+
const properties = obj.properties;
|
|
15
|
+
return properties && typeof properties === 'object'
|
|
16
|
+
? properties[path.slice(11)]
|
|
17
|
+
: undefined;
|
|
18
|
+
}
|
|
19
|
+
return obj[path];
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Match a wildcard pattern against a string value.
|
|
23
|
+
*
|
|
24
|
+
* Supports `*` as wildcard:
|
|
25
|
+
* - `"*@domain.com"` — ends with
|
|
26
|
+
* - `"bogdan.*"` — starts with
|
|
27
|
+
* - `"bogdan+*@vertesia.com"` — contains
|
|
28
|
+
* - `"*"` — match all
|
|
29
|
+
*
|
|
30
|
+
* Case-insensitive. Non-string `value` always returns `false`.
|
|
31
|
+
*/
|
|
32
|
+
export function matchLike(value, pattern) {
|
|
33
|
+
if (typeof value !== 'string')
|
|
34
|
+
return false;
|
|
35
|
+
// Convert wildcard pattern to regex: escape regex chars except *, then replace * with .*
|
|
36
|
+
const escaped = pattern.replace(/[.+?^${}()|[\]\\]/g, '\\$&').replace(/\*/g, '.*');
|
|
37
|
+
return new RegExp(`^${escaped}$`, 'i').test(value);
|
|
38
|
+
}
|
|
39
|
+
function compareOrdered(value, expected, op) {
|
|
40
|
+
if (typeof value !== 'number' && typeof value !== 'string')
|
|
41
|
+
return false;
|
|
42
|
+
if (typeof value !== typeof expected)
|
|
43
|
+
return false;
|
|
44
|
+
const left = value;
|
|
45
|
+
const right = expected;
|
|
46
|
+
switch (op) {
|
|
47
|
+
case '$gt':
|
|
48
|
+
return left > right;
|
|
49
|
+
case '$gte':
|
|
50
|
+
return left >= right;
|
|
51
|
+
case '$lt':
|
|
52
|
+
return left < right;
|
|
53
|
+
case '$lte':
|
|
54
|
+
return left <= right;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Evaluate a PropertyConditions object against a set of properties (JS-side, in-memory).
|
|
59
|
+
*
|
|
60
|
+
* Supports the MongoDB query syntax subset shared across token-server (principal property
|
|
61
|
+
* matching at JWT-mint time) and zeno-server (write-path ABAC permission checks against an
|
|
62
|
+
* in-memory document):
|
|
63
|
+
*
|
|
64
|
+
* - Direct value match (`{ field: literal }`)
|
|
65
|
+
* - `$eq`, `$ne`, `$gt`, `$gte`, `$lt`, `$lte`
|
|
66
|
+
* - `$in`, `$nin` (against array `expected`)
|
|
67
|
+
* - `$exists` (boolean)
|
|
68
|
+
* - `$empty` (boolean) — true for undefined/null/empty-string/empty-array
|
|
69
|
+
* - `$like` (wildcard string, see {@link matchLike})
|
|
70
|
+
*
|
|
71
|
+
* All field-level conditions are AND'd (every field must match). Within a single field, all
|
|
72
|
+
* operators are AND'd.
|
|
73
|
+
*
|
|
74
|
+
* Mirrors the Mongo-side filter built by `conditionsToMongoFilter` (zeno-server utils.ts) and
|
|
75
|
+
* the ES-side filter built by `conditionsToEsQuery`. Use this when conditions need to be
|
|
76
|
+
* evaluated against a single hydrated document instead of pushed down as a query.
|
|
77
|
+
*
|
|
78
|
+
* Unknown operators emit a warning via the studio-utils logger and return false — surfacing
|
|
79
|
+
* misconfiguration loudly without breaking the surrounding token mint or permission check.
|
|
80
|
+
*
|
|
81
|
+
* `$principal.X` substitutions in conditions are expected to have already been resolved at
|
|
82
|
+
* JWT-mint time by `resolveConditions` in token-server; values reaching this function are
|
|
83
|
+
* concrete.
|
|
84
|
+
*/
|
|
85
|
+
export function matchConditions(conditions, properties) {
|
|
86
|
+
for (const [key, condition] of Object.entries(conditions)) {
|
|
87
|
+
const value = resolvePath(properties, key);
|
|
88
|
+
if (condition === null || condition === undefined || typeof condition !== 'object') {
|
|
89
|
+
// Direct value match
|
|
90
|
+
if (value !== condition)
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
// Operator object
|
|
95
|
+
const ops = condition;
|
|
96
|
+
for (const [op, expected] of Object.entries(ops)) {
|
|
97
|
+
switch (op) {
|
|
98
|
+
case '$eq':
|
|
99
|
+
if (value !== expected)
|
|
100
|
+
return false;
|
|
101
|
+
break;
|
|
102
|
+
case '$ne':
|
|
103
|
+
if (value === expected)
|
|
104
|
+
return false;
|
|
105
|
+
break;
|
|
106
|
+
case '$gt':
|
|
107
|
+
if (!compareOrdered(value, expected, '$gt'))
|
|
108
|
+
return false;
|
|
109
|
+
break;
|
|
110
|
+
case '$gte':
|
|
111
|
+
if (!compareOrdered(value, expected, '$gte'))
|
|
112
|
+
return false;
|
|
113
|
+
break;
|
|
114
|
+
case '$lt':
|
|
115
|
+
if (!compareOrdered(value, expected, '$lt'))
|
|
116
|
+
return false;
|
|
117
|
+
break;
|
|
118
|
+
case '$lte':
|
|
119
|
+
if (!compareOrdered(value, expected, '$lte'))
|
|
120
|
+
return false;
|
|
121
|
+
break;
|
|
122
|
+
case '$in':
|
|
123
|
+
if (!Array.isArray(expected) || !expected.includes(value))
|
|
124
|
+
return false;
|
|
125
|
+
break;
|
|
126
|
+
case '$nin':
|
|
127
|
+
if (Array.isArray(expected) && expected.includes(value))
|
|
128
|
+
return false;
|
|
129
|
+
break;
|
|
130
|
+
case '$exists':
|
|
131
|
+
if (typeof expected !== 'boolean' || (value !== undefined) !== expected)
|
|
132
|
+
return false;
|
|
133
|
+
break;
|
|
134
|
+
case '$empty': {
|
|
135
|
+
const isEmpty = value === undefined ||
|
|
136
|
+
value === null ||
|
|
137
|
+
value === '' ||
|
|
138
|
+
(Array.isArray(value) && value.length === 0);
|
|
139
|
+
if (typeof expected !== 'boolean' || isEmpty !== expected)
|
|
140
|
+
return false;
|
|
141
|
+
break;
|
|
142
|
+
}
|
|
143
|
+
case '$like':
|
|
144
|
+
if (typeof expected !== 'string' || !matchLike(value, expected))
|
|
145
|
+
return false;
|
|
146
|
+
break;
|
|
147
|
+
default:
|
|
148
|
+
getStudioUtilsLogger().warn({ op, key }, 'Unknown operator in PropertyConditions');
|
|
149
|
+
return false;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return true;
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=match.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"match.js","sourceRoot":"","sources":["../../src/conditions/match.ts"],"names":[],"mappings":"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"}
|
package/lib/index.d.ts
CHANGED
|
@@ -2,4 +2,5 @@ export { extractHandlebarsVariables } from './prompts/extract-vars.js';
|
|
|
2
2
|
export { generateMockData } from './prompts/mock-data.js';
|
|
3
3
|
export { executeHandlebars, executeJST, renderPrompt, renderSegments, renderSegmentsOrErrors, renderTemplate, type SegmentPreview, } from './prompts/render.js';
|
|
4
4
|
export { type PromptValidationInput, type PromptValidationIssue, type PromptValidationIssueSeverity, type PromptValidationIssueType, type PromptValidationResult, validatePrompt, } from './prompts/validate.js';
|
|
5
|
+
export * from './roles/index.js';
|
|
5
6
|
//# sourceMappingURL=index.d.ts.map
|
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AACvE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EACH,iBAAiB,EACjB,UAAU,EACV,YAAY,EACZ,cAAc,EACd,sBAAsB,EACtB,cAAc,EACd,KAAK,cAAc,GACtB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACH,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,EAC1B,KAAK,6BAA6B,EAClC,KAAK,yBAAyB,EAC9B,KAAK,sBAAsB,EAC3B,cAAc,GACjB,MAAM,uBAAuB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AACvE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EACH,iBAAiB,EACjB,UAAU,EACV,YAAY,EACZ,cAAc,EACd,sBAAsB,EACtB,cAAc,EACd,KAAK,cAAc,GACtB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACH,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,EAC1B,KAAK,6BAA6B,EAClC,KAAK,yBAAyB,EAC9B,KAAK,sBAAsB,EAC3B,cAAc,GACjB,MAAM,uBAAuB,CAAC;AAC/B,cAAc,kBAAkB,CAAC"}
|
package/lib/index.js
CHANGED
|
@@ -2,4 +2,5 @@ export { extractHandlebarsVariables } from './prompts/extract-vars.js';
|
|
|
2
2
|
export { generateMockData } from './prompts/mock-data.js';
|
|
3
3
|
export { executeHandlebars, executeJST, renderPrompt, renderSegments, renderSegmentsOrErrors, renderTemplate, } from './prompts/render.js';
|
|
4
4
|
export { validatePrompt, } from './prompts/validate.js';
|
|
5
|
+
export * from './roles/index.js';
|
|
5
6
|
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AACvE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EACH,iBAAiB,EACjB,UAAU,EACV,YAAY,EACZ,cAAc,EACd,sBAAsB,EACtB,cAAc,GAEjB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAMH,cAAc,GACjB,MAAM,uBAAuB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AACvE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EACH,iBAAiB,EACjB,UAAU,EACV,YAAY,EACZ,cAAc,EACd,sBAAsB,EACtB,cAAc,GAEjB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAMH,cAAc,GACjB,MAAM,uBAAuB,CAAC;AAC/B,cAAc,kBAAkB,CAAC"}
|
package/lib/logger.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export interface StudioUtilsLogger {
|
|
2
|
+
warn(details: Record<string, unknown>, message: string): void;
|
|
3
|
+
}
|
|
4
|
+
export declare function getStudioUtilsLogger(): StudioUtilsLogger;
|
|
5
|
+
export declare function installStudioUtilsLogger(customLogger: StudioUtilsLogger): StudioUtilsLogger;
|
|
6
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,iBAAiB;IAC9B,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACjE;AAcD,wBAAgB,oBAAoB,IAAI,iBAAiB,CAExD;AAED,wBAAgB,wBAAwB,CAAC,YAAY,EAAE,iBAAiB,GAAG,iBAAiB,CAI3F"}
|
package/lib/logger.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const consoleLogger = {
|
|
2
|
+
warn: (details, message) => {
|
|
3
|
+
console.warn(message, details);
|
|
4
|
+
},
|
|
5
|
+
};
|
|
6
|
+
let logger = consoleLogger;
|
|
7
|
+
export function getStudioUtilsLogger() {
|
|
8
|
+
return logger;
|
|
9
|
+
}
|
|
10
|
+
export function installStudioUtilsLogger(customLogger) {
|
|
11
|
+
const previousLogger = logger;
|
|
12
|
+
logger = customLogger;
|
|
13
|
+
return previousLogger;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAQA,MAAM,aAAa,GAAsB;IACrC,IAAI,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE;QACvB,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACnC,CAAC;CACJ,CAAC;AAEF,IAAI,MAAM,GAAsB,aAAa,CAAC;AAE9C,MAAM,UAAU,oBAAoB;IAChC,OAAO,MAAM,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,YAA+B;IACpE,MAAM,cAAc,GAAG,MAAM,CAAC;IAC9B,MAAM,GAAG,YAAY,CAAC;IACtB,OAAO,cAAc,CAAC;AAC1B,CAAC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { AbacScope, Permission, RoleDomain } from '@vertesia/common';
|
|
2
|
+
/**
|
|
3
|
+
* Class hierarchy and registry-bound interface for the role system. These
|
|
4
|
+
* are LOGIC — they have runtime behavior (constructors, instance methods,
|
|
5
|
+
* subclass dispatch via `instanceof`). They live in `@vertesia/studio-utils`
|
|
6
|
+
* (not common) per the package-layering contract: only types stay in common.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* A role: a named bundle of permissions that ACEs reference by name.
|
|
10
|
+
*
|
|
11
|
+
* Generic over the permission type so subclasses can tighten it:
|
|
12
|
+
* - **System roles** declare `extends Role<Permission>` — construction time
|
|
13
|
+
* type-checks against the central `Permission` enum.
|
|
14
|
+
* - **ABAC roles** (`AbacRole`) declare `extends Role<string>` — permissions
|
|
15
|
+
* are bare verbs (`'read'`, `'write'`, `'delete'`, future domain-specific
|
|
16
|
+
* verbs) consumed by the JWT generator to form `{scope}:{verb}` keys in
|
|
17
|
+
* `content_security`.
|
|
18
|
+
*
|
|
19
|
+
* The registry stores `Role` (defaulting to `Role<string>`) — the loose type
|
|
20
|
+
* is the lowest common denominator. Tight typing is only enforced at
|
|
21
|
+
* declaration sites of the role subclasses.
|
|
22
|
+
*/
|
|
23
|
+
export declare class Role<PermissionType extends string = string> {
|
|
24
|
+
name: string;
|
|
25
|
+
domain: RoleDomain;
|
|
26
|
+
permissions: Set<PermissionType>;
|
|
27
|
+
constructor(name: string, permissions: PermissionType[], domain: RoleDomain);
|
|
28
|
+
hasPermission(permission: PermissionType): boolean;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Base class for built-in system roles. Hardcodes `domain: 'system'` and
|
|
32
|
+
* specializes `Role<Permission>` so subclasses get compile-time type-checking
|
|
33
|
+
* against the central `Permission` enum at construction.
|
|
34
|
+
*/
|
|
35
|
+
export declare class SystemRole extends Role<Permission> {
|
|
36
|
+
constructor(name: string, permissions: Permission[]);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* A role usable in ContentSet ACEs. Adds `applicableScopes` — the kinds of
|
|
40
|
+
* objects the role can be applied to at the ABAC scope level. Inherits
|
|
41
|
+
* `Role<string>` because ABAC verbs aren't constrained to the central
|
|
42
|
+
* `Permission` enum.
|
|
43
|
+
*
|
|
44
|
+
* The IAM UI filters via `listAbacRolesForScope` which checks `instanceof AbacRole`.
|
|
45
|
+
*/
|
|
46
|
+
export declare class AbacRole extends Role<string> {
|
|
47
|
+
applicableScopes: readonly AbacScope[];
|
|
48
|
+
constructor(name: string, permissions: string[], domain: RoleDomain, applicableScopes: readonly AbacScope[]);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* A logical bucket of roles owned by a single domain. The registry iterates
|
|
52
|
+
* partitions in registration order — first match wins. The `system` partition
|
|
53
|
+
* is registered first so domain partitions cannot shadow built-in system roles.
|
|
54
|
+
*/
|
|
55
|
+
export interface RolePartition {
|
|
56
|
+
domain: RoleDomain;
|
|
57
|
+
roles: Map<string, Role>;
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=classes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classes.d.ts","sourceRoot":"","sources":["../../src/roles/classes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE1E;;;;;GAKG;AAEH;;;;;;;;;;;;;;GAcG;AACH,qBAAa,IAAI,CAAC,cAAc,SAAS,MAAM,GAAG,MAAM;IAGzC,IAAI,EAAE,MAAM;IAEZ,MAAM,EAAE,UAAU;IAJ7B,WAAW,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC;gBAEtB,IAAI,EAAE,MAAM,EACnB,WAAW,EAAE,cAAc,EAAE,EACtB,MAAM,EAAE,UAAU;IAK7B,aAAa,CAAC,UAAU,EAAE,cAAc;CAG3C;AAED;;;;GAIG;AACH,qBAAa,UAAW,SAAQ,IAAI,CAAC,UAAU,CAAC;gBAChC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE;CAGtD;AAED;;;;;;;GAOG;AACH,qBAAa,QAAS,SAAQ,IAAI,CAAC,MAAM,CAAC;IAK3B,gBAAgB,EAAE,SAAS,SAAS,EAAE;gBAH7C,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EAAE,EACrB,MAAM,EAAE,UAAU,EACX,gBAAgB,EAAE,SAAS,SAAS,EAAE;CAIpD;AAED;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC1B,MAAM,EAAE,UAAU,CAAC;IACnB,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;CAC5B"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Class hierarchy and registry-bound interface for the role system. These
|
|
3
|
+
* are LOGIC — they have runtime behavior (constructors, instance methods,
|
|
4
|
+
* subclass dispatch via `instanceof`). They live in `@vertesia/studio-utils`
|
|
5
|
+
* (not common) per the package-layering contract: only types stay in common.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* A role: a named bundle of permissions that ACEs reference by name.
|
|
9
|
+
*
|
|
10
|
+
* Generic over the permission type so subclasses can tighten it:
|
|
11
|
+
* - **System roles** declare `extends Role<Permission>` — construction time
|
|
12
|
+
* type-checks against the central `Permission` enum.
|
|
13
|
+
* - **ABAC roles** (`AbacRole`) declare `extends Role<string>` — permissions
|
|
14
|
+
* are bare verbs (`'read'`, `'write'`, `'delete'`, future domain-specific
|
|
15
|
+
* verbs) consumed by the JWT generator to form `{scope}:{verb}` keys in
|
|
16
|
+
* `content_security`.
|
|
17
|
+
*
|
|
18
|
+
* The registry stores `Role` (defaulting to `Role<string>`) — the loose type
|
|
19
|
+
* is the lowest common denominator. Tight typing is only enforced at
|
|
20
|
+
* declaration sites of the role subclasses.
|
|
21
|
+
*/
|
|
22
|
+
export class Role {
|
|
23
|
+
name;
|
|
24
|
+
domain;
|
|
25
|
+
permissions;
|
|
26
|
+
constructor(name, permissions, domain) {
|
|
27
|
+
this.name = name;
|
|
28
|
+
this.domain = domain;
|
|
29
|
+
this.permissions = new Set(permissions);
|
|
30
|
+
}
|
|
31
|
+
hasPermission(permission) {
|
|
32
|
+
return this.permissions.has(permission);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Base class for built-in system roles. Hardcodes `domain: 'system'` and
|
|
37
|
+
* specializes `Role<Permission>` so subclasses get compile-time type-checking
|
|
38
|
+
* against the central `Permission` enum at construction.
|
|
39
|
+
*/
|
|
40
|
+
export class SystemRole extends Role {
|
|
41
|
+
constructor(name, permissions) {
|
|
42
|
+
super(name, permissions, 'system');
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* A role usable in ContentSet ACEs. Adds `applicableScopes` — the kinds of
|
|
47
|
+
* objects the role can be applied to at the ABAC scope level. Inherits
|
|
48
|
+
* `Role<string>` because ABAC verbs aren't constrained to the central
|
|
49
|
+
* `Permission` enum.
|
|
50
|
+
*
|
|
51
|
+
* The IAM UI filters via `listAbacRolesForScope` which checks `instanceof AbacRole`.
|
|
52
|
+
*/
|
|
53
|
+
export class AbacRole extends Role {
|
|
54
|
+
applicableScopes;
|
|
55
|
+
constructor(name, permissions, domain, applicableScopes) {
|
|
56
|
+
super(name, permissions, domain);
|
|
57
|
+
this.applicableScopes = applicableScopes;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=classes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classes.js","sourceRoot":"","sources":["../../src/roles/classes.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AAEH;;;;;;;;;;;;;;GAcG;AACH,MAAM,OAAO,IAAI;IAGF;IAEA;IAJX,WAAW,CAAsB;IACjC,YACW,IAAY,EACnB,WAA6B,EACtB,MAAkB;QAFlB,SAAI,GAAJ,IAAI,CAAQ;QAEZ,WAAM,GAAN,MAAM,CAAY;QAEzB,IAAI,CAAC,WAAW,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,CAAC;IAC5C,CAAC;IAED,aAAa,CAAC,UAA0B;QACpC,OAAO,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAC5C,CAAC;CACJ;AAED;;;;GAIG;AACH,MAAM,OAAO,UAAW,SAAQ,IAAgB;IAC5C,YAAY,IAAY,EAAE,WAAyB;QAC/C,KAAK,CAAC,IAAI,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC;IACvC,CAAC;CACJ;AAED;;;;;;;GAOG;AACH,MAAM,OAAO,QAAS,SAAQ,IAAY;IAK3B;IAJX,YACI,IAAY,EACZ,WAAqB,EACrB,MAAkB,EACX,gBAAsC;QAE7C,KAAK,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC;QAF1B,qBAAgB,GAAhB,gBAAgB,CAAsB;IAGjD,CAAC;CACJ"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type RolePartition } from './classes.js';
|
|
2
|
+
/**
|
|
3
|
+
* Names of roles owned by the `content` domain. Apply to ContentSet ACEs
|
|
4
|
+
* scoped to either `document` or `collection` — the semantics of "read
|
|
5
|
+
* content" are the same for both kinds.
|
|
6
|
+
*/
|
|
7
|
+
export declare enum ContentRoleNames {
|
|
8
|
+
content_reader = "content_reader",
|
|
9
|
+
content_writer = "content_writer",
|
|
10
|
+
content_manager = "content_manager"
|
|
11
|
+
}
|
|
12
|
+
export declare const contentPartition: RolePartition;
|
|
13
|
+
//# sourceMappingURL=content.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content.d.ts","sourceRoot":"","sources":["../../src/roles/content.ts"],"names":[],"mappings":"AACA,OAAO,EAAuB,KAAK,aAAa,EAAE,MAAM,cAAc,CAAC;AAMvE;;;;GAIG;AACH,oBAAY,gBAAgB;IACxB,cAAc,mBAAmB;IACjC,cAAc,mBAAmB;IACjC,eAAe,oBAAoB;CACtC;AA0BD,eAAO,MAAM,gBAAgB,EAAE,aAG9B,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { AbacRole } from './classes.js';
|
|
2
|
+
const ContentRoleDomain = 'content';
|
|
3
|
+
const APPLICABLE_SCOPES = ['document', 'collection'];
|
|
4
|
+
/**
|
|
5
|
+
* Names of roles owned by the `content` domain. Apply to ContentSet ACEs
|
|
6
|
+
* scoped to either `document` or `collection` — the semantics of "read
|
|
7
|
+
* content" are the same for both kinds.
|
|
8
|
+
*/
|
|
9
|
+
export var ContentRoleNames;
|
|
10
|
+
(function (ContentRoleNames) {
|
|
11
|
+
ContentRoleNames["content_reader"] = "content_reader";
|
|
12
|
+
ContentRoleNames["content_writer"] = "content_writer";
|
|
13
|
+
ContentRoleNames["content_manager"] = "content_manager";
|
|
14
|
+
})(ContentRoleNames || (ContentRoleNames = {}));
|
|
15
|
+
class ContentReaderRole extends AbacRole {
|
|
16
|
+
constructor() {
|
|
17
|
+
super(ContentRoleNames.content_reader, ['read'], ContentRoleDomain, APPLICABLE_SCOPES);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
class ContentWriterRole extends AbacRole {
|
|
21
|
+
constructor() {
|
|
22
|
+
super(ContentRoleNames.content_writer, ['read', 'write'], ContentRoleDomain, APPLICABLE_SCOPES);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
class ContentManagerRole extends AbacRole {
|
|
26
|
+
constructor() {
|
|
27
|
+
super(ContentRoleNames.content_manager, ['read', 'write', 'delete'], ContentRoleDomain, APPLICABLE_SCOPES);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
const contentRoles = {
|
|
31
|
+
[ContentRoleNames.content_reader]: new ContentReaderRole(),
|
|
32
|
+
[ContentRoleNames.content_writer]: new ContentWriterRole(),
|
|
33
|
+
[ContentRoleNames.content_manager]: new ContentManagerRole(),
|
|
34
|
+
};
|
|
35
|
+
export const contentPartition = {
|
|
36
|
+
domain: ContentRoleDomain,
|
|
37
|
+
roles: new Map(Object.entries(contentRoles)),
|
|
38
|
+
};
|
|
39
|
+
//# sourceMappingURL=content.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content.js","sourceRoot":"","sources":["../../src/roles/content.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAiC,MAAM,cAAc,CAAC;AAEvE,MAAM,iBAAiB,GAAe,SAAS,CAAC;AAEhD,MAAM,iBAAiB,GAAyB,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;AAE3E;;;;GAIG;AACH,MAAM,CAAN,IAAY,gBAIX;AAJD,WAAY,gBAAgB;IACxB,qDAAiC,CAAA;IACjC,qDAAiC,CAAA;IACjC,uDAAmC,CAAA;AACvC,CAAC,EAJW,gBAAgB,KAAhB,gBAAgB,QAI3B;AAED,MAAM,iBAAkB,SAAQ,QAAQ;IACpC;QACI,KAAK,CAAC,gBAAgB,CAAC,cAAc,EAAE,CAAC,MAAM,CAAC,EAAE,iBAAiB,EAAE,iBAAiB,CAAC,CAAC;IAC3F,CAAC;CACJ;AAED,MAAM,iBAAkB,SAAQ,QAAQ;IACpC;QACI,KAAK,CAAC,gBAAgB,CAAC,cAAc,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,iBAAiB,EAAE,iBAAiB,CAAC,CAAC;IACpG,CAAC;CACJ;AAED,MAAM,kBAAmB,SAAQ,QAAQ;IACrC;QACI,KAAK,CAAC,gBAAgB,CAAC,eAAe,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,iBAAiB,EAAE,iBAAiB,CAAC,CAAC;IAC/G,CAAC;CACJ;AAED,MAAM,YAAY,GAAmC;IACjD,CAAC,gBAAgB,CAAC,cAAc,CAAC,EAAE,IAAI,iBAAiB,EAAE;IAC1D,CAAC,gBAAgB,CAAC,cAAc,CAAC,EAAE,IAAI,iBAAiB,EAAE;IAC1D,CAAC,gBAAgB,CAAC,eAAe,CAAC,EAAE,IAAI,kBAAkB,EAAE;CAC/D,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAkB;IAC3C,MAAM,EAAE,iBAAiB;IACzB,KAAK,EAAE,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;CAC/C,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { AbacScope, RoleDomain } from '@vertesia/common';
|
|
2
|
+
import { AbacRole, type Role, SystemRole } from './classes.js';
|
|
3
|
+
export { AbacRole, Role, type RolePartition, SystemRole } from './classes.js';
|
|
4
|
+
export { ContentRoleNames } from './content.js';
|
|
5
|
+
/** Look up a role by its name across all registered partitions. */
|
|
6
|
+
export declare function getRoleByName(name: string): Role;
|
|
7
|
+
/** List every role across all partitions, in partition registration order. */
|
|
8
|
+
export declare function listRoles(): Role[];
|
|
9
|
+
/** Roles owned by a specific domain (e.g. `'system'`, `'content'`). */
|
|
10
|
+
export declare function listRolesByDomain(domain: RoleDomain): Role[];
|
|
11
|
+
/**
|
|
12
|
+
* ABAC roles applicable to a given ContentSet scope (e.g. `'document'`,
|
|
13
|
+
* `'collection'`). System roles are excluded — they don't carry scope semantics.
|
|
14
|
+
*/
|
|
15
|
+
export declare function listAbacRolesForScope(scope: AbacScope): AbacRole[];
|
|
16
|
+
/** Shortcut for the system partition: returns only `SystemRole` instances. */
|
|
17
|
+
export declare function listSystemRoles(): SystemRole[];
|
|
18
|
+
/** Names of every registered role across all partitions — suited for mongoose schema enum constraints. */
|
|
19
|
+
export declare function getAllRoleNames(): string[];
|
|
20
|
+
/**
|
|
21
|
+
* Merge the permissions granted by a set of roles into a single array.
|
|
22
|
+
* Intended for the system-role gating path. For ABAC roles, the bare-verb
|
|
23
|
+
* permissions returned here aren't directly meaningful — use the JWT
|
|
24
|
+
* `content_security` pathway instead.
|
|
25
|
+
*/
|
|
26
|
+
export declare function getPermissionsForRoles(roleNames: Iterable<string>): string[];
|
|
27
|
+
/**
|
|
28
|
+
* A list of roles with a unified `hasPermission` check across them.
|
|
29
|
+
*/
|
|
30
|
+
export declare class RoleList {
|
|
31
|
+
readonly roles: Role[];
|
|
32
|
+
private constructor();
|
|
33
|
+
static fromRoleNames(roleNames: string[]): RoleList;
|
|
34
|
+
static fromRoleName(roleName: string): RoleList;
|
|
35
|
+
hasPermission(perm: string): boolean;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/roles/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,KAAK,IAAI,EAAsB,UAAU,EAAE,MAAM,cAAc,CAAC;AAInF,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,aAAa,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC9E,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAShD,mEAAmE;AACnE,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAMhD;AAED,8EAA8E;AAC9E,wBAAgB,SAAS,IAAI,IAAI,EAAE,CAQlC;AAED,uEAAuE;AACvE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,EAAE,CAG5D;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,SAAS,GAAG,QAAQ,EAAE,CAElE;AAED,8EAA8E;AAC9E,wBAAgB,eAAe,IAAI,UAAU,EAAE,CAE9C;AAED,0GAA0G;AAC1G,wBAAgB,eAAe,IAAI,MAAM,EAAE,CAE1C;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,MAAM,EAAE,CAS5E;AAED;;GAEG;AACH,qBAAa,QAAQ;aACmB,KAAK,EAAE,IAAI,EAAE;IAAjD,OAAO;IAEP,MAAM,CAAC,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,QAAQ;IAKnD,MAAM,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ;IAK/C,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;CAGvC"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { AbacRole, SystemRole } from './classes.js';
|
|
2
|
+
import { contentPartition } from './content.js';
|
|
3
|
+
import { systemPartition } from './system.js';
|
|
4
|
+
export { AbacRole, Role, SystemRole } from './classes.js';
|
|
5
|
+
export { ContentRoleNames } from './content.js';
|
|
6
|
+
/**
|
|
7
|
+
* The ordered partition registry. Partitions are queried in this order — first
|
|
8
|
+
* match wins. The `system` partition is registered first so domain-specific
|
|
9
|
+
* partitions (added later) cannot shadow built-in system roles.
|
|
10
|
+
*/
|
|
11
|
+
const partitions = [systemPartition, contentPartition];
|
|
12
|
+
/** Look up a role by its name across all registered partitions. */
|
|
13
|
+
export function getRoleByName(name) {
|
|
14
|
+
for (const partition of partitions) {
|
|
15
|
+
const role = partition.roles.get(name);
|
|
16
|
+
if (role)
|
|
17
|
+
return role;
|
|
18
|
+
}
|
|
19
|
+
throw new Error(`Role ${name} not found`);
|
|
20
|
+
}
|
|
21
|
+
/** List every role across all partitions, in partition registration order. */
|
|
22
|
+
export function listRoles() {
|
|
23
|
+
const result = [];
|
|
24
|
+
for (const partition of partitions) {
|
|
25
|
+
for (const role of partition.roles.values()) {
|
|
26
|
+
result.push(role);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return result;
|
|
30
|
+
}
|
|
31
|
+
/** Roles owned by a specific domain (e.g. `'system'`, `'content'`). */
|
|
32
|
+
export function listRolesByDomain(domain) {
|
|
33
|
+
const partition = partitions.find((p) => p.domain === domain);
|
|
34
|
+
return partition ? Array.from(partition.roles.values()) : [];
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* ABAC roles applicable to a given ContentSet scope (e.g. `'document'`,
|
|
38
|
+
* `'collection'`). System roles are excluded — they don't carry scope semantics.
|
|
39
|
+
*/
|
|
40
|
+
export function listAbacRolesForScope(scope) {
|
|
41
|
+
return listRoles().filter((r) => r instanceof AbacRole && r.applicableScopes.includes(scope));
|
|
42
|
+
}
|
|
43
|
+
/** Shortcut for the system partition: returns only `SystemRole` instances. */
|
|
44
|
+
export function listSystemRoles() {
|
|
45
|
+
return listRoles().filter((r) => r instanceof SystemRole);
|
|
46
|
+
}
|
|
47
|
+
/** Names of every registered role across all partitions — suited for mongoose schema enum constraints. */
|
|
48
|
+
export function getAllRoleNames() {
|
|
49
|
+
return listRoles().map((r) => r.name);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Merge the permissions granted by a set of roles into a single array.
|
|
53
|
+
* Intended for the system-role gating path. For ABAC roles, the bare-verb
|
|
54
|
+
* permissions returned here aren't directly meaningful — use the JWT
|
|
55
|
+
* `content_security` pathway instead.
|
|
56
|
+
*/
|
|
57
|
+
export function getPermissionsForRoles(roleNames) {
|
|
58
|
+
const permissions = new Set();
|
|
59
|
+
for (const roleName of roleNames) {
|
|
60
|
+
const role = getRoleByName(roleName);
|
|
61
|
+
for (const permission of role.permissions) {
|
|
62
|
+
permissions.add(permission);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return Array.from(permissions);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* A list of roles with a unified `hasPermission` check across them.
|
|
69
|
+
*/
|
|
70
|
+
export class RoleList {
|
|
71
|
+
roles;
|
|
72
|
+
constructor(roles) {
|
|
73
|
+
this.roles = roles;
|
|
74
|
+
}
|
|
75
|
+
static fromRoleNames(roleNames) {
|
|
76
|
+
const roles = roleNames.map((r) => getRoleByName(r));
|
|
77
|
+
return new RoleList(roles);
|
|
78
|
+
}
|
|
79
|
+
static fromRoleName(roleName) {
|
|
80
|
+
const roles = [getRoleByName(roleName)];
|
|
81
|
+
return new RoleList(roles);
|
|
82
|
+
}
|
|
83
|
+
hasPermission(perm) {
|
|
84
|
+
return this.roles.some((role) => role.hasPermission(perm));
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/roles/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"system.d.ts","sourceRoot":"","sources":["../../src/roles/system.ts"],"names":[],"mappings":"AACA,OAAO,EAAa,KAAK,aAAa,EAAc,MAAM,cAAc,CAAC;AAuMzE,eAAO,MAAM,eAAe,EAAE,aAG7B,CAAC"}
|