@spinajs/rbac 2.0.526 → 2.0.528
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/cjs/permission-service.d.ts +36 -0
- package/lib/cjs/permission-service.d.ts.map +1 -1
- package/lib/cjs/permission-service.js +57 -0
- package/lib/cjs/permission-service.js.map +1 -1
- package/lib/mjs/permission-service.d.ts +36 -0
- package/lib/mjs/permission-service.d.ts.map +1 -1
- package/lib/mjs/permission-service.js +56 -0
- package/lib/mjs/permission-service.js.map +1 -1
- package/lib/tsconfig.cjs.tsbuildinfo +1 -1
- package/lib/tsconfig.mjs.tsbuildinfo +1 -1
- package/package.json +11 -11
|
@@ -54,6 +54,23 @@ export declare abstract class PermissionService {
|
|
|
54
54
|
* else in the store kept.
|
|
55
55
|
*/
|
|
56
56
|
protected withUser<T>(user: User, fn: () => T | Promise<T>): Promise<T>;
|
|
57
|
+
/**
|
|
58
|
+
* A fluent, awaitable sequence of this service's own rule checks — see {@link RuleChain}.
|
|
59
|
+
* Composite rules build out of the simple ones without imperative glue:
|
|
60
|
+
*
|
|
61
|
+
* await this.chain().assert('update', entry, user).assertFileCapacity(entry);
|
|
62
|
+
*
|
|
63
|
+
* Public so a domain service can compose the rules it consumes the same way:
|
|
64
|
+
*
|
|
65
|
+
* await this.permissions.chain().assert('update', entry, actor).assertFileCapacity(entry);
|
|
66
|
+
*
|
|
67
|
+
* CONVENTIONS the chain enforces: only `assert*` / `can*` methods are chainable (anything else
|
|
68
|
+
* throws at build time), and chainable rules are public - `keyof this` sees only public
|
|
69
|
+
* members. And the one discipline it cannot enforce: an UN-AWAITED chain runs nothing, so the
|
|
70
|
+
* consuming package must lint with `@typescript-eslint/no-floating-promises` - the chain is a
|
|
71
|
+
* PromiseLike precisely so that rule catches a forgotten await on a permission gate.
|
|
72
|
+
*/
|
|
73
|
+
chain(): RuleChain<this>;
|
|
57
74
|
protected noPermissionError(user: User, verb: PermissionVerb): Error;
|
|
58
75
|
protected noUserError(): Error;
|
|
59
76
|
private storage;
|
|
@@ -88,6 +105,25 @@ export declare abstract class ResourceRules<TModel> extends PermissionService {
|
|
|
88
105
|
/** Override hook for typed domain errors, like {@link noPermissionError}. */
|
|
89
106
|
protected notOwnedError(user: User, _subject: TModel | undefined): Error;
|
|
90
107
|
}
|
|
108
|
+
/**
|
|
109
|
+
* A fluent, awaitable sequence of rule checks — what `chain()` answers.
|
|
110
|
+
*
|
|
111
|
+
* Every method of the underlying service appears here with the same arguments but answering
|
|
112
|
+
* the chain again (meant for the assert-style rules; a queued step's own return value is
|
|
113
|
+
* discarded), so composite rules read as one sentence:
|
|
114
|
+
*
|
|
115
|
+
* await this.chain().assert('update', entry, user).assertFileCapacity(entry);
|
|
116
|
+
*
|
|
117
|
+
* Nothing runs until the chain is awaited; then the steps run IN CALL ORDER, sequentially and
|
|
118
|
+
* fail-fast — the first throw rejects the chain and later steps never execute, so a cheap grant
|
|
119
|
+
* check placed first still spares the DB lookups behind it. Awaiting the same chain twice runs
|
|
120
|
+
* it once.
|
|
121
|
+
*/
|
|
122
|
+
export type RuleChain<T> = PromiseLike<void> & {
|
|
123
|
+
[K in keyof T]: T[K] extends (...args: infer A) => unknown ? (...args: A) => RuleChain<T> : never;
|
|
124
|
+
};
|
|
125
|
+
/** Builds a {@link RuleChain} over any rules object — the mechanics behind `chain()`. */
|
|
126
|
+
export declare function ruleChain<T extends object>(target: T): RuleChain<T>;
|
|
91
127
|
/**
|
|
92
128
|
* Retrieves a permission service from DI — sugar for domain services and plain
|
|
93
129
|
* functions down the callstack, so code reads as intent
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permission-service.d.ts","sourceRoot":"","sources":["../../src/permission-service.ts"],"names":[],"mappings":"AACA,OAAO,EAAiB,UAAU,EAAE,MAAM,eAAe,CAAC;AAC1D,OAAO,EAAE,KAAK,EAAM,MAAM,aAAa,CAAC;AAGxC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAE7C,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,CAAC;AACrE,MAAM,MAAM,oBAAoB,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;AAE1D;;;;;;;;;;GAUG;AACH,8BAAsB,iBAAiB;IACrC;;;;;OAKG;IACH,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,GAAG,MAAM,CAAC;IAE9D;;;;;;OAMG;IACH,SAAS,CAAC,YAAY,IAAI,MAAM,CAS/B;IAED;;;;OAIG;IACH,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,CAWhC;IAED,8FAA8F;IAC9F,SAAS,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,EAAE,CAE7C;IAED,SAAS,CAAC,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,GAAG,oBAAoB,CAU3E;IAED,kFAAkF;IAClF,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAE1D;IAED,wFAAwF;IACxF,SAAS,CAAC,WAAW,CAAC,IAAI,EAAE,cAAc,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,KAAK,EAAE,KAAK,GAAG,KAAK,CAAA;KAAE,CAS7F;IAED;;;;;;OAMG;IACH,UAAgB,QAAQ,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAS5E;IAED,SAAS,CAAC,iBAAiB,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,GAAG,KAAK,CAEnE;IAED,SAAS,CAAC,WAAW,IAAI,KAAK,CAE7B;IAED,OAAO,CAAC,OAAO;CAGhB;AAED;;;;;;;;;;;;GAYG;AACH,8BAAsB,aAAa,CAAC,MAAM,CAAE,SAAQ,iBAAiB;IACnE,4BAAqC,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAE7D;;;OAGG;IACH,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;IAEjF;;;;;OAKG;IACU,MAAM,CAAC,IAAI,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAUtF;IAED,6EAA6E;IAE7E,SAAS,CAAC,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,KAAK,CAEvE;CACF;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,iBAAiB,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAM5E;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAc5G;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,EAAE,CAK1G"}
|
|
1
|
+
{"version":3,"file":"permission-service.d.ts","sourceRoot":"","sources":["../../src/permission-service.ts"],"names":[],"mappings":"AACA,OAAO,EAAiB,UAAU,EAAE,MAAM,eAAe,CAAC;AAC1D,OAAO,EAAE,KAAK,EAAM,MAAM,aAAa,CAAC;AAGxC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAE7C,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,CAAC;AACrE,MAAM,MAAM,oBAAoB,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;AAE1D;;;;;;;;;;GAUG;AACH,8BAAsB,iBAAiB;IACrC;;;;;OAKG;IACH,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,GAAG,MAAM,CAAC;IAE9D;;;;;;OAMG;IACH,SAAS,CAAC,YAAY,IAAI,MAAM,CAS/B;IAED;;;;OAIG;IACH,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,CAWhC;IAED,8FAA8F;IAC9F,SAAS,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,EAAE,CAE7C;IAED,SAAS,CAAC,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,GAAG,oBAAoB,CAU3E;IAED,kFAAkF;IAClF,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAE1D;IAED,wFAAwF;IACxF,SAAS,CAAC,WAAW,CAAC,IAAI,EAAE,cAAc,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,KAAK,EAAE,KAAK,GAAG,KAAK,CAAA;KAAE,CAS7F;IAED;;;;;;OAMG;IACH,UAAgB,QAAQ,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAS5E;IAED;;;;;;;;;;;;;;;OAeG;IACI,KAAK,IAAI,SAAS,CAAC,IAAI,CAAC,CAE9B;IAED,SAAS,CAAC,iBAAiB,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,GAAG,KAAK,CAEnE;IAED,SAAS,CAAC,WAAW,IAAI,KAAK,CAE7B;IAED,OAAO,CAAC,OAAO;CAGhB;AAED;;;;;;;;;;;;GAYG;AACH,8BAAsB,aAAa,CAAC,MAAM,CAAE,SAAQ,iBAAiB;IACnE,4BAAqC,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAE7D;;;OAGG;IACH,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;IAEjF;;;;;OAKG;IACU,MAAM,CAAC,IAAI,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAUtF;IAED,6EAA6E;IAE7E,SAAS,CAAC,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,KAAK,CAEvE;CACF;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI,WAAW,CAAC,IAAI,CAAC,GAAG;KAC5C,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,KAAK,OAAO,GAAG,CAAC,GAAG,IAAI,EAAE,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,KAAK;CAClG,CAAC;AAEF,yFAAyF;AACzF,wBAAgB,SAAS,CAAC,CAAC,SAAS,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CA0CnE;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,iBAAiB,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAM5E;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAc5G;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,EAAE,CAK1G"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ResourceRules = exports.PermissionService = void 0;
|
|
4
|
+
exports.ruleChain = ruleChain;
|
|
4
5
|
exports.usePermission = usePermission;
|
|
5
6
|
exports.probeGrant = probeGrant;
|
|
6
7
|
exports.effectiveRoles = effectiveRoles;
|
|
@@ -92,6 +93,25 @@ class PermissionService {
|
|
|
92
93
|
}
|
|
93
94
|
return storage.run({ ...parent, User: user, ActiveRole: undefined }, async () => fn());
|
|
94
95
|
}
|
|
96
|
+
/**
|
|
97
|
+
* A fluent, awaitable sequence of this service's own rule checks — see {@link RuleChain}.
|
|
98
|
+
* Composite rules build out of the simple ones without imperative glue:
|
|
99
|
+
*
|
|
100
|
+
* await this.chain().assert('update', entry, user).assertFileCapacity(entry);
|
|
101
|
+
*
|
|
102
|
+
* Public so a domain service can compose the rules it consumes the same way:
|
|
103
|
+
*
|
|
104
|
+
* await this.permissions.chain().assert('update', entry, actor).assertFileCapacity(entry);
|
|
105
|
+
*
|
|
106
|
+
* CONVENTIONS the chain enforces: only `assert*` / `can*` methods are chainable (anything else
|
|
107
|
+
* throws at build time), and chainable rules are public - `keyof this` sees only public
|
|
108
|
+
* members. And the one discipline it cannot enforce: an UN-AWAITED chain runs nothing, so the
|
|
109
|
+
* consuming package must lint with `@typescript-eslint/no-floating-promises` - the chain is a
|
|
110
|
+
* PromiseLike precisely so that rule catches a forgotten await on a permission gate.
|
|
111
|
+
*/
|
|
112
|
+
chain() {
|
|
113
|
+
return ruleChain(this);
|
|
114
|
+
}
|
|
95
115
|
noPermissionError(user, verb) {
|
|
96
116
|
return new exceptions_1.Forbidden(`user ${user.Id} has no ${verb} grant for resource ${this.resourceName()}`);
|
|
97
117
|
}
|
|
@@ -139,6 +159,43 @@ class ResourceRules extends PermissionService {
|
|
|
139
159
|
}
|
|
140
160
|
}
|
|
141
161
|
exports.ResourceRules = ResourceRules;
|
|
162
|
+
/** Builds a {@link RuleChain} over any rules object — the mechanics behind `chain()`. */
|
|
163
|
+
function ruleChain(target) {
|
|
164
|
+
const steps = [];
|
|
165
|
+
let run;
|
|
166
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
167
|
+
const proxy = new Proxy({}, {
|
|
168
|
+
get(_, prop) {
|
|
169
|
+
if (prop === 'then') {
|
|
170
|
+
run ??= (async () => {
|
|
171
|
+
for (const step of steps) {
|
|
172
|
+
await step();
|
|
173
|
+
}
|
|
174
|
+
})();
|
|
175
|
+
return run.then.bind(run);
|
|
176
|
+
}
|
|
177
|
+
// Only rule methods are chainable - the `assert*` / `can*` naming convention IS the
|
|
178
|
+
// contract (it also forces them public: `keyof T` sees only public members, so the type
|
|
179
|
+
// mirrors this gate). Anything else answers undefined rather than throwing: the chain is
|
|
180
|
+
// a thenable, and consumers PROBE it (`catch`/`finally`, inspection symbols - chai's
|
|
181
|
+
// promise detection reads `.catch`), so only a rule-shaped name that names no method is
|
|
182
|
+
// a build-time error - that one is a typo on a permission gate, and it must not
|
|
183
|
+
// typecheck into a queued nonsense call whose result is silently discarded.
|
|
184
|
+
if (typeof prop !== 'string' || !/^(assert|can)/.test(prop)) {
|
|
185
|
+
return undefined;
|
|
186
|
+
}
|
|
187
|
+
if (typeof target[prop] !== 'function') {
|
|
188
|
+
throw new Error(`RuleChain: '${prop}' is not a rule method on ${target.constructor.name}`);
|
|
189
|
+
}
|
|
190
|
+
return (...args) => {
|
|
191
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-call
|
|
192
|
+
steps.push(() => target[prop](...args));
|
|
193
|
+
return proxy;
|
|
194
|
+
};
|
|
195
|
+
},
|
|
196
|
+
});
|
|
197
|
+
return proxy;
|
|
198
|
+
}
|
|
142
199
|
/**
|
|
143
200
|
* Retrieves a permission service from DI — sugar for domain services and plain
|
|
144
201
|
* functions down the callstack, so code reads as intent
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permission-service.js","sourceRoot":"","sources":["../../src/permission-service.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"permission-service.js","sourceRoot":"","sources":["../../src/permission-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -54,6 +54,23 @@ export declare abstract class PermissionService {
|
|
|
54
54
|
* else in the store kept.
|
|
55
55
|
*/
|
|
56
56
|
protected withUser<T>(user: User, fn: () => T | Promise<T>): Promise<T>;
|
|
57
|
+
/**
|
|
58
|
+
* A fluent, awaitable sequence of this service's own rule checks — see {@link RuleChain}.
|
|
59
|
+
* Composite rules build out of the simple ones without imperative glue:
|
|
60
|
+
*
|
|
61
|
+
* await this.chain().assert('update', entry, user).assertFileCapacity(entry);
|
|
62
|
+
*
|
|
63
|
+
* Public so a domain service can compose the rules it consumes the same way:
|
|
64
|
+
*
|
|
65
|
+
* await this.permissions.chain().assert('update', entry, actor).assertFileCapacity(entry);
|
|
66
|
+
*
|
|
67
|
+
* CONVENTIONS the chain enforces: only `assert*` / `can*` methods are chainable (anything else
|
|
68
|
+
* throws at build time), and chainable rules are public - `keyof this` sees only public
|
|
69
|
+
* members. And the one discipline it cannot enforce: an UN-AWAITED chain runs nothing, so the
|
|
70
|
+
* consuming package must lint with `@typescript-eslint/no-floating-promises` - the chain is a
|
|
71
|
+
* PromiseLike precisely so that rule catches a forgotten await on a permission gate.
|
|
72
|
+
*/
|
|
73
|
+
chain(): RuleChain<this>;
|
|
57
74
|
protected noPermissionError(user: User, verb: PermissionVerb): Error;
|
|
58
75
|
protected noUserError(): Error;
|
|
59
76
|
private storage;
|
|
@@ -88,6 +105,25 @@ export declare abstract class ResourceRules<TModel> extends PermissionService {
|
|
|
88
105
|
/** Override hook for typed domain errors, like {@link noPermissionError}. */
|
|
89
106
|
protected notOwnedError(user: User, _subject: TModel | undefined): Error;
|
|
90
107
|
}
|
|
108
|
+
/**
|
|
109
|
+
* A fluent, awaitable sequence of rule checks — what `chain()` answers.
|
|
110
|
+
*
|
|
111
|
+
* Every method of the underlying service appears here with the same arguments but answering
|
|
112
|
+
* the chain again (meant for the assert-style rules; a queued step's own return value is
|
|
113
|
+
* discarded), so composite rules read as one sentence:
|
|
114
|
+
*
|
|
115
|
+
* await this.chain().assert('update', entry, user).assertFileCapacity(entry);
|
|
116
|
+
*
|
|
117
|
+
* Nothing runs until the chain is awaited; then the steps run IN CALL ORDER, sequentially and
|
|
118
|
+
* fail-fast — the first throw rejects the chain and later steps never execute, so a cheap grant
|
|
119
|
+
* check placed first still spares the DB lookups behind it. Awaiting the same chain twice runs
|
|
120
|
+
* it once.
|
|
121
|
+
*/
|
|
122
|
+
export type RuleChain<T> = PromiseLike<void> & {
|
|
123
|
+
[K in keyof T]: T[K] extends (...args: infer A) => unknown ? (...args: A) => RuleChain<T> : never;
|
|
124
|
+
};
|
|
125
|
+
/** Builds a {@link RuleChain} over any rules object — the mechanics behind `chain()`. */
|
|
126
|
+
export declare function ruleChain<T extends object>(target: T): RuleChain<T>;
|
|
91
127
|
/**
|
|
92
128
|
* Retrieves a permission service from DI — sugar for domain services and plain
|
|
93
129
|
* functions down the callstack, so code reads as intent
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permission-service.d.ts","sourceRoot":"","sources":["../../src/permission-service.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"permission-service.d.ts","sourceRoot":"","sources":["../../src/permission-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -86,6 +86,25 @@ export class PermissionService {
|
|
|
86
86
|
}
|
|
87
87
|
return storage.run({ ...parent, User: user, ActiveRole: undefined }, async () => fn());
|
|
88
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* A fluent, awaitable sequence of this service's own rule checks — see {@link RuleChain}.
|
|
91
|
+
* Composite rules build out of the simple ones without imperative glue:
|
|
92
|
+
*
|
|
93
|
+
* await this.chain().assert('update', entry, user).assertFileCapacity(entry);
|
|
94
|
+
*
|
|
95
|
+
* Public so a domain service can compose the rules it consumes the same way:
|
|
96
|
+
*
|
|
97
|
+
* await this.permissions.chain().assert('update', entry, actor).assertFileCapacity(entry);
|
|
98
|
+
*
|
|
99
|
+
* CONVENTIONS the chain enforces: only `assert*` / `can*` methods are chainable (anything else
|
|
100
|
+
* throws at build time), and chainable rules are public - `keyof this` sees only public
|
|
101
|
+
* members. And the one discipline it cannot enforce: an UN-AWAITED chain runs nothing, so the
|
|
102
|
+
* consuming package must lint with `@typescript-eslint/no-floating-promises` - the chain is a
|
|
103
|
+
* PromiseLike precisely so that rule catches a forgotten await on a permission gate.
|
|
104
|
+
*/
|
|
105
|
+
chain() {
|
|
106
|
+
return ruleChain(this);
|
|
107
|
+
}
|
|
89
108
|
noPermissionError(user, verb) {
|
|
90
109
|
return new Forbidden(`user ${user.Id} has no ${verb} grant for resource ${this.resourceName()}`);
|
|
91
110
|
}
|
|
@@ -131,6 +150,43 @@ export class ResourceRules extends PermissionService {
|
|
|
131
150
|
return new Forbidden(`user ${user.Id} does not own the ${this.resourceName()} subject of this action`);
|
|
132
151
|
}
|
|
133
152
|
}
|
|
153
|
+
/** Builds a {@link RuleChain} over any rules object — the mechanics behind `chain()`. */
|
|
154
|
+
export function ruleChain(target) {
|
|
155
|
+
const steps = [];
|
|
156
|
+
let run;
|
|
157
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
158
|
+
const proxy = new Proxy({}, {
|
|
159
|
+
get(_, prop) {
|
|
160
|
+
if (prop === 'then') {
|
|
161
|
+
run ??= (async () => {
|
|
162
|
+
for (const step of steps) {
|
|
163
|
+
await step();
|
|
164
|
+
}
|
|
165
|
+
})();
|
|
166
|
+
return run.then.bind(run);
|
|
167
|
+
}
|
|
168
|
+
// Only rule methods are chainable - the `assert*` / `can*` naming convention IS the
|
|
169
|
+
// contract (it also forces them public: `keyof T` sees only public members, so the type
|
|
170
|
+
// mirrors this gate). Anything else answers undefined rather than throwing: the chain is
|
|
171
|
+
// a thenable, and consumers PROBE it (`catch`/`finally`, inspection symbols - chai's
|
|
172
|
+
// promise detection reads `.catch`), so only a rule-shaped name that names no method is
|
|
173
|
+
// a build-time error - that one is a typo on a permission gate, and it must not
|
|
174
|
+
// typecheck into a queued nonsense call whose result is silently discarded.
|
|
175
|
+
if (typeof prop !== 'string' || !/^(assert|can)/.test(prop)) {
|
|
176
|
+
return undefined;
|
|
177
|
+
}
|
|
178
|
+
if (typeof target[prop] !== 'function') {
|
|
179
|
+
throw new Error(`RuleChain: '${prop}' is not a rule method on ${target.constructor.name}`);
|
|
180
|
+
}
|
|
181
|
+
return (...args) => {
|
|
182
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-call
|
|
183
|
+
steps.push(() => target[prop](...args));
|
|
184
|
+
return proxy;
|
|
185
|
+
};
|
|
186
|
+
},
|
|
187
|
+
});
|
|
188
|
+
return proxy;
|
|
189
|
+
}
|
|
134
190
|
/**
|
|
135
191
|
* Retrieves a permission service from DI — sugar for domain services and plain
|
|
136
192
|
* functions down the callstack, so code reads as intent
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permission-service.js","sourceRoot":"","sources":["../../src/permission-service.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"permission-service.js","sourceRoot":"","sources":["../../src/permission-service.ts"],"names":[],"mappings":"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"}
|