@auth-gate/rbac 0.8.1 → 0.9.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/dist/{chunk-5YEMXO7B.mjs → chunk-ZFKXT2MP.mjs} +25 -2
- package/dist/cli.cjs +26 -2
- package/dist/cli.mjs +2 -1
- package/dist/index.cjs +115 -3
- package/dist/index.d.cts +121 -7
- package/dist/index.d.ts +121 -7
- package/dist/index.mjs +90 -2
- package/package.json +1 -1
|
@@ -150,6 +150,21 @@ function validateRbacConfig(config) {
|
|
|
150
150
|
}
|
|
151
151
|
}
|
|
152
152
|
}
|
|
153
|
+
const defaultRoles = [];
|
|
154
|
+
for (const key of roleKeys) {
|
|
155
|
+
const role = roles[key];
|
|
156
|
+
if (role.isDefault !== void 0 && typeof role.isDefault !== "boolean") {
|
|
157
|
+
throw new Error(`Role "${key}".isDefault must be a boolean.`);
|
|
158
|
+
}
|
|
159
|
+
if (role.isDefault === true) {
|
|
160
|
+
defaultRoles.push(key);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
if (defaultRoles.length > 1) {
|
|
164
|
+
throw new Error(
|
|
165
|
+
`Only one role may have isDefault: true. Found ${defaultRoles.length}: ${defaultRoles.join(", ")}.`
|
|
166
|
+
);
|
|
167
|
+
}
|
|
153
168
|
for (const key of roleKeys) {
|
|
154
169
|
const role = roles[key];
|
|
155
170
|
if (role.inherits !== void 0) {
|
|
@@ -302,7 +317,7 @@ function hashConditionSource(fn) {
|
|
|
302
317
|
return createHash("sha256").update(fn.toString()).digest("hex").slice(0, 16);
|
|
303
318
|
}
|
|
304
319
|
function computeRbacDiff(config, server, memberCounts) {
|
|
305
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
|
|
320
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
|
|
306
321
|
const resourceOps = [];
|
|
307
322
|
const roleOps = [];
|
|
308
323
|
const conditionOps = [];
|
|
@@ -393,6 +408,11 @@ function computeRbacDiff(config, server, memberCounts) {
|
|
|
393
408
|
if (existingInherits !== configInherits) {
|
|
394
409
|
changes.push("inherits changed");
|
|
395
410
|
}
|
|
411
|
+
const existingDefault = (_l = existing.isDefault) != null ? _l : false;
|
|
412
|
+
const configDefault = (_m = role.isDefault) != null ? _m : false;
|
|
413
|
+
if (existingDefault !== configDefault) {
|
|
414
|
+
changes.push(`isDefault: ${existingDefault} -> ${configDefault}`);
|
|
415
|
+
}
|
|
396
416
|
if (changes.length > 0) {
|
|
397
417
|
roleOps.push({ type: "update", key, role, existing, changes });
|
|
398
418
|
}
|
|
@@ -402,7 +422,7 @@ function computeRbacDiff(config, server, memberCounts) {
|
|
|
402
422
|
for (const [key, role] of serverRoleByKey) {
|
|
403
423
|
if (renameMap.has(key)) continue;
|
|
404
424
|
if (role.isActive) {
|
|
405
|
-
const members = (
|
|
425
|
+
const members = (_n = memberCounts[role.configKey]) != null ? _n : 0;
|
|
406
426
|
if (members > 0) hasDestructive = true;
|
|
407
427
|
roleOps.push({ type: "archive", key, existing: role, assignedMembers: members });
|
|
408
428
|
}
|
|
@@ -489,6 +509,9 @@ function formatRbacDiff(diff, dryRun) {
|
|
|
489
509
|
chalk.dim(` inherits: [${[...op.role.inherits].join(", ")}]`)
|
|
490
510
|
);
|
|
491
511
|
}
|
|
512
|
+
if (op.role.isDefault) {
|
|
513
|
+
lines.push(chalk.dim(` isDefault: true`));
|
|
514
|
+
}
|
|
492
515
|
} else if (op.type === "update") {
|
|
493
516
|
lines.push(chalk.yellow(` ~ UPDATE role "${op.key}"`));
|
|
494
517
|
for (const change of op.changes) {
|
package/dist/cli.cjs
CHANGED
|
@@ -170,6 +170,21 @@ function validateRbacConfig(config) {
|
|
|
170
170
|
}
|
|
171
171
|
}
|
|
172
172
|
}
|
|
173
|
+
const defaultRoles = [];
|
|
174
|
+
for (const key of roleKeys) {
|
|
175
|
+
const role = roles[key];
|
|
176
|
+
if (role.isDefault !== void 0 && typeof role.isDefault !== "boolean") {
|
|
177
|
+
throw new Error(`Role "${key}".isDefault must be a boolean.`);
|
|
178
|
+
}
|
|
179
|
+
if (role.isDefault === true) {
|
|
180
|
+
defaultRoles.push(key);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
if (defaultRoles.length > 1) {
|
|
184
|
+
throw new Error(
|
|
185
|
+
`Only one role may have isDefault: true. Found ${defaultRoles.length}: ${defaultRoles.join(", ")}.`
|
|
186
|
+
);
|
|
187
|
+
}
|
|
173
188
|
for (const key of roleKeys) {
|
|
174
189
|
const role = roles[key];
|
|
175
190
|
if (role.inherits !== void 0) {
|
|
@@ -320,7 +335,7 @@ function hashConditionSource(fn) {
|
|
|
320
335
|
return createHash("sha256").update(fn.toString()).digest("hex").slice(0, 16);
|
|
321
336
|
}
|
|
322
337
|
function computeRbacDiff(config, server, memberCounts) {
|
|
323
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
|
|
338
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
|
|
324
339
|
const resourceOps = [];
|
|
325
340
|
const roleOps = [];
|
|
326
341
|
const conditionOps = [];
|
|
@@ -411,6 +426,11 @@ function computeRbacDiff(config, server, memberCounts) {
|
|
|
411
426
|
if (existingInherits !== configInherits) {
|
|
412
427
|
changes.push("inherits changed");
|
|
413
428
|
}
|
|
429
|
+
const existingDefault = (_l = existing.isDefault) != null ? _l : false;
|
|
430
|
+
const configDefault = (_m = role.isDefault) != null ? _m : false;
|
|
431
|
+
if (existingDefault !== configDefault) {
|
|
432
|
+
changes.push(`isDefault: ${existingDefault} -> ${configDefault}`);
|
|
433
|
+
}
|
|
414
434
|
if (changes.length > 0) {
|
|
415
435
|
roleOps.push({ type: "update", key, role, existing, changes });
|
|
416
436
|
}
|
|
@@ -420,7 +440,7 @@ function computeRbacDiff(config, server, memberCounts) {
|
|
|
420
440
|
for (const [key, role] of serverRoleByKey) {
|
|
421
441
|
if (renameMap.has(key)) continue;
|
|
422
442
|
if (role.isActive) {
|
|
423
|
-
const members = (
|
|
443
|
+
const members = (_n = memberCounts[role.configKey]) != null ? _n : 0;
|
|
424
444
|
if (members > 0) hasDestructive = true;
|
|
425
445
|
roleOps.push({ type: "archive", key, existing: role, assignedMembers: members });
|
|
426
446
|
}
|
|
@@ -507,6 +527,9 @@ function formatRbacDiff(diff, dryRun) {
|
|
|
507
527
|
import_chalk.default.dim(` inherits: [${[...op.role.inherits].join(", ")}]`)
|
|
508
528
|
);
|
|
509
529
|
}
|
|
530
|
+
if (op.role.isDefault) {
|
|
531
|
+
lines.push(import_chalk.default.dim(` isDefault: true`));
|
|
532
|
+
}
|
|
510
533
|
} else if (op.type === "update") {
|
|
511
534
|
lines.push(import_chalk.default.yellow(` ~ UPDATE role "${op.key}"`));
|
|
512
535
|
for (const change of op.changes) {
|
|
@@ -726,6 +749,7 @@ export const rbac = defineRbac({
|
|
|
726
749
|
},
|
|
727
750
|
viewer: {
|
|
728
751
|
name: "Viewer",
|
|
752
|
+
isDefault: true,
|
|
729
753
|
grants: {
|
|
730
754
|
documents: { read: true },
|
|
731
755
|
},
|
package/dist/cli.mjs
CHANGED
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
computeRbacDiff,
|
|
6
6
|
formatRbacDiff,
|
|
7
7
|
loadRbacConfig
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-ZFKXT2MP.mjs";
|
|
9
9
|
|
|
10
10
|
// src/cli.ts
|
|
11
11
|
import chalk from "chalk";
|
|
@@ -93,6 +93,7 @@ export const rbac = defineRbac({
|
|
|
93
93
|
},
|
|
94
94
|
viewer: {
|
|
95
95
|
name: "Viewer",
|
|
96
|
+
isDefault: true,
|
|
96
97
|
grants: {
|
|
97
98
|
documents: { read: true },
|
|
98
99
|
},
|
package/dist/index.cjs
CHANGED
|
@@ -32,6 +32,7 @@ var index_exports = {};
|
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
RbacSyncClient: () => RbacSyncClient,
|
|
34
34
|
computeRbacDiff: () => computeRbacDiff,
|
|
35
|
+
createRoleManagement: () => createRoleManagement,
|
|
35
36
|
defineRbac: () => defineRbac,
|
|
36
37
|
formatRbacDiff: () => formatRbacDiff,
|
|
37
38
|
hashConditionSource: () => hashConditionSource,
|
|
@@ -169,6 +170,21 @@ function validateRbacConfig(config) {
|
|
|
169
170
|
}
|
|
170
171
|
}
|
|
171
172
|
}
|
|
173
|
+
const defaultRoles = [];
|
|
174
|
+
for (const key of roleKeys) {
|
|
175
|
+
const role = roles[key];
|
|
176
|
+
if (role.isDefault !== void 0 && typeof role.isDefault !== "boolean") {
|
|
177
|
+
throw new Error(`Role "${key}".isDefault must be a boolean.`);
|
|
178
|
+
}
|
|
179
|
+
if (role.isDefault === true) {
|
|
180
|
+
defaultRoles.push(key);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
if (defaultRoles.length > 1) {
|
|
184
|
+
throw new Error(
|
|
185
|
+
`Only one role may have isDefault: true. Found ${defaultRoles.length}: ${defaultRoles.join(", ")}.`
|
|
186
|
+
);
|
|
187
|
+
}
|
|
172
188
|
for (const key of roleKeys) {
|
|
173
189
|
const role = roles[key];
|
|
174
190
|
if (role.inherits !== void 0) {
|
|
@@ -321,7 +337,7 @@ function hashConditionSource(fn) {
|
|
|
321
337
|
return createHash("sha256").update(fn.toString()).digest("hex").slice(0, 16);
|
|
322
338
|
}
|
|
323
339
|
function computeRbacDiff(config, server, memberCounts) {
|
|
324
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
|
|
340
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
|
|
325
341
|
const resourceOps = [];
|
|
326
342
|
const roleOps = [];
|
|
327
343
|
const conditionOps = [];
|
|
@@ -412,6 +428,11 @@ function computeRbacDiff(config, server, memberCounts) {
|
|
|
412
428
|
if (existingInherits !== configInherits) {
|
|
413
429
|
changes.push("inherits changed");
|
|
414
430
|
}
|
|
431
|
+
const existingDefault = (_l = existing.isDefault) != null ? _l : false;
|
|
432
|
+
const configDefault = (_m = role.isDefault) != null ? _m : false;
|
|
433
|
+
if (existingDefault !== configDefault) {
|
|
434
|
+
changes.push(`isDefault: ${existingDefault} -> ${configDefault}`);
|
|
435
|
+
}
|
|
415
436
|
if (changes.length > 0) {
|
|
416
437
|
roleOps.push({ type: "update", key, role, existing, changes });
|
|
417
438
|
}
|
|
@@ -421,7 +442,7 @@ function computeRbacDiff(config, server, memberCounts) {
|
|
|
421
442
|
for (const [key, role] of serverRoleByKey) {
|
|
422
443
|
if (renameMap.has(key)) continue;
|
|
423
444
|
if (role.isActive) {
|
|
424
|
-
const members = (
|
|
445
|
+
const members = (_n = memberCounts[role.configKey]) != null ? _n : 0;
|
|
425
446
|
if (members > 0) hasDestructive = true;
|
|
426
447
|
roleOps.push({ type: "archive", key, existing: role, assignedMembers: members });
|
|
427
448
|
}
|
|
@@ -571,6 +592,9 @@ function formatRbacDiff(diff, dryRun) {
|
|
|
571
592
|
import_chalk.default.dim(` inherits: [${[...op.role.inherits].join(", ")}]`)
|
|
572
593
|
);
|
|
573
594
|
}
|
|
595
|
+
if (op.role.isDefault) {
|
|
596
|
+
lines.push(import_chalk.default.dim(` isDefault: true`));
|
|
597
|
+
}
|
|
574
598
|
} else if (op.type === "update") {
|
|
575
599
|
lines.push(import_chalk.default.yellow(` ~ UPDATE role "${op.key}"`));
|
|
576
600
|
for (const change of op.changes) {
|
|
@@ -641,8 +665,95 @@ function formatRbacDiff(diff, dryRun) {
|
|
|
641
665
|
return lines.join("\n");
|
|
642
666
|
}
|
|
643
667
|
|
|
668
|
+
// src/role-management.ts
|
|
669
|
+
function createRoleManagement(config) {
|
|
670
|
+
const baseUrl = config.baseUrl.replace(/\/$/, "");
|
|
671
|
+
const apiKey = config.apiKey;
|
|
672
|
+
async function request(method, path, body) {
|
|
673
|
+
var _a, _b;
|
|
674
|
+
const url = `${baseUrl}${path}`;
|
|
675
|
+
const headers = {
|
|
676
|
+
Authorization: `Bearer ${apiKey}`,
|
|
677
|
+
"Content-Type": "application/json"
|
|
678
|
+
};
|
|
679
|
+
const res = await fetch(url, {
|
|
680
|
+
method,
|
|
681
|
+
headers,
|
|
682
|
+
body: body ? JSON.stringify(body) : void 0
|
|
683
|
+
});
|
|
684
|
+
if (!res.ok) {
|
|
685
|
+
const text = await res.text();
|
|
686
|
+
let message;
|
|
687
|
+
try {
|
|
688
|
+
const json = JSON.parse(text);
|
|
689
|
+
message = (_b = (_a = json.error) != null ? _a : json.message) != null ? _b : "Unknown error";
|
|
690
|
+
} catch (e) {
|
|
691
|
+
message = text.length > 500 ? text.slice(0, 500) + "..." : text;
|
|
692
|
+
}
|
|
693
|
+
if (apiKey) {
|
|
694
|
+
message = message.replaceAll(apiKey, "[REDACTED]");
|
|
695
|
+
}
|
|
696
|
+
throw new Error(`API error (${res.status}): ${message}`);
|
|
697
|
+
}
|
|
698
|
+
return res.json();
|
|
699
|
+
}
|
|
700
|
+
return {
|
|
701
|
+
async listRoles() {
|
|
702
|
+
const result = await request("GET", "/api/v1/roles");
|
|
703
|
+
return result.data.map(toRole);
|
|
704
|
+
},
|
|
705
|
+
async createRole(input) {
|
|
706
|
+
var _a, _b;
|
|
707
|
+
const result = await request("POST", "/api/v1/roles", {
|
|
708
|
+
key: input.key,
|
|
709
|
+
name: input.name,
|
|
710
|
+
description: input.description,
|
|
711
|
+
is_default: (_a = input.isDefault) != null ? _a : false,
|
|
712
|
+
permissions: (_b = input.permissions) != null ? _b : []
|
|
713
|
+
});
|
|
714
|
+
return toRole(result.role);
|
|
715
|
+
},
|
|
716
|
+
async updateRole(roleId, input) {
|
|
717
|
+
const body = {};
|
|
718
|
+
if (input.name !== void 0) body.name = input.name;
|
|
719
|
+
if (input.description !== void 0) body.description = input.description;
|
|
720
|
+
if (input.permissions !== void 0) body.permissions = input.permissions;
|
|
721
|
+
if (input.isDefault !== void 0) body.is_default = input.isDefault;
|
|
722
|
+
const result = await request(
|
|
723
|
+
"PATCH",
|
|
724
|
+
`/api/v1/roles/${encodeURIComponent(roleId)}`,
|
|
725
|
+
body
|
|
726
|
+
);
|
|
727
|
+
return toRole(result.role);
|
|
728
|
+
},
|
|
729
|
+
async deleteRole(roleId) {
|
|
730
|
+
await request(
|
|
731
|
+
"DELETE",
|
|
732
|
+
`/api/v1/roles/${encodeURIComponent(roleId)}`
|
|
733
|
+
);
|
|
734
|
+
},
|
|
735
|
+
async setDefaultRole(roleId) {
|
|
736
|
+
return this.updateRole(roleId, { isDefault: true });
|
|
737
|
+
}
|
|
738
|
+
};
|
|
739
|
+
}
|
|
740
|
+
function toRole(raw) {
|
|
741
|
+
return {
|
|
742
|
+
id: raw.id,
|
|
743
|
+
projectId: raw.project_id,
|
|
744
|
+
key: raw.key,
|
|
745
|
+
name: raw.name,
|
|
746
|
+
description: raw.description,
|
|
747
|
+
isDefault: raw.is_default,
|
|
748
|
+
permissions: raw.permissions,
|
|
749
|
+
createdAt: raw.created_at,
|
|
750
|
+
updatedAt: raw.updated_at
|
|
751
|
+
};
|
|
752
|
+
}
|
|
753
|
+
|
|
644
754
|
// src/index.ts
|
|
645
755
|
function defineRbac(config, opts) {
|
|
756
|
+
var _a;
|
|
646
757
|
if ((opts == null ? void 0 : opts.validate) !== false) {
|
|
647
758
|
validateRbacConfig(config);
|
|
648
759
|
}
|
|
@@ -656,7 +767,7 @@ function defineRbac(config, opts) {
|
|
|
656
767
|
}
|
|
657
768
|
const roles = {};
|
|
658
769
|
for (const [key, role] of Object.entries(config.roles)) {
|
|
659
|
-
roles[key] = { key, name: role.name, grants: role.grants };
|
|
770
|
+
roles[key] = { key, name: role.name, grants: role.grants, isDefault: (_a = role.isDefault) != null ? _a : false };
|
|
660
771
|
}
|
|
661
772
|
const permissions = {};
|
|
662
773
|
for (const [key, resource] of Object.entries(config.resources)) {
|
|
@@ -679,6 +790,7 @@ function defineRbac(config, opts) {
|
|
|
679
790
|
0 && (module.exports = {
|
|
680
791
|
RbacSyncClient,
|
|
681
792
|
computeRbacDiff,
|
|
793
|
+
createRoleManagement,
|
|
682
794
|
defineRbac,
|
|
683
795
|
formatRbacDiff,
|
|
684
796
|
hashConditionSource,
|
package/dist/index.d.cts
CHANGED
|
@@ -39,6 +39,8 @@ interface RoleConfig {
|
|
|
39
39
|
description?: string;
|
|
40
40
|
inherits?: readonly string[];
|
|
41
41
|
grants: Record<string, Record<string, GrantValue>>;
|
|
42
|
+
/** Mark this role as the default for new org members. Only one role may be default. */
|
|
43
|
+
isDefault?: boolean;
|
|
42
44
|
/** Previous config key if this role was renamed. */
|
|
43
45
|
renamedFrom?: string;
|
|
44
46
|
}
|
|
@@ -80,6 +82,63 @@ type InferScopes<T, Resource extends string> = T extends {
|
|
|
80
82
|
type InferConditionKeys<T> = T extends {
|
|
81
83
|
conditions: infer C;
|
|
82
84
|
} ? keyof C & string : never;
|
|
85
|
+
/** Extract role keys that have `isDefault: true`. */
|
|
86
|
+
type DefaultRoleKeys<Roles> = {
|
|
87
|
+
[K in keyof Roles]: Roles[K] extends {
|
|
88
|
+
isDefault: true;
|
|
89
|
+
} ? K : never;
|
|
90
|
+
}[keyof Roles];
|
|
91
|
+
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
|
|
92
|
+
type IsUnion<T> = [T] extends [UnionToIntersection<T>] ? false : true;
|
|
93
|
+
/**
|
|
94
|
+
* Compile-time constraint: if more than one role has `isDefault: true`,
|
|
95
|
+
* intersect those roles' `isDefault` with an error string so TypeScript
|
|
96
|
+
* produces a descriptive message.
|
|
97
|
+
*
|
|
98
|
+
* Error reads: Type 'true' is not assignable to type '"ERROR: ..."'.
|
|
99
|
+
*/
|
|
100
|
+
type ValidateSingleDefault<T> = T extends {
|
|
101
|
+
roles: infer Roles;
|
|
102
|
+
} ? IsUnion<DefaultRoleKeys<Roles>> extends true ? {
|
|
103
|
+
roles: {
|
|
104
|
+
[K in DefaultRoleKeys<Roles> & keyof Roles]: {
|
|
105
|
+
isDefault: "ERROR: Only one role may have isDefault: true";
|
|
106
|
+
};
|
|
107
|
+
};
|
|
108
|
+
} : {} : {};
|
|
109
|
+
/** Extract valid action string literals from a resource config. */
|
|
110
|
+
type ValidActions<R> = R extends {
|
|
111
|
+
actions: readonly (infer U)[];
|
|
112
|
+
} ? U & string : never;
|
|
113
|
+
/**
|
|
114
|
+
* Compile-time constraint: validates grant resource/action keys against
|
|
115
|
+
* declared resources at the type level.
|
|
116
|
+
*
|
|
117
|
+
* - **Invalid resource key** → descriptive error naming the resource.
|
|
118
|
+
* - **Invalid action key** → descriptive error listing valid actions.
|
|
119
|
+
* - **Valid grants** → passes through original types transparently.
|
|
120
|
+
*
|
|
121
|
+
* Used as `T & ValidateConfig<T>` in the `defineRbac()` parameter type.
|
|
122
|
+
*
|
|
123
|
+
* @note Extra properties on role objects (e.g. `isFakeProp`) are caught
|
|
124
|
+
* by the runtime `validateRbacConfig()` which runs by default.
|
|
125
|
+
*/
|
|
126
|
+
type ValidateConfig<T> = T extends {
|
|
127
|
+
resources: infer R extends Record<string, ResourceConfig>;
|
|
128
|
+
roles: infer Roles;
|
|
129
|
+
} ? {
|
|
130
|
+
roles: {
|
|
131
|
+
[RK in keyof Roles]: Roles[RK] extends {
|
|
132
|
+
grants: infer G;
|
|
133
|
+
} ? {
|
|
134
|
+
grants: {
|
|
135
|
+
[ResK in keyof G]: ResK extends keyof R ? keyof G[ResK] extends ValidActions<R[ResK & keyof R]> ? {
|
|
136
|
+
[ActK in keyof G[ResK]]: G[ResK][ActK];
|
|
137
|
+
} : `ERROR: invalid action(s) in "${ResK & string}" grants. Valid actions: ${ValidActions<R[ResK & keyof R]>}` : `ERROR: resource "${ResK & string}" is not declared in resources`;
|
|
138
|
+
};
|
|
139
|
+
} : Roles[RK];
|
|
140
|
+
};
|
|
141
|
+
} : {};
|
|
83
142
|
/** A structured resource with a `key` constant and an `actions` map of `"resource:action"` strings. */
|
|
84
143
|
type StructuredResource<T, K extends string> = {
|
|
85
144
|
readonly key: K;
|
|
@@ -91,7 +150,7 @@ type StructuredResource<T, K extends string> = {
|
|
|
91
150
|
type StructuredResources<T> = {
|
|
92
151
|
readonly [K in InferResourceKeys<T>]: StructuredResource<T, K>;
|
|
93
152
|
};
|
|
94
|
-
/** A structured role with `key`, `name`, and `
|
|
153
|
+
/** A structured role with `key`, `name`, `grants`, and optional `isDefault` from the config. */
|
|
95
154
|
type StructuredRole<T, K extends string> = {
|
|
96
155
|
readonly key: K;
|
|
97
156
|
readonly name: T extends {
|
|
@@ -104,6 +163,11 @@ type StructuredRole<T, K extends string> = {
|
|
|
104
163
|
} ? K extends keyof R ? R[K] extends {
|
|
105
164
|
grants: infer G;
|
|
106
165
|
} ? Readonly<G> : {} : {} : {};
|
|
166
|
+
readonly isDefault: T extends {
|
|
167
|
+
roles: infer R;
|
|
168
|
+
} ? K extends keyof R ? R[K] extends {
|
|
169
|
+
isDefault: infer D;
|
|
170
|
+
} ? D : false : false : false;
|
|
107
171
|
};
|
|
108
172
|
/** Map of all roles as structured objects: `roles.admin.key` -> `"admin"`. */
|
|
109
173
|
type StructuredRoles<T> = {
|
|
@@ -121,7 +185,7 @@ type StructuredPermissions<T> = {
|
|
|
121
185
|
* Carries phantom types that downstream factories use to constrain
|
|
122
186
|
* permission/role string parameters -- enabling full IDE autocomplete.
|
|
123
187
|
*/
|
|
124
|
-
interface TypedRbac<T
|
|
188
|
+
interface TypedRbac<T> {
|
|
125
189
|
/** The raw RBAC config. Access resources, roles, etc. via `rbac._config`. */
|
|
126
190
|
readonly _config: T;
|
|
127
191
|
/**
|
|
@@ -172,6 +236,7 @@ interface ServerRole {
|
|
|
172
236
|
grants: Record<string, Record<string, GrantValue>> | null;
|
|
173
237
|
inherits: string[];
|
|
174
238
|
resolvedPermissions: string[];
|
|
239
|
+
isDefault: boolean;
|
|
175
240
|
isActive: boolean;
|
|
176
241
|
managedBy: string;
|
|
177
242
|
version: number;
|
|
@@ -272,12 +337,61 @@ declare class RbacSyncClient {
|
|
|
272
337
|
|
|
273
338
|
declare function formatRbacDiff(diff: DiffResult, dryRun: boolean): string;
|
|
274
339
|
|
|
340
|
+
interface RoleManagementConfig {
|
|
341
|
+
baseUrl: string;
|
|
342
|
+
apiKey: string;
|
|
343
|
+
}
|
|
344
|
+
interface Role {
|
|
345
|
+
id: string;
|
|
346
|
+
projectId: string;
|
|
347
|
+
key: string;
|
|
348
|
+
name: string;
|
|
349
|
+
description: string | null;
|
|
350
|
+
isDefault: boolean;
|
|
351
|
+
permissions: string[];
|
|
352
|
+
createdAt: string;
|
|
353
|
+
updatedAt: string;
|
|
354
|
+
}
|
|
355
|
+
interface CreateRoleInput {
|
|
356
|
+
key: string;
|
|
357
|
+
name: string;
|
|
358
|
+
description?: string;
|
|
359
|
+
isDefault?: boolean;
|
|
360
|
+
permissions?: string[];
|
|
361
|
+
}
|
|
362
|
+
interface UpdateRoleInput {
|
|
363
|
+
name?: string;
|
|
364
|
+
description?: string | null;
|
|
365
|
+
permissions?: string[];
|
|
366
|
+
isDefault?: boolean;
|
|
367
|
+
}
|
|
368
|
+
interface RoleManagementClient {
|
|
369
|
+
listRoles(): Promise<Role[]>;
|
|
370
|
+
createRole(input: CreateRoleInput): Promise<Role>;
|
|
371
|
+
updateRole(roleId: string, input: UpdateRoleInput): Promise<Role>;
|
|
372
|
+
deleteRole(roleId: string): Promise<void>;
|
|
373
|
+
setDefaultRole(roleId: string): Promise<Role>;
|
|
374
|
+
}
|
|
375
|
+
declare function createRoleManagement(config: RoleManagementConfig): RoleManagementClient;
|
|
376
|
+
|
|
377
|
+
/** Base config shape used as the generic constraint for `defineRbac()`. */
|
|
378
|
+
type DefineRbacConfig = {
|
|
379
|
+
resources: Record<string, ResourceConfig>;
|
|
380
|
+
conditions?: Record<string, ConditionFn>;
|
|
381
|
+
roles: Record<string, {
|
|
382
|
+
name: string;
|
|
383
|
+
description?: string;
|
|
384
|
+
inherits?: readonly string[];
|
|
385
|
+
isDefault?: boolean;
|
|
386
|
+
renamedFrom?: string;
|
|
387
|
+
grants: Record<string, Record<string, GrantValue>>;
|
|
388
|
+
}>;
|
|
389
|
+
};
|
|
275
390
|
/**
|
|
276
391
|
* Define your RBAC config. Use this in your `authgate.rbac.ts` config file.
|
|
277
392
|
*
|
|
278
|
-
*
|
|
279
|
-
*
|
|
280
|
-
* and server-side checks.
|
|
393
|
+
* Grants are validated at compile-time: if a role references an undeclared
|
|
394
|
+
* resource or action, TypeScript flags it as a type error.
|
|
281
395
|
*
|
|
282
396
|
* @example
|
|
283
397
|
* ```ts
|
|
@@ -310,8 +424,8 @@ declare function formatRbacDiff(diff: DiffResult, dryRun: boolean): string;
|
|
|
310
424
|
* rbac.permissions.documents.write // "documents:write"
|
|
311
425
|
* ```
|
|
312
426
|
*/
|
|
313
|
-
declare function defineRbac<const T extends
|
|
427
|
+
declare function defineRbac<const T extends DefineRbacConfig>(config: T & ValidateConfig<T> & ValidateSingleDefault<T>, opts?: {
|
|
314
428
|
validate?: boolean;
|
|
315
429
|
}): TypedRbac<T>;
|
|
316
430
|
|
|
317
|
-
export { type ApplyResult, type ConditionContext, type ConditionFn, type ConditionOp, type DiffResult, type GrantValue, type InferActions, type InferConditionKeys, type InferPermissions, type InferResourceKeys, type InferRoleKeys, type InferScopes, type Permission, type RbacConfig, RbacSyncClient, type RbacSyncClientConfig, type ResourceConfig, type ResourceKey, type ResourceOp, type RoleConfig, type RoleKey, type RoleOp, type ServerCondition, type ServerResource, type ServerRole, type ServerState, type TypedRbac, computeRbacDiff, defineRbac, formatRbacDiff, hashConditionSource, loadRbacConfig, validateRbacConfig };
|
|
431
|
+
export { type ApplyResult, type ConditionContext, type ConditionFn, type ConditionOp, type CreateRoleInput, type DiffResult, type GrantValue, type InferActions, type InferConditionKeys, type InferPermissions, type InferResourceKeys, type InferRoleKeys, type InferScopes, type Permission, type RbacConfig, RbacSyncClient, type RbacSyncClientConfig, type ResourceConfig, type ResourceKey, type ResourceOp, type Role, type RoleConfig, type RoleKey, type RoleManagementClient, type RoleManagementConfig, type RoleOp, type ServerCondition, type ServerResource, type ServerRole, type ServerState, type TypedRbac, type UpdateRoleInput, computeRbacDiff, createRoleManagement, defineRbac, formatRbacDiff, hashConditionSource, loadRbacConfig, validateRbacConfig };
|
package/dist/index.d.ts
CHANGED
|
@@ -39,6 +39,8 @@ interface RoleConfig {
|
|
|
39
39
|
description?: string;
|
|
40
40
|
inherits?: readonly string[];
|
|
41
41
|
grants: Record<string, Record<string, GrantValue>>;
|
|
42
|
+
/** Mark this role as the default for new org members. Only one role may be default. */
|
|
43
|
+
isDefault?: boolean;
|
|
42
44
|
/** Previous config key if this role was renamed. */
|
|
43
45
|
renamedFrom?: string;
|
|
44
46
|
}
|
|
@@ -80,6 +82,63 @@ type InferScopes<T, Resource extends string> = T extends {
|
|
|
80
82
|
type InferConditionKeys<T> = T extends {
|
|
81
83
|
conditions: infer C;
|
|
82
84
|
} ? keyof C & string : never;
|
|
85
|
+
/** Extract role keys that have `isDefault: true`. */
|
|
86
|
+
type DefaultRoleKeys<Roles> = {
|
|
87
|
+
[K in keyof Roles]: Roles[K] extends {
|
|
88
|
+
isDefault: true;
|
|
89
|
+
} ? K : never;
|
|
90
|
+
}[keyof Roles];
|
|
91
|
+
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
|
|
92
|
+
type IsUnion<T> = [T] extends [UnionToIntersection<T>] ? false : true;
|
|
93
|
+
/**
|
|
94
|
+
* Compile-time constraint: if more than one role has `isDefault: true`,
|
|
95
|
+
* intersect those roles' `isDefault` with an error string so TypeScript
|
|
96
|
+
* produces a descriptive message.
|
|
97
|
+
*
|
|
98
|
+
* Error reads: Type 'true' is not assignable to type '"ERROR: ..."'.
|
|
99
|
+
*/
|
|
100
|
+
type ValidateSingleDefault<T> = T extends {
|
|
101
|
+
roles: infer Roles;
|
|
102
|
+
} ? IsUnion<DefaultRoleKeys<Roles>> extends true ? {
|
|
103
|
+
roles: {
|
|
104
|
+
[K in DefaultRoleKeys<Roles> & keyof Roles]: {
|
|
105
|
+
isDefault: "ERROR: Only one role may have isDefault: true";
|
|
106
|
+
};
|
|
107
|
+
};
|
|
108
|
+
} : {} : {};
|
|
109
|
+
/** Extract valid action string literals from a resource config. */
|
|
110
|
+
type ValidActions<R> = R extends {
|
|
111
|
+
actions: readonly (infer U)[];
|
|
112
|
+
} ? U & string : never;
|
|
113
|
+
/**
|
|
114
|
+
* Compile-time constraint: validates grant resource/action keys against
|
|
115
|
+
* declared resources at the type level.
|
|
116
|
+
*
|
|
117
|
+
* - **Invalid resource key** → descriptive error naming the resource.
|
|
118
|
+
* - **Invalid action key** → descriptive error listing valid actions.
|
|
119
|
+
* - **Valid grants** → passes through original types transparently.
|
|
120
|
+
*
|
|
121
|
+
* Used as `T & ValidateConfig<T>` in the `defineRbac()` parameter type.
|
|
122
|
+
*
|
|
123
|
+
* @note Extra properties on role objects (e.g. `isFakeProp`) are caught
|
|
124
|
+
* by the runtime `validateRbacConfig()` which runs by default.
|
|
125
|
+
*/
|
|
126
|
+
type ValidateConfig<T> = T extends {
|
|
127
|
+
resources: infer R extends Record<string, ResourceConfig>;
|
|
128
|
+
roles: infer Roles;
|
|
129
|
+
} ? {
|
|
130
|
+
roles: {
|
|
131
|
+
[RK in keyof Roles]: Roles[RK] extends {
|
|
132
|
+
grants: infer G;
|
|
133
|
+
} ? {
|
|
134
|
+
grants: {
|
|
135
|
+
[ResK in keyof G]: ResK extends keyof R ? keyof G[ResK] extends ValidActions<R[ResK & keyof R]> ? {
|
|
136
|
+
[ActK in keyof G[ResK]]: G[ResK][ActK];
|
|
137
|
+
} : `ERROR: invalid action(s) in "${ResK & string}" grants. Valid actions: ${ValidActions<R[ResK & keyof R]>}` : `ERROR: resource "${ResK & string}" is not declared in resources`;
|
|
138
|
+
};
|
|
139
|
+
} : Roles[RK];
|
|
140
|
+
};
|
|
141
|
+
} : {};
|
|
83
142
|
/** A structured resource with a `key` constant and an `actions` map of `"resource:action"` strings. */
|
|
84
143
|
type StructuredResource<T, K extends string> = {
|
|
85
144
|
readonly key: K;
|
|
@@ -91,7 +150,7 @@ type StructuredResource<T, K extends string> = {
|
|
|
91
150
|
type StructuredResources<T> = {
|
|
92
151
|
readonly [K in InferResourceKeys<T>]: StructuredResource<T, K>;
|
|
93
152
|
};
|
|
94
|
-
/** A structured role with `key`, `name`, and `
|
|
153
|
+
/** A structured role with `key`, `name`, `grants`, and optional `isDefault` from the config. */
|
|
95
154
|
type StructuredRole<T, K extends string> = {
|
|
96
155
|
readonly key: K;
|
|
97
156
|
readonly name: T extends {
|
|
@@ -104,6 +163,11 @@ type StructuredRole<T, K extends string> = {
|
|
|
104
163
|
} ? K extends keyof R ? R[K] extends {
|
|
105
164
|
grants: infer G;
|
|
106
165
|
} ? Readonly<G> : {} : {} : {};
|
|
166
|
+
readonly isDefault: T extends {
|
|
167
|
+
roles: infer R;
|
|
168
|
+
} ? K extends keyof R ? R[K] extends {
|
|
169
|
+
isDefault: infer D;
|
|
170
|
+
} ? D : false : false : false;
|
|
107
171
|
};
|
|
108
172
|
/** Map of all roles as structured objects: `roles.admin.key` -> `"admin"`. */
|
|
109
173
|
type StructuredRoles<T> = {
|
|
@@ -121,7 +185,7 @@ type StructuredPermissions<T> = {
|
|
|
121
185
|
* Carries phantom types that downstream factories use to constrain
|
|
122
186
|
* permission/role string parameters -- enabling full IDE autocomplete.
|
|
123
187
|
*/
|
|
124
|
-
interface TypedRbac<T
|
|
188
|
+
interface TypedRbac<T> {
|
|
125
189
|
/** The raw RBAC config. Access resources, roles, etc. via `rbac._config`. */
|
|
126
190
|
readonly _config: T;
|
|
127
191
|
/**
|
|
@@ -172,6 +236,7 @@ interface ServerRole {
|
|
|
172
236
|
grants: Record<string, Record<string, GrantValue>> | null;
|
|
173
237
|
inherits: string[];
|
|
174
238
|
resolvedPermissions: string[];
|
|
239
|
+
isDefault: boolean;
|
|
175
240
|
isActive: boolean;
|
|
176
241
|
managedBy: string;
|
|
177
242
|
version: number;
|
|
@@ -272,12 +337,61 @@ declare class RbacSyncClient {
|
|
|
272
337
|
|
|
273
338
|
declare function formatRbacDiff(diff: DiffResult, dryRun: boolean): string;
|
|
274
339
|
|
|
340
|
+
interface RoleManagementConfig {
|
|
341
|
+
baseUrl: string;
|
|
342
|
+
apiKey: string;
|
|
343
|
+
}
|
|
344
|
+
interface Role {
|
|
345
|
+
id: string;
|
|
346
|
+
projectId: string;
|
|
347
|
+
key: string;
|
|
348
|
+
name: string;
|
|
349
|
+
description: string | null;
|
|
350
|
+
isDefault: boolean;
|
|
351
|
+
permissions: string[];
|
|
352
|
+
createdAt: string;
|
|
353
|
+
updatedAt: string;
|
|
354
|
+
}
|
|
355
|
+
interface CreateRoleInput {
|
|
356
|
+
key: string;
|
|
357
|
+
name: string;
|
|
358
|
+
description?: string;
|
|
359
|
+
isDefault?: boolean;
|
|
360
|
+
permissions?: string[];
|
|
361
|
+
}
|
|
362
|
+
interface UpdateRoleInput {
|
|
363
|
+
name?: string;
|
|
364
|
+
description?: string | null;
|
|
365
|
+
permissions?: string[];
|
|
366
|
+
isDefault?: boolean;
|
|
367
|
+
}
|
|
368
|
+
interface RoleManagementClient {
|
|
369
|
+
listRoles(): Promise<Role[]>;
|
|
370
|
+
createRole(input: CreateRoleInput): Promise<Role>;
|
|
371
|
+
updateRole(roleId: string, input: UpdateRoleInput): Promise<Role>;
|
|
372
|
+
deleteRole(roleId: string): Promise<void>;
|
|
373
|
+
setDefaultRole(roleId: string): Promise<Role>;
|
|
374
|
+
}
|
|
375
|
+
declare function createRoleManagement(config: RoleManagementConfig): RoleManagementClient;
|
|
376
|
+
|
|
377
|
+
/** Base config shape used as the generic constraint for `defineRbac()`. */
|
|
378
|
+
type DefineRbacConfig = {
|
|
379
|
+
resources: Record<string, ResourceConfig>;
|
|
380
|
+
conditions?: Record<string, ConditionFn>;
|
|
381
|
+
roles: Record<string, {
|
|
382
|
+
name: string;
|
|
383
|
+
description?: string;
|
|
384
|
+
inherits?: readonly string[];
|
|
385
|
+
isDefault?: boolean;
|
|
386
|
+
renamedFrom?: string;
|
|
387
|
+
grants: Record<string, Record<string, GrantValue>>;
|
|
388
|
+
}>;
|
|
389
|
+
};
|
|
275
390
|
/**
|
|
276
391
|
* Define your RBAC config. Use this in your `authgate.rbac.ts` config file.
|
|
277
392
|
*
|
|
278
|
-
*
|
|
279
|
-
*
|
|
280
|
-
* and server-side checks.
|
|
393
|
+
* Grants are validated at compile-time: if a role references an undeclared
|
|
394
|
+
* resource or action, TypeScript flags it as a type error.
|
|
281
395
|
*
|
|
282
396
|
* @example
|
|
283
397
|
* ```ts
|
|
@@ -310,8 +424,8 @@ declare function formatRbacDiff(diff: DiffResult, dryRun: boolean): string;
|
|
|
310
424
|
* rbac.permissions.documents.write // "documents:write"
|
|
311
425
|
* ```
|
|
312
426
|
*/
|
|
313
|
-
declare function defineRbac<const T extends
|
|
427
|
+
declare function defineRbac<const T extends DefineRbacConfig>(config: T & ValidateConfig<T> & ValidateSingleDefault<T>, opts?: {
|
|
314
428
|
validate?: boolean;
|
|
315
429
|
}): TypedRbac<T>;
|
|
316
430
|
|
|
317
|
-
export { type ApplyResult, type ConditionContext, type ConditionFn, type ConditionOp, type DiffResult, type GrantValue, type InferActions, type InferConditionKeys, type InferPermissions, type InferResourceKeys, type InferRoleKeys, type InferScopes, type Permission, type RbacConfig, RbacSyncClient, type RbacSyncClientConfig, type ResourceConfig, type ResourceKey, type ResourceOp, type RoleConfig, type RoleKey, type RoleOp, type ServerCondition, type ServerResource, type ServerRole, type ServerState, type TypedRbac, computeRbacDiff, defineRbac, formatRbacDiff, hashConditionSource, loadRbacConfig, validateRbacConfig };
|
|
431
|
+
export { type ApplyResult, type ConditionContext, type ConditionFn, type ConditionOp, type CreateRoleInput, type DiffResult, type GrantValue, type InferActions, type InferConditionKeys, type InferPermissions, type InferResourceKeys, type InferRoleKeys, type InferScopes, type Permission, type RbacConfig, RbacSyncClient, type RbacSyncClientConfig, type ResourceConfig, type ResourceKey, type ResourceOp, type Role, type RoleConfig, type RoleKey, type RoleManagementClient, type RoleManagementConfig, type RoleOp, type ServerCondition, type ServerResource, type ServerRole, type ServerState, type TypedRbac, type UpdateRoleInput, computeRbacDiff, createRoleManagement, defineRbac, formatRbacDiff, hashConditionSource, loadRbacConfig, validateRbacConfig };
|
package/dist/index.mjs
CHANGED
|
@@ -5,10 +5,97 @@ import {
|
|
|
5
5
|
hashConditionSource,
|
|
6
6
|
loadRbacConfig,
|
|
7
7
|
validateRbacConfig
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-ZFKXT2MP.mjs";
|
|
9
|
+
|
|
10
|
+
// src/role-management.ts
|
|
11
|
+
function createRoleManagement(config) {
|
|
12
|
+
const baseUrl = config.baseUrl.replace(/\/$/, "");
|
|
13
|
+
const apiKey = config.apiKey;
|
|
14
|
+
async function request(method, path, body) {
|
|
15
|
+
var _a, _b;
|
|
16
|
+
const url = `${baseUrl}${path}`;
|
|
17
|
+
const headers = {
|
|
18
|
+
Authorization: `Bearer ${apiKey}`,
|
|
19
|
+
"Content-Type": "application/json"
|
|
20
|
+
};
|
|
21
|
+
const res = await fetch(url, {
|
|
22
|
+
method,
|
|
23
|
+
headers,
|
|
24
|
+
body: body ? JSON.stringify(body) : void 0
|
|
25
|
+
});
|
|
26
|
+
if (!res.ok) {
|
|
27
|
+
const text = await res.text();
|
|
28
|
+
let message;
|
|
29
|
+
try {
|
|
30
|
+
const json = JSON.parse(text);
|
|
31
|
+
message = (_b = (_a = json.error) != null ? _a : json.message) != null ? _b : "Unknown error";
|
|
32
|
+
} catch (e) {
|
|
33
|
+
message = text.length > 500 ? text.slice(0, 500) + "..." : text;
|
|
34
|
+
}
|
|
35
|
+
if (apiKey) {
|
|
36
|
+
message = message.replaceAll(apiKey, "[REDACTED]");
|
|
37
|
+
}
|
|
38
|
+
throw new Error(`API error (${res.status}): ${message}`);
|
|
39
|
+
}
|
|
40
|
+
return res.json();
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
async listRoles() {
|
|
44
|
+
const result = await request("GET", "/api/v1/roles");
|
|
45
|
+
return result.data.map(toRole);
|
|
46
|
+
},
|
|
47
|
+
async createRole(input) {
|
|
48
|
+
var _a, _b;
|
|
49
|
+
const result = await request("POST", "/api/v1/roles", {
|
|
50
|
+
key: input.key,
|
|
51
|
+
name: input.name,
|
|
52
|
+
description: input.description,
|
|
53
|
+
is_default: (_a = input.isDefault) != null ? _a : false,
|
|
54
|
+
permissions: (_b = input.permissions) != null ? _b : []
|
|
55
|
+
});
|
|
56
|
+
return toRole(result.role);
|
|
57
|
+
},
|
|
58
|
+
async updateRole(roleId, input) {
|
|
59
|
+
const body = {};
|
|
60
|
+
if (input.name !== void 0) body.name = input.name;
|
|
61
|
+
if (input.description !== void 0) body.description = input.description;
|
|
62
|
+
if (input.permissions !== void 0) body.permissions = input.permissions;
|
|
63
|
+
if (input.isDefault !== void 0) body.is_default = input.isDefault;
|
|
64
|
+
const result = await request(
|
|
65
|
+
"PATCH",
|
|
66
|
+
`/api/v1/roles/${encodeURIComponent(roleId)}`,
|
|
67
|
+
body
|
|
68
|
+
);
|
|
69
|
+
return toRole(result.role);
|
|
70
|
+
},
|
|
71
|
+
async deleteRole(roleId) {
|
|
72
|
+
await request(
|
|
73
|
+
"DELETE",
|
|
74
|
+
`/api/v1/roles/${encodeURIComponent(roleId)}`
|
|
75
|
+
);
|
|
76
|
+
},
|
|
77
|
+
async setDefaultRole(roleId) {
|
|
78
|
+
return this.updateRole(roleId, { isDefault: true });
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
function toRole(raw) {
|
|
83
|
+
return {
|
|
84
|
+
id: raw.id,
|
|
85
|
+
projectId: raw.project_id,
|
|
86
|
+
key: raw.key,
|
|
87
|
+
name: raw.name,
|
|
88
|
+
description: raw.description,
|
|
89
|
+
isDefault: raw.is_default,
|
|
90
|
+
permissions: raw.permissions,
|
|
91
|
+
createdAt: raw.created_at,
|
|
92
|
+
updatedAt: raw.updated_at
|
|
93
|
+
};
|
|
94
|
+
}
|
|
9
95
|
|
|
10
96
|
// src/index.ts
|
|
11
97
|
function defineRbac(config, opts) {
|
|
98
|
+
var _a;
|
|
12
99
|
if ((opts == null ? void 0 : opts.validate) !== false) {
|
|
13
100
|
validateRbacConfig(config);
|
|
14
101
|
}
|
|
@@ -22,7 +109,7 @@ function defineRbac(config, opts) {
|
|
|
22
109
|
}
|
|
23
110
|
const roles = {};
|
|
24
111
|
for (const [key, role] of Object.entries(config.roles)) {
|
|
25
|
-
roles[key] = { key, name: role.name, grants: role.grants };
|
|
112
|
+
roles[key] = { key, name: role.name, grants: role.grants, isDefault: (_a = role.isDefault) != null ? _a : false };
|
|
26
113
|
}
|
|
27
114
|
const permissions = {};
|
|
28
115
|
for (const [key, resource] of Object.entries(config.resources)) {
|
|
@@ -44,6 +131,7 @@ function defineRbac(config, opts) {
|
|
|
44
131
|
export {
|
|
45
132
|
RbacSyncClient,
|
|
46
133
|
computeRbacDiff,
|
|
134
|
+
createRoleManagement,
|
|
47
135
|
defineRbac,
|
|
48
136
|
formatRbacDiff,
|
|
49
137
|
hashConditionSource,
|