@spinajs/rbac 2.0.522 → 2.0.524
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/actions.d.ts.map +1 -1
- package/lib/cjs/actions.js.map +1 -1
- package/lib/cjs/index.d.ts +2 -0
- package/lib/cjs/index.d.ts.map +1 -1
- package/lib/cjs/index.js +2 -0
- package/lib/cjs/index.js.map +1 -1
- package/lib/cjs/interfaces.d.ts +0 -24
- package/lib/cjs/interfaces.d.ts.map +1 -1
- package/lib/cjs/interfaces.js +1 -5
- package/lib/cjs/interfaces.js.map +1 -1
- package/lib/cjs/middleware.d.ts +16 -6
- package/lib/cjs/middleware.d.ts.map +1 -1
- package/lib/cjs/middleware.js +151 -90
- package/lib/cjs/middleware.js.map +1 -1
- package/lib/cjs/orm-permission.d.ts +77 -0
- package/lib/cjs/orm-permission.d.ts.map +1 -0
- package/lib/cjs/orm-permission.js +128 -0
- package/lib/cjs/orm-permission.js.map +1 -0
- package/lib/cjs/permission-service.d.ts +80 -0
- package/lib/cjs/permission-service.d.ts.map +1 -0
- package/lib/cjs/permission-service.js +144 -0
- package/lib/cjs/permission-service.js.map +1 -0
- package/lib/mjs/actions.d.ts.map +1 -1
- package/lib/mjs/actions.js.map +1 -1
- package/lib/mjs/index.d.ts +2 -0
- package/lib/mjs/index.d.ts.map +1 -1
- package/lib/mjs/index.js +2 -0
- package/lib/mjs/index.js.map +1 -1
- package/lib/mjs/interfaces.d.ts +0 -24
- package/lib/mjs/interfaces.d.ts.map +1 -1
- package/lib/mjs/interfaces.js +0 -4
- package/lib/mjs/interfaces.js.map +1 -1
- package/lib/mjs/middleware.d.ts +16 -6
- package/lib/mjs/middleware.d.ts.map +1 -1
- package/lib/mjs/middleware.js +152 -91
- package/lib/mjs/middleware.js.map +1 -1
- package/lib/mjs/orm-permission.d.ts +77 -0
- package/lib/mjs/orm-permission.d.ts.map +1 -0
- package/lib/mjs/orm-permission.js +119 -0
- package/lib/mjs/orm-permission.js.map +1 -0
- package/lib/mjs/permission-service.d.ts +80 -0
- package/lib/mjs/permission-service.d.ts.map +1 -0
- package/lib/mjs/permission-service.js +137 -0
- package/lib/mjs/permission-service.js.map +1 -0
- package/lib/tsconfig.cjs.tsbuildinfo +1 -1
- package/lib/tsconfig.mjs.tsbuildinfo +1 -1
- package/package.json +11 -11
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { Permission } from 'accesscontrol';
|
|
2
|
+
import { Class } from '@spinajs/di';
|
|
3
|
+
import type { User } from './models/User.js';
|
|
4
|
+
export type PermissionVerb = 'create' | 'read' | 'update' | 'delete';
|
|
5
|
+
export type PermissionGrantScope = 'any' | 'own' | 'none';
|
|
6
|
+
/**
|
|
7
|
+
* Base for per-domain permission services: decides and explains authorization at the
|
|
8
|
+
* domain layer, BEFORE any effect — the ORM rbac middleware stays the enforcement
|
|
9
|
+
* backstop. One concrete class per rbac resource; public API is domain-named assert
|
|
10
|
+
* methods built from the protected primitives below. The rbac User model is the actor —
|
|
11
|
+
* no wrapper objects.
|
|
12
|
+
*
|
|
13
|
+
* Stateless by contract: no instance fields in subclasses. Spinajs DI caches resolved
|
|
14
|
+
* instances, so `@FromDI()` injection in controllers, `@Autoinject` fields and
|
|
15
|
+
* `usePermission()` anywhere else share one instance safely.
|
|
16
|
+
*/
|
|
17
|
+
export declare abstract class PermissionService {
|
|
18
|
+
/** Rbac resource name this service guards — same string the grants config uses. */
|
|
19
|
+
protected abstract readonly Resource: string;
|
|
20
|
+
/**
|
|
21
|
+
* The acting user: explicit argument wins, else the rbac AsyncLocalStorage store.
|
|
22
|
+
* No user anywhere throws — a permission decision must never silently pass without
|
|
23
|
+
* an identity.
|
|
24
|
+
*/
|
|
25
|
+
protected user(user?: User): User;
|
|
26
|
+
/** Roles the decision runs against — the shared ActiveRole rule against the ambient store. */
|
|
27
|
+
protected effectiveRoles(user: User): string[];
|
|
28
|
+
protected grantScope(user: User, verb: PermissionVerb): PermissionGrantScope;
|
|
29
|
+
/** Single guarded probe against this.Resource — an unknown role answers false. */
|
|
30
|
+
protected can(roles: string[], permission: string): boolean;
|
|
31
|
+
/** Resolve acting user + scope, refusing `none` with the (overridable) domain error. */
|
|
32
|
+
protected assertGrant(verb: PermissionVerb, user?: User): {
|
|
33
|
+
user: User;
|
|
34
|
+
scope: 'any' | 'own';
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Runs `fn` as the given user, so rbac-scoped ORM queries inside answer "what does
|
|
38
|
+
* THIS user see" — ownership rules stay stated once, in the query layer. The store's
|
|
39
|
+
* own user runs in the ambient store untouched; any other user impersonates: User is
|
|
40
|
+
* swapped and ActiveRole cleared (it belongs to the ambient user only), everything
|
|
41
|
+
* else in the store kept.
|
|
42
|
+
*/
|
|
43
|
+
protected withUser<T>(user: User, fn: () => T | Promise<T>): Promise<T>;
|
|
44
|
+
protected noPermissionError(user: User, verb: PermissionVerb): Error;
|
|
45
|
+
protected noUserError(): Error;
|
|
46
|
+
private storage;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Retrieves a permission service from DI — sugar for domain services and plain
|
|
50
|
+
* functions down the callstack, so code reads as intent
|
|
51
|
+
* (`usePermission(ContentEntriesPermission)`) instead of container plumbing.
|
|
52
|
+
* Answers the same DI-cached instance controllers receive via `@FromDI()`.
|
|
53
|
+
*
|
|
54
|
+
* Accepts ONLY PermissionService subclasses — the generic constraint is erased at
|
|
55
|
+
* runtime, so this is enforced here too instead of degrading into a bare DI.resolve.
|
|
56
|
+
*/
|
|
57
|
+
export declare function usePermission<T extends PermissionService>(type: Class<T>): T;
|
|
58
|
+
/**
|
|
59
|
+
* THE guarded accesscontrol probe — single home for the AccessControlError semantics
|
|
60
|
+
* previously copy-pasted into the ORM query middleware and rbac-http's RbacPolicy.
|
|
61
|
+
* Answers the Permission object (grant attributes stay reachable), or null for a role
|
|
62
|
+
* unknown to accesscontrol — which throws AccessControlError for any role absent from
|
|
63
|
+
* the grants map and rejects the whole role array on one unknown member. A genuine
|
|
64
|
+
* programming error (bad permission name) still propagates loud.
|
|
65
|
+
*/
|
|
66
|
+
export declare function probeGrant(roles: string | string[], permission: string, resource: string): Permission | null;
|
|
67
|
+
/**
|
|
68
|
+
* THE ActiveRole rule — single home for the narrowing previously inlined in the ORM
|
|
69
|
+
* query middleware and rbac-http's checkRoutePermission. The session's ActiveRole
|
|
70
|
+
* applies only to the user it was selected for — matched by id; any other user answers
|
|
71
|
+
* their full role list.
|
|
72
|
+
*
|
|
73
|
+
* The storage parameter is structural (not IRbacAsyncStorage) so both the rbac ALS
|
|
74
|
+
* store and http's request storage (whose User is `User | null`) fit.
|
|
75
|
+
*/
|
|
76
|
+
export declare function effectiveRoles(user: User, storage?: {
|
|
77
|
+
User?: User | null;
|
|
78
|
+
ActiveRole?: string;
|
|
79
|
+
}): string[];
|
|
80
|
+
//# sourceMappingURL=permission-service.d.ts.map
|
|
@@ -0,0 +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,mFAAmF;IACnF,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE7C;;;;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;;;;;;;;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"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
2
|
+
import { AccessControl } from 'accesscontrol';
|
|
3
|
+
import { DI } from '@spinajs/di';
|
|
4
|
+
import { Forbidden } from '@spinajs/exceptions';
|
|
5
|
+
/**
|
|
6
|
+
* Base for per-domain permission services: decides and explains authorization at the
|
|
7
|
+
* domain layer, BEFORE any effect — the ORM rbac middleware stays the enforcement
|
|
8
|
+
* backstop. One concrete class per rbac resource; public API is domain-named assert
|
|
9
|
+
* methods built from the protected primitives below. The rbac User model is the actor —
|
|
10
|
+
* no wrapper objects.
|
|
11
|
+
*
|
|
12
|
+
* Stateless by contract: no instance fields in subclasses. Spinajs DI caches resolved
|
|
13
|
+
* instances, so `@FromDI()` injection in controllers, `@Autoinject` fields and
|
|
14
|
+
* `usePermission()` anywhere else share one instance safely.
|
|
15
|
+
*/
|
|
16
|
+
export class PermissionService {
|
|
17
|
+
/**
|
|
18
|
+
* The acting user: explicit argument wins, else the rbac AsyncLocalStorage store.
|
|
19
|
+
* No user anywhere throws — a permission decision must never silently pass without
|
|
20
|
+
* an identity.
|
|
21
|
+
*/
|
|
22
|
+
user(user) {
|
|
23
|
+
if (user) {
|
|
24
|
+
return user;
|
|
25
|
+
}
|
|
26
|
+
const store = this.storage().getStore();
|
|
27
|
+
if (!store?.User) {
|
|
28
|
+
throw this.noUserError();
|
|
29
|
+
}
|
|
30
|
+
return store.User;
|
|
31
|
+
}
|
|
32
|
+
/** Roles the decision runs against — the shared ActiveRole rule against the ambient store. */
|
|
33
|
+
effectiveRoles(user) {
|
|
34
|
+
return effectiveRoles(user, this.storage().getStore());
|
|
35
|
+
}
|
|
36
|
+
grantScope(user, verb) {
|
|
37
|
+
const roles = this.effectiveRoles(user);
|
|
38
|
+
if (this.can(roles, `${verb}Any`)) {
|
|
39
|
+
return 'any';
|
|
40
|
+
}
|
|
41
|
+
if (this.can(roles, `${verb}Own`)) {
|
|
42
|
+
return 'own';
|
|
43
|
+
}
|
|
44
|
+
return 'none';
|
|
45
|
+
}
|
|
46
|
+
/** Single guarded probe against this.Resource — an unknown role answers false. */
|
|
47
|
+
can(roles, permission) {
|
|
48
|
+
return probeGrant(roles, permission, this.Resource)?.granted ?? false;
|
|
49
|
+
}
|
|
50
|
+
/** Resolve acting user + scope, refusing `none` with the (overridable) domain error. */
|
|
51
|
+
assertGrant(verb, user) {
|
|
52
|
+
const acting = this.user(user);
|
|
53
|
+
const scope = this.grantScope(acting, verb);
|
|
54
|
+
if (scope === 'none') {
|
|
55
|
+
throw this.noPermissionError(acting, verb);
|
|
56
|
+
}
|
|
57
|
+
return { user: acting, scope };
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Runs `fn` as the given user, so rbac-scoped ORM queries inside answer "what does
|
|
61
|
+
* THIS user see" — ownership rules stay stated once, in the query layer. The store's
|
|
62
|
+
* own user runs in the ambient store untouched; any other user impersonates: User is
|
|
63
|
+
* swapped and ActiveRole cleared (it belongs to the ambient user only), everything
|
|
64
|
+
* else in the store kept.
|
|
65
|
+
*/
|
|
66
|
+
async withUser(user, fn) {
|
|
67
|
+
const storage = this.storage();
|
|
68
|
+
const parent = storage.getStore() ?? {};
|
|
69
|
+
if (parent.User?.Id === user.Id) {
|
|
70
|
+
return fn();
|
|
71
|
+
}
|
|
72
|
+
return storage.run({ ...parent, User: user, ActiveRole: undefined }, async () => fn());
|
|
73
|
+
}
|
|
74
|
+
noPermissionError(user, verb) {
|
|
75
|
+
return new Forbidden(`user ${user.Id} has no ${verb} grant for resource ${this.Resource}`);
|
|
76
|
+
}
|
|
77
|
+
noUserError() {
|
|
78
|
+
return new Forbidden('no acting user: none was given and none is present in the execution context');
|
|
79
|
+
}
|
|
80
|
+
storage() {
|
|
81
|
+
return DI.resolve(AsyncLocalStorage);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Retrieves a permission service from DI — sugar for domain services and plain
|
|
86
|
+
* functions down the callstack, so code reads as intent
|
|
87
|
+
* (`usePermission(ContentEntriesPermission)`) instead of container plumbing.
|
|
88
|
+
* Answers the same DI-cached instance controllers receive via `@FromDI()`.
|
|
89
|
+
*
|
|
90
|
+
* Accepts ONLY PermissionService subclasses — the generic constraint is erased at
|
|
91
|
+
* runtime, so this is enforced here too instead of degrading into a bare DI.resolve.
|
|
92
|
+
*/
|
|
93
|
+
export function usePermission(type) {
|
|
94
|
+
if (typeof type !== 'function' || !(type.prototype instanceof PermissionService)) {
|
|
95
|
+
throw new Error(`usePermission accepts only PermissionService subclasses, got ${typeof type === 'function' ? type.name : typeof type}`);
|
|
96
|
+
}
|
|
97
|
+
return DI.resolve(type);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* THE guarded accesscontrol probe — single home for the AccessControlError semantics
|
|
101
|
+
* previously copy-pasted into the ORM query middleware and rbac-http's RbacPolicy.
|
|
102
|
+
* Answers the Permission object (grant attributes stay reachable), or null for a role
|
|
103
|
+
* unknown to accesscontrol — which throws AccessControlError for any role absent from
|
|
104
|
+
* the grants map and rejects the whole role array on one unknown member. A genuine
|
|
105
|
+
* programming error (bad permission name) still propagates loud.
|
|
106
|
+
*/
|
|
107
|
+
export function probeGrant(roles, permission, resource) {
|
|
108
|
+
const ac = DI.get('AccessControl');
|
|
109
|
+
if (!ac) {
|
|
110
|
+
throw new Error('no AccessControl registered in DI — rbac is not bootstrapped');
|
|
111
|
+
}
|
|
112
|
+
try {
|
|
113
|
+
return ac.can(roles)[permission](resource);
|
|
114
|
+
}
|
|
115
|
+
catch (err) {
|
|
116
|
+
if (AccessControl.isAccessControlError(err)) {
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
throw err;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* THE ActiveRole rule — single home for the narrowing previously inlined in the ORM
|
|
124
|
+
* query middleware and rbac-http's checkRoutePermission. The session's ActiveRole
|
|
125
|
+
* applies only to the user it was selected for — matched by id; any other user answers
|
|
126
|
+
* their full role list.
|
|
127
|
+
*
|
|
128
|
+
* The storage parameter is structural (not IRbacAsyncStorage) so both the rbac ALS
|
|
129
|
+
* store and http's request storage (whose User is `User | null`) fit.
|
|
130
|
+
*/
|
|
131
|
+
export function effectiveRoles(user, storage) {
|
|
132
|
+
if (storage?.ActiveRole && storage.User?.Id === user.Id) {
|
|
133
|
+
return [storage.ActiveRole];
|
|
134
|
+
}
|
|
135
|
+
return user.Role;
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=permission-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permission-service.js","sourceRoot":"","sources":["../../src/permission-service.ts"],"names":[],"mappings":"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"}
|