@voltro/plugin-rbac 0.81.0 → 0.82.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/CHANGELOG.md +1520 -6
- package/dist/index.d.ts +14 -3
- package/dist/index.js +20 -15
- package/package.json +4 -4
package/dist/index.d.ts
CHANGED
|
@@ -54,7 +54,7 @@ export declare const compileRoles: (roleSlugs: ReadonlyArray<string>, roleMap: R
|
|
|
54
54
|
* tenant-aware role assignments Just Work). Drop into
|
|
55
55
|
* `rbacPlugin({ resolveRoles: dataStoreRoleResolver(userRoleStore(ds)) })`.
|
|
56
56
|
*/
|
|
57
|
-
export declare const dataStoreRoleResolver: (store
|
|
57
|
+
export declare const dataStoreRoleResolver: (store?: UserRoleStore) => RoleResolver;
|
|
58
58
|
|
|
59
59
|
/**
|
|
60
60
|
* Compile a subject's roles + raw permissions into one resolved scope
|
|
@@ -260,9 +260,20 @@ export declare type RoleMap = Readonly<Record<string, ReadonlyArray<string>>>;
|
|
|
260
260
|
* A resolver that yields the role slugs a subject holds. The default
|
|
261
261
|
* reads `subject.metadata.roles` (a `string[]`) when present; a project
|
|
262
262
|
* that assigns roles at runtime supplies its own (e.g. a DB lookup
|
|
263
|
-
* filtered by `subject.tenantId`).
|
|
263
|
+
* filtered by `subject.tenantId`, reading `context.store`).
|
|
264
264
|
*/
|
|
265
|
-
export declare type RoleResolver = (subject: Subject) => ReadonlyArray<string> | Promise<ReadonlyArray<string>>;
|
|
265
|
+
export declare type RoleResolver = (subject: Subject, context?: RoleResolverContext) => ReadonlyArray<string> | Promise<ReadonlyArray<string>>;
|
|
266
|
+
|
|
267
|
+
/** What a {@link RoleResolver} is handed beside the subject. */
|
|
268
|
+
export declare interface RoleResolverContext {
|
|
269
|
+
/**
|
|
270
|
+
* The app's store, bound at boot (`bindDataStore`). `app.config.ts` is
|
|
271
|
+
* evaluated before any store exists, so a resolver that reads assignments
|
|
272
|
+
* takes it from here rather than closing over one. `undefined` only before
|
|
273
|
+
* boot has bound it.
|
|
274
|
+
*/
|
|
275
|
+
readonly store?: UserRoleDataStore;
|
|
276
|
+
}
|
|
266
277
|
|
|
267
278
|
export declare const ROLES_TABLE = "_voltro_rbac_roles";
|
|
268
279
|
|
package/dist/index.js
CHANGED
|
@@ -10,12 +10,12 @@ var j = "_voltro_rbac_roles", M = "_voltro_rbac_user_roles", N = k(j, {
|
|
|
10
10
|
name: A(),
|
|
11
11
|
permissions: T(),
|
|
12
12
|
isDefault: S().default(!1)
|
|
13
|
-
}).index("
|
|
13
|
+
}).index("_voltro_rbac_roles_by_slug", ["slug"]), P = (e = {}) => k(M, {
|
|
14
14
|
id: w({ prefix: "urole" }),
|
|
15
15
|
userId: A(),
|
|
16
16
|
tenantId: e.multitenant ? D(O(), { index: !1 }).nullable() : A().nullable(),
|
|
17
17
|
roleSlug: A()
|
|
18
|
-
}).index("
|
|
18
|
+
}).index("_voltro_rbac_user_roles_by_user_tenant", ["userId", "tenantId"]).index("_voltro_rbac_user_roles_by_role_slug", ["roleSlug"]), F = P(), I = (e = {}) => [N, P(e)], L = (e, t) => e.query({
|
|
19
19
|
table: M,
|
|
20
20
|
predicate: t,
|
|
21
21
|
order: [{
|
|
@@ -44,9 +44,11 @@ var j = "_voltro_rbac_roles", M = "_voltro_rbac_user_roles", N = k(j, {
|
|
|
44
44
|
return [...new Set(r)];
|
|
45
45
|
}
|
|
46
46
|
};
|
|
47
|
-
}, z = (e) => e === null ? C("tenantId", null) : E(C("tenantId", e), C("tenantId", null)), B = (e) => (t) => {
|
|
48
|
-
let
|
|
49
|
-
|
|
47
|
+
}, z = (e) => e === null ? C("tenantId", null) : E(C("tenantId", e), C("tenantId", null)), B = (e) => (t, n) => {
|
|
48
|
+
let r = ("tenantId" in t ? t.tenantId : void 0) ?? null, i = ("id" in t ? t.id : void 0) ?? null;
|
|
49
|
+
if (!i) return [];
|
|
50
|
+
let a = e ?? (n?.store === void 0 ? void 0 : R(n.store));
|
|
51
|
+
return a === void 0 ? [] : a.rolesOf(i, r);
|
|
50
52
|
}, V = b({ scope: "@voltro/plugin-rbac" }), H = (e) => p.suspend(() => {
|
|
51
53
|
let t = e();
|
|
52
54
|
return t instanceof Promise ? p.promise(() => t) : p.succeed(t);
|
|
@@ -63,33 +65,36 @@ var j = "_voltro_rbac_roles", M = "_voltro_rbac_user_roles", N = k(j, {
|
|
|
63
65
|
cause: String(e)
|
|
64
66
|
}), p.succeed(!1)))));
|
|
65
67
|
}
|
|
66
|
-
let u = (n, r) => p.gen(function* () {
|
|
67
|
-
let s = yield* H(() => i(r.subject)).pipe(p.catchAllCause((e) => (V.warn("resolveRoles failed; falling back to raw subject scopes", {
|
|
68
|
+
let u, d = (n, r) => p.gen(function* () {
|
|
69
|
+
let s = yield* H(() => i(r.subject, { ...u === void 0 ? {} : { store: u } })).pipe(p.catchAllCause((e) => (V.warn("resolveRoles failed; falling back to raw subject scopes", {
|
|
68
70
|
tag: r.tag,
|
|
69
71
|
traceId: r.traceId,
|
|
70
72
|
cause: String(e)
|
|
71
73
|
}), p.succeed([])))), c = o ? yield* H(() => o(r.subject)).pipe(p.catchAllCause(() => p.succeed([]))) : [], l = e(r.subject, s, t.roles, c);
|
|
72
74
|
return a(r.subject, l, s), yield* n;
|
|
73
|
-
}),
|
|
75
|
+
}), f = [
|
|
74
76
|
"rpc:intercept:mutation",
|
|
75
77
|
"rpc:intercept:query",
|
|
76
78
|
"rpc:intercept:action",
|
|
77
79
|
"rpc:intercept:workflow",
|
|
78
80
|
...c ? ["store:write"] : []
|
|
79
|
-
],
|
|
81
|
+
], h = o === void 0 ? r(t.roles) : void 0;
|
|
80
82
|
return _({
|
|
81
83
|
name: v({
|
|
82
84
|
base: U,
|
|
83
85
|
alias: t.alias
|
|
84
86
|
}),
|
|
85
87
|
baseName: U,
|
|
86
|
-
...
|
|
88
|
+
...h === void 0 ? {} : { declaredScopes: h },
|
|
87
89
|
description: "Role-based access control — roles compile to scopes on top of the protocol scope system. Ships the permission() handler guard + a role→scope interceptor + a resource-aware guard resolver, failing with protocol's typed ScopeError (one denial tag framework-wide).",
|
|
88
|
-
permissions:
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
90
|
+
permissions: f,
|
|
91
|
+
bindDataStore: (e) => {
|
|
92
|
+
u = e;
|
|
93
|
+
},
|
|
94
|
+
interceptMutation: d,
|
|
95
|
+
interceptQuery: d,
|
|
96
|
+
interceptAction: d,
|
|
97
|
+
interceptWorkflow: d,
|
|
93
98
|
errorSchemas: [{
|
|
94
99
|
schema: g,
|
|
95
100
|
import: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voltro/plugin-rbac",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.82.0",
|
|
4
4
|
"description": "Role-based access control — roles compile to scopes on top of @voltro/protocol's scope system. Ships rbacPlugin() (role→scope interceptor + resource-aware guard resolver, failing with protocol's typed ScopeError), the permission()/assertPermission()/anyPermission() handler guards, the compileRoles() pure compiler, cross-dialect roles + userRoles tables. The UI gate lives in @voltro/client (useCan / useCanAny) — scopes are a framework concept, so gating a button must not require this plugin.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"voltro",
|
|
@@ -33,9 +33,9 @@
|
|
|
33
33
|
"node": ">=24.0.0"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@voltro/database": "0.
|
|
37
|
-
"@voltro/logger": "0.
|
|
38
|
-
"@voltro/protocol": "0.
|
|
36
|
+
"@voltro/database": "0.82.0",
|
|
37
|
+
"@voltro/logger": "0.82.0",
|
|
38
|
+
"@voltro/protocol": "0.82.0"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
41
41
|
"effect": "^3.22.2",
|