snipe-auth-rbac 0.3.1 → 0.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/dist/admin/index.cjs +201 -11
- package/dist/admin/index.cjs.map +1 -1
- package/dist/admin/index.d.cts +112 -3
- package/dist/admin/index.d.ts +112 -3
- package/dist/admin/index.js +200 -12
- package/dist/admin/index.js.map +1 -1
- package/dist/{chunk-NRDW233A.js → chunk-5UAIIOKT.js} +65 -1
- package/dist/chunk-5UAIIOKT.js.map +1 -0
- package/dist/{chunk-C76JHCKM.js → chunk-XHPBUCFN.js} +33 -1
- package/dist/chunk-XHPBUCFN.js.map +1 -0
- package/dist/index-CJqb5nY5.d.cts +191 -0
- package/dist/index-nfrns9Ye.d.ts +191 -0
- package/dist/index.cjs +42 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -118
- package/dist/index.d.ts +3 -118
- package/dist/index.js +4 -2
- package/dist/react/index.cjs +106 -11
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +34 -59
- package/dist/react/index.d.ts +34 -59
- package/dist/react/index.js +14 -13
- package/dist/react/index.js.map +1 -1
- package/dist/types-Oj9yfWvz.d.cts +132 -0
- package/dist/types-Oj9yfWvz.d.ts +132 -0
- package/package.json +1 -1
- package/sql/0001_initial.sql +137 -2
- package/dist/chunk-C76JHCKM.js.map +0 -1
- package/dist/chunk-NRDW233A.js.map +0 -1
- package/dist/types-DxvFudPF.d.cts +0 -69
- package/dist/types-DxvFudPF.d.ts +0 -69
package/dist/admin/index.cjs
CHANGED
|
@@ -25,8 +25,10 @@ __export(admin_exports, {
|
|
|
25
25
|
PermissionsMatrix: () => PermissionsMatrix,
|
|
26
26
|
RolesList: () => RolesList,
|
|
27
27
|
createSupabaseAdminClient: () => createSupabaseAdminClient,
|
|
28
|
+
extractResourceDependencies: () => extractResourceDependencies,
|
|
28
29
|
useAdminCompanies: () => useAdminCompanies,
|
|
29
30
|
useAdminCompanyMembers: () => useAdminCompanyMembers,
|
|
31
|
+
useAdminResourceDependencies: () => useAdminResourceDependencies,
|
|
30
32
|
useAdminRolePermissions: () => useAdminRolePermissions,
|
|
31
33
|
useAdminRoles: () => useAdminRoles,
|
|
32
34
|
useApplyTemplateDefaults: () => useApplyTemplateDefaults,
|
|
@@ -47,9 +49,46 @@ var ACTION_COLUMN = {
|
|
|
47
49
|
update: "can_update",
|
|
48
50
|
delete: "can_delete"
|
|
49
51
|
};
|
|
52
|
+
var GRANTED_VIA_COLUMN = {
|
|
53
|
+
read: "read_granted_via",
|
|
54
|
+
write: "write_granted_via",
|
|
55
|
+
update: "update_granted_via",
|
|
56
|
+
delete: "delete_granted_via"
|
|
57
|
+
};
|
|
58
|
+
function extractResourceDependencies(resources) {
|
|
59
|
+
const out = [];
|
|
60
|
+
for (const r of resources) {
|
|
61
|
+
for (const edge of r.dependsOn ?? []) {
|
|
62
|
+
const child = typeof edge === "string" ? edge : edge.resource;
|
|
63
|
+
const actions = typeof edge === "string" ? ["read"] : edge.actions ?? ["read"];
|
|
64
|
+
for (const action of actions) {
|
|
65
|
+
out.push({
|
|
66
|
+
parent_resource: r.resource,
|
|
67
|
+
child_resource: child,
|
|
68
|
+
action
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return out;
|
|
74
|
+
}
|
|
50
75
|
function createSupabaseAdminClient(opts) {
|
|
51
76
|
const sb = opts.supabase;
|
|
52
77
|
const rbac = sb.schema("rbac");
|
|
78
|
+
const syncResourceDependencies = async (edges) => {
|
|
79
|
+
const payload = edges.map((e) => ({
|
|
80
|
+
parent_resource: e.parent_resource,
|
|
81
|
+
child_resource: e.child_resource,
|
|
82
|
+
action: e.action
|
|
83
|
+
}));
|
|
84
|
+
const { error } = await rbac.rpc("replace_resource_dependencies", {
|
|
85
|
+
p_edges: payload
|
|
86
|
+
});
|
|
87
|
+
if (error) {
|
|
88
|
+
throw new Error(`syncResourceDependencies: ${error.message}`);
|
|
89
|
+
}
|
|
90
|
+
return edges.length;
|
|
91
|
+
};
|
|
53
92
|
return {
|
|
54
93
|
async syncResources(resources) {
|
|
55
94
|
if (resources.length === 0) {
|
|
@@ -66,6 +105,15 @@ function createSupabaseAdminClient(opts) {
|
|
|
66
105
|
if (error) {
|
|
67
106
|
throw new Error(`syncResources: ${error.message}`);
|
|
68
107
|
}
|
|
108
|
+
const edges = extractResourceDependencies(resources);
|
|
109
|
+
try {
|
|
110
|
+
await syncResourceDependencies(edges);
|
|
111
|
+
} catch (err) {
|
|
112
|
+
if (err instanceof Error && /resource_dependencies/i.test(err.message) && /(does not exist|relation .* does not exist)/i.test(err.message)) {
|
|
113
|
+
} else {
|
|
114
|
+
throw err;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
69
117
|
return resources.length;
|
|
70
118
|
},
|
|
71
119
|
async listRoles({ scope, companyId, templatesOnly }) {
|
|
@@ -115,18 +163,68 @@ function createSupabaseAdminClient(opts) {
|
|
|
115
163
|
throw new Error(`deleteRole: ${error.message}`);
|
|
116
164
|
}
|
|
117
165
|
},
|
|
118
|
-
async setRolePermissionCell({ role_id, resource, action, value }) {
|
|
119
|
-
const
|
|
166
|
+
async setRolePermissionCell({ role_id, resource, action, value, grantedVia }) {
|
|
167
|
+
const actionCol = ACTION_COLUMN[action];
|
|
168
|
+
const originCol = GRANTED_VIA_COLUMN[action];
|
|
120
169
|
const row = {
|
|
121
170
|
role_id,
|
|
122
171
|
resource,
|
|
123
|
-
[
|
|
172
|
+
[actionCol]: value
|
|
124
173
|
};
|
|
174
|
+
if (grantedVia !== void 0) {
|
|
175
|
+
row[originCol] = value ? grantedVia : null;
|
|
176
|
+
}
|
|
125
177
|
const { error } = await rbac.from("role_permissions").upsert(row, { onConflict: "role_id,resource" });
|
|
126
178
|
if (error) {
|
|
179
|
+
if (grantedVia !== void 0 && /column .*granted_via.* does not exist/i.test(error.message)) {
|
|
180
|
+
const fallbackRow = {
|
|
181
|
+
role_id,
|
|
182
|
+
resource,
|
|
183
|
+
[actionCol]: value
|
|
184
|
+
};
|
|
185
|
+
const { error: retryErr } = await rbac.from("role_permissions").upsert(fallbackRow, { onConflict: "role_id,resource" });
|
|
186
|
+
if (retryErr) {
|
|
187
|
+
throw new Error(`setRolePermissionCell: ${retryErr.message}`);
|
|
188
|
+
}
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
127
191
|
throw new Error(`setRolePermissionCell: ${error.message}`);
|
|
128
192
|
}
|
|
129
193
|
},
|
|
194
|
+
async batchSetRolePermissionCells(writes) {
|
|
195
|
+
if (writes.length === 0) {
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
199
|
+
for (const w of writes) {
|
|
200
|
+
const key = `${w.role_id}::${w.resource}`;
|
|
201
|
+
const existing = byKey.get(key) ?? {
|
|
202
|
+
role_id: w.role_id,
|
|
203
|
+
resource: w.resource
|
|
204
|
+
};
|
|
205
|
+
existing[ACTION_COLUMN[w.action]] = w.value;
|
|
206
|
+
if (w.grantedVia !== void 0) {
|
|
207
|
+
existing[GRANTED_VIA_COLUMN[w.action]] = w.value ? w.grantedVia : null;
|
|
208
|
+
}
|
|
209
|
+
byKey.set(key, existing);
|
|
210
|
+
}
|
|
211
|
+
const payload = Array.from(byKey.values());
|
|
212
|
+
const { error } = await rbac.from("role_permissions").upsert(payload, { onConflict: "role_id,resource" });
|
|
213
|
+
if (error) {
|
|
214
|
+
throw new Error(`batchSetRolePermissionCells: ${error.message}`);
|
|
215
|
+
}
|
|
216
|
+
},
|
|
217
|
+
syncResourceDependencies,
|
|
218
|
+
async listResourceDependencies() {
|
|
219
|
+
const { data, error } = await rbac.from("resource_dependencies").select("parent_resource, child_resource, action").order("parent_resource", { ascending: true });
|
|
220
|
+
if (error) {
|
|
221
|
+
if (/resource_dependencies/i.test(error.message) && /does not exist/i.test(error.message)) {
|
|
222
|
+
return [];
|
|
223
|
+
}
|
|
224
|
+
throw new Error(`listResourceDependencies: ${error.message}`);
|
|
225
|
+
}
|
|
226
|
+
return data ?? [];
|
|
227
|
+
},
|
|
130
228
|
async applyTemplateDefaults({ role_id, only_missing = true }) {
|
|
131
229
|
const { data, error } = await rbac.rpc("apply_template_defaults", {
|
|
132
230
|
p_role_id: role_id,
|
|
@@ -303,6 +401,13 @@ function useApplyTemplateDefaults() {
|
|
|
303
401
|
const transport = useAdminTransport();
|
|
304
402
|
return useMutation(transport.applyTemplateDefaults);
|
|
305
403
|
}
|
|
404
|
+
function useAdminResourceDependencies() {
|
|
405
|
+
const transport = useAdminTransport();
|
|
406
|
+
return useAsync(
|
|
407
|
+
() => transport.listResourceDependencies(),
|
|
408
|
+
[transport]
|
|
409
|
+
);
|
|
410
|
+
}
|
|
306
411
|
function useCreateCompany() {
|
|
307
412
|
const transport = useAdminTransport();
|
|
308
413
|
return useMutation(transport.createCompany);
|
|
@@ -313,7 +418,11 @@ function useInviteCompanyMember() {
|
|
|
313
418
|
}
|
|
314
419
|
function useRolePermissionGrid(roleId) {
|
|
315
420
|
const { data, isLoading, error, refresh } = useAdminRolePermissions(roleId);
|
|
421
|
+
const dependencies = useAdminResourceDependencies();
|
|
316
422
|
const setCell = useSetRolePermissionCell();
|
|
423
|
+
const transport = useAdminTransport();
|
|
424
|
+
const [isCascading, setCascading] = (0, import_react.useState)(false);
|
|
425
|
+
const [cascadeError, setCascadeError] = (0, import_react.useState)(null);
|
|
317
426
|
const grid = (0, import_react.useMemo)(() => {
|
|
318
427
|
const out = {};
|
|
319
428
|
for (const row of data ?? []) {
|
|
@@ -326,26 +435,100 @@ function useRolePermissionGrid(roleId) {
|
|
|
326
435
|
}
|
|
327
436
|
return out;
|
|
328
437
|
}, [data]);
|
|
438
|
+
const originGrid = (0, import_react.useMemo)(() => {
|
|
439
|
+
const out = {};
|
|
440
|
+
for (const row of data ?? []) {
|
|
441
|
+
out[row.resource] = {
|
|
442
|
+
read: row.read_granted_via ?? null,
|
|
443
|
+
write: row.write_granted_via ?? null,
|
|
444
|
+
update: row.update_granted_via ?? null,
|
|
445
|
+
delete: row.delete_granted_via ?? null
|
|
446
|
+
};
|
|
447
|
+
}
|
|
448
|
+
return out;
|
|
449
|
+
}, [data]);
|
|
450
|
+
const edgesByParent = (0, import_react.useMemo)(() => {
|
|
451
|
+
const map = /* @__PURE__ */ new Map();
|
|
452
|
+
for (const edge of dependencies.data ?? []) {
|
|
453
|
+
const list = map.get(edge.parent_resource) ?? [];
|
|
454
|
+
map.set(edge.parent_resource, [
|
|
455
|
+
...list,
|
|
456
|
+
{ child: edge.child_resource, action: edge.action }
|
|
457
|
+
]);
|
|
458
|
+
}
|
|
459
|
+
return map;
|
|
460
|
+
}, [dependencies.data]);
|
|
329
461
|
const updateCell = (0, import_react.useCallback)(
|
|
330
462
|
async (resource, action, value) => {
|
|
331
463
|
if (!roleId) {
|
|
332
464
|
return;
|
|
333
465
|
}
|
|
334
|
-
|
|
335
|
-
|
|
466
|
+
const writes = [
|
|
467
|
+
{ role_id: roleId, resource, action, value, grantedVia: null }
|
|
468
|
+
];
|
|
469
|
+
if (value) {
|
|
470
|
+
const edges = edgesByParent.get(resource) ?? [];
|
|
471
|
+
for (const edge of edges) {
|
|
472
|
+
if (edge.action !== action) {
|
|
473
|
+
continue;
|
|
474
|
+
}
|
|
475
|
+
const childRow = (data ?? []).find((r) => r.resource === edge.child);
|
|
476
|
+
const childValue = childRow?.[ACTION_FIELD[action]] === true;
|
|
477
|
+
const childOrigin = childRow?.[ORIGIN_FIELD[action]] ?? null;
|
|
478
|
+
if (childValue && childOrigin == null) {
|
|
479
|
+
continue;
|
|
480
|
+
}
|
|
481
|
+
writes.push({
|
|
482
|
+
role_id: roleId,
|
|
483
|
+
resource: edge.child,
|
|
484
|
+
action,
|
|
485
|
+
value: true,
|
|
486
|
+
grantedVia: resource
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
setCascading(true);
|
|
491
|
+
setCascadeError(null);
|
|
492
|
+
try {
|
|
493
|
+
const [first, ...rest] = writes;
|
|
494
|
+
if (first && rest.length === 0) {
|
|
495
|
+
await setCell.mutate(first);
|
|
496
|
+
} else {
|
|
497
|
+
await transport.batchSetRolePermissionCells(writes);
|
|
498
|
+
}
|
|
499
|
+
void refresh();
|
|
500
|
+
} catch (e) {
|
|
501
|
+
setCascadeError(e instanceof Error ? e : new Error(String(e)));
|
|
502
|
+
throw e;
|
|
503
|
+
} finally {
|
|
504
|
+
setCascading(false);
|
|
505
|
+
}
|
|
336
506
|
},
|
|
337
|
-
[roleId, setCell, refresh]
|
|
507
|
+
[roleId, setCell, refresh, edgesByParent, data, transport]
|
|
338
508
|
);
|
|
339
509
|
return {
|
|
340
510
|
grid,
|
|
341
|
-
|
|
342
|
-
|
|
511
|
+
originGrid,
|
|
512
|
+
isLoading: isLoading || dependencies.isLoading,
|
|
513
|
+
error: error ?? dependencies.error,
|
|
343
514
|
refresh,
|
|
344
515
|
updateCell,
|
|
345
|
-
isUpdating: setCell.isPending,
|
|
346
|
-
updateError: setCell.error
|
|
516
|
+
isUpdating: setCell.isPending || isCascading,
|
|
517
|
+
updateError: setCell.error ?? cascadeError
|
|
347
518
|
};
|
|
348
519
|
}
|
|
520
|
+
var ACTION_FIELD = {
|
|
521
|
+
read: "can_read",
|
|
522
|
+
write: "can_write",
|
|
523
|
+
update: "can_update",
|
|
524
|
+
delete: "can_delete"
|
|
525
|
+
};
|
|
526
|
+
var ORIGIN_FIELD = {
|
|
527
|
+
read: "read_granted_via",
|
|
528
|
+
write: "write_granted_via",
|
|
529
|
+
update: "update_granted_via",
|
|
530
|
+
delete: "delete_granted_via"
|
|
531
|
+
};
|
|
349
532
|
|
|
350
533
|
// src/admin/PermissionsMatrix.tsx
|
|
351
534
|
var import_react2 = require("react");
|
|
@@ -369,7 +552,7 @@ function groupResources(registry) {
|
|
|
369
552
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
370
553
|
var ACTIONS = ["read", "write", "update", "delete"];
|
|
371
554
|
function PermissionsMatrix(props) {
|
|
372
|
-
const { grid, isLoading, error, updateCell, isUpdating } = useRolePermissionGrid(props.roleId);
|
|
555
|
+
const { grid, originGrid, isLoading, error, updateCell, isUpdating } = useRolePermissionGrid(props.roleId);
|
|
373
556
|
const groups = (0, import_react2.useMemo)(
|
|
374
557
|
() => groupResources(props.resources),
|
|
375
558
|
[props.resources]
|
|
@@ -377,12 +560,17 @@ function PermissionsMatrix(props) {
|
|
|
377
560
|
const isCellEnabled = (resource, action) => {
|
|
378
561
|
return grid[resource]?.[action] ?? false;
|
|
379
562
|
};
|
|
563
|
+
const cellOrigin = (resource, action) => {
|
|
564
|
+
const origin = originGrid[resource]?.[action];
|
|
565
|
+
return origin == null ? "direct" : origin;
|
|
566
|
+
};
|
|
380
567
|
const setCell = async (resource, action, value) => {
|
|
381
568
|
await updateCell(resource, action, value);
|
|
382
569
|
};
|
|
383
570
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: props.children({
|
|
384
571
|
groups,
|
|
385
572
|
isCellEnabled,
|
|
573
|
+
cellOrigin,
|
|
386
574
|
setCell,
|
|
387
575
|
isLoading,
|
|
388
576
|
isUpdating,
|
|
@@ -517,8 +705,10 @@ function InviteMemberForm(props) {
|
|
|
517
705
|
PermissionsMatrix,
|
|
518
706
|
RolesList,
|
|
519
707
|
createSupabaseAdminClient,
|
|
708
|
+
extractResourceDependencies,
|
|
520
709
|
useAdminCompanies,
|
|
521
710
|
useAdminCompanyMembers,
|
|
711
|
+
useAdminResourceDependencies,
|
|
522
712
|
useAdminRolePermissions,
|
|
523
713
|
useAdminRoles,
|
|
524
714
|
useApplyTemplateDefaults,
|
package/dist/admin/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/admin/index.ts","../../src/admin/transport.ts","../../src/admin/hooks.tsx","../../src/admin/PermissionsMatrix.tsx","../../src/client.ts","../../src/admin/RolesList.tsx","../../src/admin/InviteMemberForm.tsx"],"sourcesContent":["/**\n * Admin entry — import from `snipe-auth-rbac/admin`.\n *\n * Two layers shipped here, all UI-kit-agnostic:\n *\n * 1. **Transport + hooks.** Pick `createSupabaseAdminClient(...)`\n * or implement `AdminTransport` yourself, then mount\n * `<AdminTransportProvider>` and pull data with the hooks.\n * 2. **Headless render-prop components.** `<PermissionsMatrix>`,\n * `<RolesList>`, `<InviteMemberForm>` own state + mutations\n * and hand the consumer a render-prop with everything needed\n * to draw the UI in any design system.\n *\n * For a styled reference (Tailwind + Radix shadcn primitives) see\n * `examples/react-admin/` — copy the page into your project, swap\n * the imports for your local UI kit, ship.\n */\n\nexport type {\n AdminCompany,\n AdminMember,\n AdminRole,\n AdminRolePermission,\n AdminTransport,\n} from \"./types.js\";\n\nexport {\n createSupabaseAdminClient,\n type SupabaseAdminClientOptions,\n} from \"./transport.js\";\n\nexport {\n AdminTransportProvider,\n type AdminTransportProviderProps,\n useAdminRoles,\n useAdminRolePermissions,\n useAdminCompanies,\n useAdminCompanyMembers,\n useCreateRole,\n useUpdateRole,\n useDeleteRole,\n useSetRolePermissionCell,\n useApplyTemplateDefaults,\n useCreateCompany,\n useInviteCompanyMember,\n useRolePermissionGrid,\n type RolePermissionGrid,\n} from \"./hooks.js\";\n\nexport {\n PermissionsMatrix,\n type PermissionsMatrixProps,\n type MatrixGroup,\n type MatrixRenderArgs,\n} from \"./PermissionsMatrix.js\";\n\nexport {\n RolesList,\n type RolesListProps,\n type RolesListRenderArgs,\n} from \"./RolesList.js\";\n\nexport {\n InviteMemberForm,\n type InviteMemberFormProps,\n type InviteMemberFormRenderArgs,\n} from \"./InviteMemberForm.js\";\n","/**\n * Default Supabase implementation of the admin transport. Hits the\n * package's tables in the `rbac` schema directly via `.schema('rbac').\n * from(...)` and the auth admin endpoint for invites.\n *\n * Adopters must add `rbac` to their PostgREST exposed-schemas list\n * (Supabase Studio → Settings → API → Exposed schemas) for these\n * calls to reach the tables.\n *\n * Projects that route admin writes through their own backend\n * (e.g. for audit logging or extra validation) skip this and\n * implement `AdminTransport` themselves.\n */\n\nimport type { Action, ResourceDescriptor } from \"../types.js\";\n\nimport type {\n AdminCompany,\n AdminMember,\n AdminRole,\n AdminRolePermission,\n AdminTransport,\n} from \"./types.js\";\n\ninterface RbacSchemaClient {\n from(table: string): {\n select: (cols: string) => {\n eq: (col: string, value: unknown) => any;\n is: (col: string, value: unknown) => any;\n order: (col: string, opts?: { ascending: boolean }) => any;\n };\n insert: (row: Record<string, unknown>) => {\n select: (cols: string) => { single: () => any };\n };\n update: (patch: Record<string, unknown>) => {\n eq: (col: string, value: unknown) => {\n select: (cols: string) => { single: () => any };\n };\n };\n upsert: (\n row: Record<string, unknown> | Array<Record<string, unknown>>,\n opts?: { onConflict: string },\n ) => Promise<{ error: { message: string } | null }>;\n delete: () => { eq: (col: string, value: unknown) => any };\n };\n rpc(\n fn: string,\n args: Record<string, unknown>,\n ): Promise<{ data: unknown; error: { message: string } | null }>;\n}\n\ninterface SupabaseAdmin {\n schema(name: string): RbacSchemaClient;\n auth: {\n admin: {\n inviteUserByEmail: (\n email: string,\n opts?: { data?: Record<string, unknown>; redirectTo?: string },\n ) => Promise<{ data: unknown; error: { message: string } | null }>;\n };\n };\n}\n\nexport interface SupabaseAdminClientOptions {\n supabase: SupabaseAdmin;\n /** Where the invitee should land after setting their password. */\n inviteRedirectUrl?: string;\n}\n\nconst ACTION_COLUMN: Record<Action, string> = {\n read: \"can_read\",\n write: \"can_write\",\n update: \"can_update\",\n delete: \"can_delete\",\n};\n\nexport function createSupabaseAdminClient(\n opts: SupabaseAdminClientOptions,\n): AdminTransport {\n const sb = opts.supabase;\n const rbac = sb.schema(\"rbac\");\n\n return {\n async syncResources(resources) {\n if (resources.length === 0) {\n return 0;\n }\n const payload = resources.map((r: ResourceDescriptor) => ({\n resource: r.resource,\n scope: r.scope,\n label: r.label,\n description: r.description ?? null,\n group_label: r.group ?? null,\n }));\n const { error } = await rbac\n .from(\"resources\")\n .upsert(payload, { onConflict: \"resource\" });\n if (error) {\n throw new Error(`syncResources: ${error.message}`);\n }\n return resources.length;\n },\n\n async listRoles({ scope, companyId, templatesOnly }) {\n let q = rbac.from(\"roles\").select(\"*\").eq(\"scope\", scope);\n if (templatesOnly) {\n q = q.is(\"company_id\", null);\n } else if (companyId !== undefined) {\n q = companyId === null ? q.is(\"company_id\", null) : q.eq(\"company_id\", companyId);\n }\n const { data, error } = await q.order(\"name\", { ascending: true });\n if (error) {\n throw new Error(`listRoles: ${error.message}`);\n }\n return (data ?? []) as AdminRole[];\n },\n\n async listRolePermissions(roleId) {\n const { data, error } = await rbac\n .from(\"role_permissions\")\n .select(\"*\")\n .eq(\"role_id\", roleId);\n if (error) {\n throw new Error(`listRolePermissions: ${error.message}`);\n }\n return (data ?? []) as AdminRolePermission[];\n },\n\n async createRole(input) {\n const row = {\n scope: input.scope,\n company_id: input.companyId ?? null,\n name: input.name,\n description: input.description ?? null,\n frontend_config: input.frontend_config ?? {},\n };\n const { data, error } = await rbac\n .from(\"roles\")\n .insert(row)\n .select(\"*\")\n .single();\n if (error) {\n throw new Error(`createRole: ${error.message}`);\n }\n return data as AdminRole;\n },\n\n async updateRole(id, patch) {\n const { data, error } = await rbac\n .from(\"roles\")\n .update(patch)\n .eq(\"id\", id)\n .select(\"*\")\n .single();\n if (error) {\n throw new Error(`updateRole: ${error.message}`);\n }\n return data as AdminRole;\n },\n\n async deleteRole(id) {\n const { error } = await rbac.from(\"roles\").delete().eq(\"id\", id);\n if (error) {\n throw new Error(`deleteRole: ${error.message}`);\n }\n },\n\n async setRolePermissionCell({ role_id, resource, action, value }) {\n const column = ACTION_COLUMN[action];\n const row: Record<string, unknown> = {\n role_id,\n resource,\n [column]: value,\n };\n const { error } = await rbac\n .from(\"role_permissions\")\n .upsert(row, { onConflict: \"role_id,resource\" });\n if (error) {\n throw new Error(`setRolePermissionCell: ${error.message}`);\n }\n },\n\n async applyTemplateDefaults({ role_id, only_missing = true }) {\n const { data, error } = await rbac.rpc(\"apply_template_defaults\", {\n p_role_id: role_id,\n p_only_missing: only_missing,\n });\n if (error) {\n throw new Error(`applyTemplateDefaults: ${error.message}`);\n }\n if (typeof data === \"number\") return data;\n return Number(data ?? 0);\n },\n\n async listCompanies() {\n const { data, error } = await rbac\n .from(\"companies\")\n .select(\"*\")\n .order(\"name\", { ascending: true });\n if (error) {\n throw new Error(`listCompanies: ${error.message}`);\n }\n return (data ?? []) as AdminCompany[];\n },\n\n async createCompany(input) {\n const { data, error } = await rbac\n .from(\"companies\")\n .insert({\n name: input.name,\n slug: input.slug ?? null,\n type: input.type ?? null,\n })\n .select(\"*\")\n .single();\n if (error) {\n throw new Error(`createCompany: ${error.message}`);\n }\n return data as AdminCompany;\n },\n\n async listCompanyMembers(companyId) {\n // The package doesn't ship a view that joins users + invitations\n // out of the box because the host's auth.users schema may differ.\n // Adopters that need a richer join replace this with their own\n // transport. Fallback: list raw assignments.\n const { data, error } = await rbac\n .from(\"user_company_roles\")\n .select(\"user_id, role_id, assigned_at\")\n .eq(\"company_id\", companyId);\n if (error) {\n throw new Error(`listCompanyMembers: ${error.message}`);\n }\n const grouped = new Map<string, AdminMember>();\n for (const row of (data ?? []) as Array<{\n user_id: string;\n role_id: string;\n assigned_at: string;\n }>) {\n const existing = grouped.get(row.user_id);\n if (existing) {\n existing.role_ids.push(row.role_id);\n } else {\n grouped.set(row.user_id, {\n user_id: row.user_id,\n email: null,\n full_name: null,\n role_ids: [row.role_id],\n invited_at: row.assigned_at,\n invitation_status: \"accepted\",\n });\n }\n }\n return Array.from(grouped.values());\n },\n\n async inviteCompanyMember({ companyId, email, roleIds }) {\n const { error } = await sb.auth.admin.inviteUserByEmail(email, {\n data: {\n rbac_company_id: companyId,\n rbac_role_ids: roleIds,\n },\n redirectTo: opts.inviteRedirectUrl,\n });\n if (error) {\n throw new Error(`inviteCompanyMember: ${error.message}`);\n }\n return { invited: true };\n },\n };\n}\n","/**\n * React hooks for the admin surface. UI-kit-agnostic — adopters\n * render whatever JSX they like with the data + mutations these\n * expose. A copy-paste reference page styled with Tailwind primitives\n * lives in `examples/react-admin/`.\n *\n * Pattern: each hook returns `{ data, isLoading, error, refresh }`\n * and where applicable `{ mutate }`. We deliberately avoid pulling in\n * react-query as a dependency so the package stays peer-light;\n * adopters that already use react-query can wrap these primitives\n * with an extra hook of their own (5 lines).\n */\n\nimport { createContext, useCallback, useContext, useEffect, useMemo, useState } from \"react\";\n\nimport type { Action, FrontendConfig, ResourceScope } from \"../types.js\";\n\nimport type {\n AdminCompany,\n AdminMember,\n AdminRole,\n AdminRolePermission,\n AdminTransport,\n} from \"./types.js\";\n\n// ─────────────────────────────────────────────────────────────────\n// Context — adopter mounts <AdminTransportProvider> once\n// ─────────────────────────────────────────────────────────────────\n\nconst AdminTransportContext = createContext<AdminTransport | null>(null);\n\nexport interface AdminTransportProviderProps {\n transport: AdminTransport;\n children: React.ReactNode;\n}\n\nexport function AdminTransportProvider(props: AdminTransportProviderProps) {\n return (\n <AdminTransportContext.Provider value={props.transport}>\n {props.children}\n </AdminTransportContext.Provider>\n );\n}\n\nfunction useAdminTransport(): AdminTransport {\n const t = useContext(AdminTransportContext);\n if (!t) {\n throw new Error(\n \"auth-rbac admin hooks require <AdminTransportProvider> — wrap your admin pages with one.\",\n );\n }\n return t;\n}\n\n// ─────────────────────────────────────────────────────────────────\n// Tiny generic async-state helper. Avoids reinventing react-query\n// while keeping the boilerplate per-hook to a single line.\n// ─────────────────────────────────────────────────────────────────\n\ninterface AsyncState<T> {\n data: T | null;\n isLoading: boolean;\n error: Error | null;\n}\n\nfunction useAsync<T>(loader: () => Promise<T>, deps: ReadonlyArray<unknown>) {\n const [state, setState] = useState<AsyncState<T>>({\n data: null,\n isLoading: true,\n error: null,\n });\n\n const refresh = useCallback(async () => {\n setState((s) => ({ ...s, isLoading: true, error: null }));\n try {\n const data = await loader();\n setState({ data, isLoading: false, error: null });\n } catch (e) {\n setState({\n data: null,\n isLoading: false,\n error: e instanceof Error ? e : new Error(String(e)),\n });\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, deps);\n\n useEffect(() => {\n void refresh();\n }, [refresh]);\n\n return { ...state, refresh };\n}\n\n// ─────────────────────────────────────────────────────────────────\n// Reads\n// ─────────────────────────────────────────────────────────────────\n\nexport function useAdminRoles(args: {\n scope: ResourceScope;\n companyId?: string | null;\n templatesOnly?: boolean;\n}) {\n const transport = useAdminTransport();\n return useAsync(\n () => transport.listRoles(args),\n [transport, args.scope, args.companyId, args.templatesOnly],\n );\n}\n\nexport function useAdminRolePermissions(roleId: string | null) {\n const transport = useAdminTransport();\n return useAsync(\n async () =>\n roleId == null ? [] : transport.listRolePermissions(roleId),\n [transport, roleId],\n );\n}\n\nexport function useAdminCompanies() {\n const transport = useAdminTransport();\n return useAsync(() => transport.listCompanies(), [transport]);\n}\n\nexport function useAdminCompanyMembers(companyId: string | null) {\n const transport = useAdminTransport();\n return useAsync(\n async () =>\n companyId == null ? [] : transport.listCompanyMembers(companyId),\n [transport, companyId],\n );\n}\n\n// ─────────────────────────────────────────────────────────────────\n// Mutations — return `{ mutate, isPending, error }`. Adopters wrap\n// these in their own toast / error-boundary as needed.\n// ─────────────────────────────────────────────────────────────────\n\ninterface MutationState {\n isPending: boolean;\n error: Error | null;\n}\n\nfunction useMutation<TArgs extends unknown[], TResult>(\n fn: (...args: TArgs) => Promise<TResult>,\n) {\n const [state, setState] = useState<MutationState>({\n isPending: false,\n error: null,\n });\n\n const mutate = useCallback(\n async (...args: TArgs): Promise<TResult> => {\n setState({ isPending: true, error: null });\n try {\n const result = await fn(...args);\n setState({ isPending: false, error: null });\n return result;\n } catch (e) {\n const err = e instanceof Error ? e : new Error(String(e));\n setState({ isPending: false, error: err });\n throw err;\n }\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [fn],\n );\n\n return { mutate, ...state };\n}\n\nexport function useCreateRole() {\n const transport = useAdminTransport();\n return useMutation(transport.createRole);\n}\n\nexport function useUpdateRole() {\n const transport = useAdminTransport();\n return useMutation(transport.updateRole);\n}\n\nexport function useDeleteRole() {\n const transport = useAdminTransport();\n return useMutation(transport.deleteRole);\n}\n\nexport function useSetRolePermissionCell() {\n const transport = useAdminTransport();\n return useMutation(transport.setRolePermissionCell);\n}\n\nexport function useApplyTemplateDefaults() {\n const transport = useAdminTransport();\n return useMutation(transport.applyTemplateDefaults);\n}\n\nexport function useCreateCompany() {\n const transport = useAdminTransport();\n return useMutation(transport.createCompany);\n}\n\nexport function useInviteCompanyMember() {\n const transport = useAdminTransport();\n return useMutation(transport.inviteCompanyMember);\n}\n\n// ─────────────────────────────────────────────────────────────────\n// Convenience: hold a role's full state (role + permission grid)\n// in one hook, with a `setCell` mutator that optimistically updates\n// the local cache and writes through to the transport.\n// ─────────────────────────────────────────────────────────────────\n\nexport interface RolePermissionGrid {\n // resource → action → boolean\n [resource: string]: { [A in Action]: boolean };\n}\n\nexport function useRolePermissionGrid(roleId: string | null) {\n const { data, isLoading, error, refresh } = useAdminRolePermissions(roleId);\n const setCell = useSetRolePermissionCell();\n\n const grid = useMemo<RolePermissionGrid>(() => {\n const out: RolePermissionGrid = {};\n for (const row of data ?? []) {\n out[row.resource] = {\n read: row.can_read,\n write: row.can_write,\n update: row.can_update,\n delete: row.can_delete,\n };\n }\n return out;\n }, [data]);\n\n const updateCell = useCallback(\n async (resource: string, action: Action, value: boolean) => {\n if (!roleId) {\n return;\n }\n await setCell.mutate({ role_id: roleId, resource, action, value });\n void refresh();\n },\n [roleId, setCell, refresh],\n );\n\n return {\n grid,\n isLoading,\n error,\n refresh,\n updateCell,\n isUpdating: setCell.isPending,\n updateError: setCell.error,\n };\n}\n","/**\n * Headless permissions matrix.\n *\n * Owns:\n * - reading the role's current permission grid\n * - debounced write-through on every cell toggle\n * - grouping resources by `group` for a sectioned UI\n *\n * Owns NOTHING about styling — the consumer renders all JSX via the\n * single `children` render-prop. A copy-paste reference styled with\n * Tailwind + Radix lives in `examples/react-admin/`.\n *\n * @example minimum viable adoption\n *\n * <PermissionsMatrix\n * roleId={role.id}\n * resources={resources.filter(r => r.scope === role.scope)}\n * >\n * {({ groups, isCellEnabled, setCell, isLoading }) =>\n * groups.map((g) => (\n * <section key={g.group}>\n * <h3>{g.group}</h3>\n * {g.resources.map((r) => (\n * <div key={r.resource}>\n * <span>{r.label}</span>\n * {([\"read\", \"write\", \"update\", \"delete\"] as const).map((a) => (\n * <input\n * key={a}\n * type=\"checkbox\"\n * checked={isCellEnabled(r.resource, a)}\n * disabled={isLoading}\n * onChange={(e) => setCell(r.resource, a, e.target.checked)}\n * />\n * ))}\n * </div>\n * ))}\n * </section>\n * ))\n * }\n * </PermissionsMatrix>\n */\n\nimport { useMemo } from \"react\";\n\nimport type {\n Action,\n ResourceDescriptor,\n} from \"../types.js\";\nimport { groupResources } from \"../client.js\";\n\nimport { useRolePermissionGrid } from \"./hooks.js\";\n\nexport interface MatrixGroup {\n group: string;\n resources: ResourceDescriptor[];\n}\n\nexport interface MatrixRenderArgs {\n /** Resources grouped by their `group` label, original insertion order. */\n groups: MatrixGroup[];\n /** Read a single cell from the current grid. */\n isCellEnabled: (resource: string, action: Action) => boolean;\n /** Write a single cell. Optimistic in the local cache + writes through. */\n setCell: (resource: string, action: Action, value: boolean) => Promise<void>;\n isLoading: boolean;\n isUpdating: boolean;\n error: Error | null;\n /** All four actions, exposed for the consumer to render headers. */\n actions: ReadonlyArray<Action>;\n}\n\nexport interface PermissionsMatrixProps {\n roleId: string | null;\n resources: ReadonlyArray<ResourceDescriptor>;\n children: (args: MatrixRenderArgs) => React.ReactNode;\n}\n\nconst ACTIONS = [\"read\", \"write\", \"update\", \"delete\"] as const;\n\nexport function PermissionsMatrix(props: PermissionsMatrixProps) {\n const { grid, isLoading, error, updateCell, isUpdating } =\n useRolePermissionGrid(props.roleId);\n\n const groups = useMemo<MatrixGroup[]>(\n () => groupResources(props.resources),\n [props.resources],\n );\n\n const isCellEnabled = (resource: string, action: Action): boolean => {\n return grid[resource]?.[action] ?? false;\n };\n\n const setCell = async (resource: string, action: Action, value: boolean) => {\n await updateCell(resource, action, value);\n };\n\n return (\n <>\n {props.children({\n groups,\n isCellEnabled,\n setCell,\n isLoading,\n isUpdating,\n error,\n actions: ACTIONS,\n })}\n </>\n );\n}\n","/**\n * Transport-agnostic client: turns an adopter-supplied\n * `AuthRbacFetcher` into a permission resolver. The React provider\n * wraps this; non-React consumers (Node scripts, edge functions)\n * can use it directly.\n */\n\nimport type {\n Action,\n AuthRbacFetcher,\n PermissionMap,\n ResourceDescriptor,\n ResourceRegistry,\n ResourceScope,\n UserProfile,\n} from \"./types.js\";\n\nexport interface AuthRbacClientOptions {\n fetcher: AuthRbacFetcher;\n /**\n * The host project's full resource list. Required so the resolver\n * can look up a resource's scope without a DB round-trip per call.\n * Re-using the same array the host syncs into the\n * `rbac.resources` table at boot keeps everything in lockstep.\n */\n resources: ResourceRegistry;\n}\n\nexport interface CanOptions {\n /**\n * Override the active company. Omit to use the company the\n * caller has currently activated (the React provider tracks\n * this; for direct client use you must pass it).\n */\n companyId?: string | null;\n}\n\n/**\n * Pure resolver. Given a hydrated profile it answers boolean\n * questions instantly — no I/O. The `resourceMap` is built once at\n * construction so per-call work is two map lookups.\n */\nexport function buildPermissionResolver(\n resources: ResourceRegistry,\n profile: UserProfile,\n defaultCompanyId: string | null,\n) {\n const scopeByResource = new Map<string, ResourceScope>(\n resources.map((r) => [r.resource, r.scope]),\n );\n\n const can = (\n resource: string,\n action: Action,\n options?: CanOptions,\n ): boolean => {\n if (profile.is_super_admin) {\n return true;\n }\n const scope = scopeByResource.get(resource);\n if (!scope) {\n // Unknown resource — fail closed.\n return false;\n }\n if (scope === \"system\") {\n return readGrid(profile.system_permissions, resource, action);\n }\n const companyId = options?.companyId ?? defaultCompanyId;\n if (!companyId) {\n return false;\n }\n const membership = profile.memberships.find(\n (m) => m.company_id === companyId,\n );\n if (!membership) {\n return false;\n }\n return readGrid(membership.permissions, resource, action);\n };\n\n return {\n can,\n /** Permission map for the active (or specified) company. */\n activePermissions: (companyId?: string | null): PermissionMap => {\n const id = companyId ?? defaultCompanyId;\n if (!id) {\n return {};\n }\n return (\n profile.memberships.find((m) => m.company_id === id)?.permissions ?? {}\n );\n },\n systemPermissions: (): PermissionMap => profile.system_permissions,\n };\n}\n\nfunction readGrid(\n map: PermissionMap,\n resource: string,\n action: Action,\n): boolean {\n const grid = map[resource];\n if (!grid) {\n return false;\n }\n return grid[action];\n}\n\n/**\n * Helper: groups a resource registry by `group` for the matrix UI.\n * Returns groups in insertion order with their resources.\n */\nexport function groupResources(\n registry: ResourceRegistry,\n): Array<{ group: string; resources: ResourceDescriptor[] }> {\n const order: string[] = [];\n const buckets = new Map<string, ResourceDescriptor[]>();\n for (const r of registry) {\n const key = r.group ?? \"Sonstige\";\n if (!buckets.has(key)) {\n buckets.set(key, []);\n order.push(key);\n }\n buckets.get(key)!.push(r);\n }\n return order.map((g) => ({ group: g, resources: buckets.get(g)! }));\n}\n\nexport type AuthRbacClient = ReturnType<typeof buildPermissionResolver>;\nexport type { AuthRbacClientOptions as ClientOptions };\n","/**\n * Headless roles-list controller. Tracks selection + create/delete\n * mutations; consumer renders the list, the new-role dialog, and\n * the destructive-action confirmation.\n */\n\nimport { useCallback, useState } from \"react\";\n\nimport type { ResourceScope } from \"../types.js\";\n\nimport {\n useAdminRoles,\n useCreateRole,\n useDeleteRole,\n} from \"./hooks.js\";\nimport type { AdminRole } from \"./types.js\";\n\nexport interface RolesListRenderArgs {\n roles: AdminRole[];\n isLoading: boolean;\n error: Error | null;\n\n selectedRoleId: string | null;\n selectRole: (id: string | null) => void;\n\n createRole: (input: {\n name: string;\n description?: string;\n }) => Promise<AdminRole>;\n isCreating: boolean;\n createError: Error | null;\n\n deleteRole: (id: string) => Promise<void>;\n isDeleting: boolean;\n deleteError: Error | null;\n\n refresh: () => Promise<void>;\n}\n\nexport interface RolesListProps {\n scope: ResourceScope;\n /** Required for company-scope. Pass `null` for templates. */\n companyId?: string | null;\n /** Pre-select the first role on load. Default: true. */\n autoSelectFirst?: boolean;\n children: (args: RolesListRenderArgs) => React.ReactNode;\n}\n\nexport function RolesList(props: RolesListProps) {\n const { scope, companyId, autoSelectFirst = true } = props;\n\n const list = useAdminRoles({ scope, companyId });\n const create = useCreateRole();\n const remove = useDeleteRole();\n\n const [selectedRoleId, setSelectedRoleId] = useState<string | null>(null);\n\n // Auto-select first role on load.\n if (\n autoSelectFirst &&\n selectedRoleId == null &&\n list.data != null &&\n list.data.length > 0\n ) {\n setSelectedRoleId(list.data[0]!.id);\n }\n\n const createRole = useCallback(\n async (input: { name: string; description?: string }) => {\n const role = await create.mutate({\n scope,\n companyId: companyId ?? null,\n name: input.name,\n description: input.description,\n });\n await list.refresh();\n setSelectedRoleId(role.id);\n return role;\n },\n [create, scope, companyId, list],\n );\n\n const deleteRole = useCallback(\n async (id: string) => {\n await remove.mutate(id);\n if (selectedRoleId === id) {\n setSelectedRoleId(null);\n }\n await list.refresh();\n },\n [remove, list, selectedRoleId],\n );\n\n return (\n <>\n {props.children({\n roles: list.data ?? [],\n isLoading: list.isLoading,\n error: list.error,\n selectedRoleId,\n selectRole: setSelectedRoleId,\n createRole,\n isCreating: create.isPending,\n createError: create.error,\n deleteRole,\n isDeleting: remove.isPending,\n deleteError: remove.error,\n refresh: list.refresh,\n })}\n </>\n );\n}\n","/**\n * Headless invite-member form state. Tracks email + selected role\n * ids, runs basic local validation, and exposes a submit handler\n * that calls the configured transport (Supabase Auth invite by\n * default).\n */\n\nimport { useCallback, useState } from \"react\";\n\nimport { useAdminRoles, useInviteCompanyMember } from \"./hooks.js\";\nimport type { AdminRole } from \"./types.js\";\n\nexport interface InviteMemberFormRenderArgs {\n // form state\n email: string;\n setEmail: (v: string) => void;\n selectedRoleIds: Set<string>;\n toggleRole: (roleId: string) => void;\n resetForm: () => void;\n\n // catalog\n roles: AdminRole[];\n rolesLoading: boolean;\n rolesError: Error | null;\n\n // submission\n submit: () => Promise<void>;\n isSubmitting: boolean;\n submitError: Error | null;\n submittedSuccessfully: boolean;\n\n // validation\n isValid: boolean;\n errors: { email?: string; roles?: string };\n}\n\nexport interface InviteMemberFormProps {\n companyId: string;\n /** Called after a successful invite — typically clears a dialog. */\n onSuccess?: () => void;\n children: (args: InviteMemberFormRenderArgs) => React.ReactNode;\n}\n\nexport function InviteMemberForm(props: InviteMemberFormProps) {\n const rolesQuery = useAdminRoles({\n scope: \"company\",\n companyId: props.companyId,\n });\n const invite = useInviteCompanyMember();\n\n const [email, setEmail] = useState(\"\");\n const [selectedRoleIds, setSelectedRoleIds] = useState<Set<string>>(\n new Set(),\n );\n const [submittedSuccessfully, setSubmittedSuccessfully] = useState(false);\n\n const toggleRole = useCallback((roleId: string) => {\n setSelectedRoleIds((prev) => {\n const next = new Set(prev);\n if (next.has(roleId)) {\n next.delete(roleId);\n } else {\n next.add(roleId);\n }\n return next;\n });\n }, []);\n\n const resetForm = useCallback(() => {\n setEmail(\"\");\n setSelectedRoleIds(new Set());\n setSubmittedSuccessfully(false);\n }, []);\n\n const errors: InviteMemberFormRenderArgs[\"errors\"] = {};\n if (email.trim() && !/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email.trim())) {\n errors.email = \"Bitte gib eine gültige E-Mail-Adresse ein.\";\n }\n if (selectedRoleIds.size === 0) {\n errors.roles = \"Bitte mindestens eine Rolle auswählen.\";\n }\n const isValid =\n email.trim().length > 0 &&\n Object.keys(errors).length === 0;\n\n const submit = useCallback(async () => {\n if (!isValid) {\n return;\n }\n await invite.mutate({\n companyId: props.companyId,\n email: email.trim(),\n roleIds: Array.from(selectedRoleIds),\n });\n setSubmittedSuccessfully(true);\n props.onSuccess?.();\n }, [invite, props, email, selectedRoleIds, isValid]);\n\n return (\n <>\n {props.children({\n email,\n setEmail,\n selectedRoleIds,\n toggleRole,\n resetForm,\n roles: rolesQuery.data ?? [],\n rolesLoading: rolesQuery.isLoading,\n rolesError: rolesQuery.error,\n submit,\n isSubmitting: invite.isPending,\n submitError: invite.error,\n submittedSuccessfully,\n isValid,\n errors,\n })}\n </>\n );\n}\n"],"mappings":"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","names":["import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime"]}
|
|
1
|
+
{"version":3,"sources":["../../src/admin/index.ts","../../src/admin/transport.ts","../../src/admin/hooks.tsx","../../src/admin/PermissionsMatrix.tsx","../../src/client.ts","../../src/admin/RolesList.tsx","../../src/admin/InviteMemberForm.tsx"],"sourcesContent":["/**\n * Admin entry — import from `snipe-auth-rbac/admin`.\n *\n * Two layers shipped here, all UI-kit-agnostic:\n *\n * 1. **Transport + hooks.** Pick `createSupabaseAdminClient(...)`\n * or implement `AdminTransport` yourself, then mount\n * `<AdminTransportProvider>` and pull data with the hooks.\n * 2. **Headless render-prop components.** `<PermissionsMatrix>`,\n * `<RolesList>`, `<InviteMemberForm>` own state + mutations\n * and hand the consumer a render-prop with everything needed\n * to draw the UI in any design system.\n *\n * For a styled reference (Tailwind + Radix shadcn primitives) see\n * `examples/react-admin/` — copy the page into your project, swap\n * the imports for your local UI kit, ship.\n */\n\nexport type {\n AdminCompany,\n AdminMember,\n AdminResourceDependency,\n AdminRole,\n AdminRolePermission,\n AdminTransport,\n} from \"./types.js\";\n\nexport {\n createSupabaseAdminClient,\n extractResourceDependencies,\n type SupabaseAdminClientOptions,\n} from \"./transport.js\";\n\nexport {\n AdminTransportProvider,\n type AdminTransportProviderProps,\n useAdminRoles,\n useAdminRolePermissions,\n useAdminCompanies,\n useAdminCompanyMembers,\n useAdminResourceDependencies,\n useCreateRole,\n useUpdateRole,\n useDeleteRole,\n useSetRolePermissionCell,\n useApplyTemplateDefaults,\n useCreateCompany,\n useInviteCompanyMember,\n useRolePermissionGrid,\n type RolePermissionGrid,\n type RolePermissionOriginGrid,\n} from \"./hooks.js\";\n\nexport {\n PermissionsMatrix,\n type PermissionsMatrixProps,\n type MatrixGroup,\n type MatrixRenderArgs,\n} from \"./PermissionsMatrix.js\";\n\nexport {\n RolesList,\n type RolesListProps,\n type RolesListRenderArgs,\n} from \"./RolesList.js\";\n\nexport {\n InviteMemberForm,\n type InviteMemberFormProps,\n type InviteMemberFormRenderArgs,\n} from \"./InviteMemberForm.js\";\n","/**\n * Default Supabase implementation of the admin transport. Hits the\n * package's tables in the `rbac` schema directly via `.schema('rbac').\n * from(...)` and the auth admin endpoint for invites.\n *\n * Adopters must add `rbac` to their PostgREST exposed-schemas list\n * (Supabase Studio → Settings → API → Exposed schemas) for these\n * calls to reach the tables.\n *\n * Projects that route admin writes through their own backend\n * (e.g. for audit logging or extra validation) skip this and\n * implement `AdminTransport` themselves.\n */\n\nimport type { Action, ResourceDescriptor } from \"../types.js\";\n\nimport type {\n AdminCompany,\n AdminMember,\n AdminResourceDependency,\n AdminRole,\n AdminRolePermission,\n AdminTransport,\n} from \"./types.js\";\n\ninterface RbacSchemaClient {\n from(table: string): {\n select: (cols: string) => {\n eq: (col: string, value: unknown) => any;\n is: (col: string, value: unknown) => any;\n order: (col: string, opts?: { ascending: boolean }) => any;\n };\n insert: (row: Record<string, unknown>) => {\n select: (cols: string) => { single: () => any };\n };\n update: (patch: Record<string, unknown>) => {\n eq: (col: string, value: unknown) => {\n select: (cols: string) => { single: () => any };\n };\n };\n upsert: (\n row: Record<string, unknown> | Array<Record<string, unknown>>,\n opts?: { onConflict: string },\n ) => Promise<{ error: { message: string } | null }>;\n delete: () => { eq: (col: string, value: unknown) => any };\n };\n rpc(\n fn: string,\n args: Record<string, unknown>,\n ): Promise<{ data: unknown; error: { message: string } | null }>;\n}\n\ninterface SupabaseAdmin {\n schema(name: string): RbacSchemaClient;\n auth: {\n admin: {\n inviteUserByEmail: (\n email: string,\n opts?: { data?: Record<string, unknown>; redirectTo?: string },\n ) => Promise<{ data: unknown; error: { message: string } | null }>;\n };\n };\n}\n\nexport interface SupabaseAdminClientOptions {\n supabase: SupabaseAdmin;\n /** Where the invitee should land after setting their password. */\n inviteRedirectUrl?: string;\n}\n\nconst ACTION_COLUMN: Record<Action, string> = {\n read: \"can_read\",\n write: \"can_write\",\n update: \"can_update\",\n delete: \"can_delete\",\n};\n\nconst GRANTED_VIA_COLUMN: Record<Action, string> = {\n read: \"read_granted_via\",\n write: \"write_granted_via\",\n update: \"update_granted_via\",\n delete: \"delete_granted_via\",\n};\n\n/**\n * Pull `dependsOn` edges out of a registry array and flatten them\n * into one row per (parent, child, action). Shared helper used by\n * `syncResources` and by adopters who want to sync dependencies\n * manually.\n */\nexport function extractResourceDependencies(\n resources: ReadonlyArray<ResourceDescriptor>,\n): AdminResourceDependency[] {\n const out: AdminResourceDependency[] = [];\n for (const r of resources) {\n for (const edge of r.dependsOn ?? []) {\n const child = typeof edge === \"string\" ? edge : edge.resource;\n const actions =\n typeof edge === \"string\" ? ([\"read\"] as const) : (edge.actions ?? [\"read\"]);\n for (const action of actions) {\n out.push({\n parent_resource: r.resource,\n child_resource: child,\n action,\n });\n }\n }\n }\n return out;\n}\n\nexport function createSupabaseAdminClient(\n opts: SupabaseAdminClientOptions,\n): AdminTransport {\n const sb = opts.supabase;\n const rbac = sb.schema(\"rbac\");\n\n const syncResourceDependencies = async (\n edges: ReadonlyArray<AdminResourceDependency>,\n ): Promise<number> => {\n // Atomic replace-all via the package's RPC. Sidesteps PostgREST's\n // refusal of wildcard deletes and gives a single round-trip.\n const payload = edges.map((e) => ({\n parent_resource: e.parent_resource,\n child_resource: e.child_resource,\n action: e.action,\n }));\n const { error } = await rbac.rpc(\"replace_resource_dependencies\", {\n p_edges: payload,\n });\n if (error) {\n throw new Error(`syncResourceDependencies: ${error.message}`);\n }\n return edges.length;\n };\n\n return {\n async syncResources(resources) {\n if (resources.length === 0) {\n return 0;\n }\n const payload = resources.map((r: ResourceDescriptor) => ({\n resource: r.resource,\n scope: r.scope,\n label: r.label,\n description: r.description ?? null,\n group_label: r.group ?? null,\n }));\n const { error } = await rbac\n .from(\"resources\")\n .upsert(payload, { onConflict: \"resource\" });\n if (error) {\n throw new Error(`syncResources: ${error.message}`);\n }\n // 0.4.0+: also sync dependency edges declared via `dependsOn`.\n // Pre-0.4.0 SQL won't have `rbac.resource_dependencies` yet —\n // syncResourceDependencies tolerates that case internally and\n // surfaces other errors normally.\n const edges = extractResourceDependencies(resources);\n try {\n await syncResourceDependencies(edges);\n } catch (err) {\n if (\n err instanceof Error &&\n /resource_dependencies/i.test(err.message) &&\n /(does not exist|relation .* does not exist)/i.test(err.message)\n ) {\n // Pre-0.4.0 SQL — silently skip.\n } else {\n throw err;\n }\n }\n return resources.length;\n },\n\n async listRoles({ scope, companyId, templatesOnly }) {\n let q = rbac.from(\"roles\").select(\"*\").eq(\"scope\", scope);\n if (templatesOnly) {\n q = q.is(\"company_id\", null);\n } else if (companyId !== undefined) {\n q = companyId === null ? q.is(\"company_id\", null) : q.eq(\"company_id\", companyId);\n }\n const { data, error } = await q.order(\"name\", { ascending: true });\n if (error) {\n throw new Error(`listRoles: ${error.message}`);\n }\n return (data ?? []) as AdminRole[];\n },\n\n async listRolePermissions(roleId) {\n const { data, error } = await rbac\n .from(\"role_permissions\")\n .select(\"*\")\n .eq(\"role_id\", roleId);\n if (error) {\n throw new Error(`listRolePermissions: ${error.message}`);\n }\n return (data ?? []) as AdminRolePermission[];\n },\n\n async createRole(input) {\n const row = {\n scope: input.scope,\n company_id: input.companyId ?? null,\n name: input.name,\n description: input.description ?? null,\n frontend_config: input.frontend_config ?? {},\n };\n const { data, error } = await rbac\n .from(\"roles\")\n .insert(row)\n .select(\"*\")\n .single();\n if (error) {\n throw new Error(`createRole: ${error.message}`);\n }\n return data as AdminRole;\n },\n\n async updateRole(id, patch) {\n const { data, error } = await rbac\n .from(\"roles\")\n .update(patch)\n .eq(\"id\", id)\n .select(\"*\")\n .single();\n if (error) {\n throw new Error(`updateRole: ${error.message}`);\n }\n return data as AdminRole;\n },\n\n async deleteRole(id) {\n const { error } = await rbac.from(\"roles\").delete().eq(\"id\", id);\n if (error) {\n throw new Error(`deleteRole: ${error.message}`);\n }\n },\n\n async setRolePermissionCell({ role_id, resource, action, value, grantedVia }) {\n const actionCol = ACTION_COLUMN[action];\n const originCol = GRANTED_VIA_COLUMN[action];\n // grantedVia semantics:\n // undefined → don't touch the origin column (legacy callers)\n // null → explicit \"this is a direct grant\" — set origin\n // to NULL even if a previous parent owned it\n // string → record the parent name\n const row: Record<string, unknown> = {\n role_id,\n resource,\n [actionCol]: value,\n };\n if (grantedVia !== undefined) {\n // When clearing the action (value=false) we always clear the\n // origin too. Otherwise we record whatever the caller passed.\n row[originCol] = value ? grantedVia : null;\n }\n const { error } = await rbac\n .from(\"role_permissions\")\n .upsert(row, { onConflict: \"role_id,resource\" });\n if (error) {\n // Tolerate pre-0.4.0 SQL that doesn't have the origin column\n // — retry without the origin field so existing adopters can\n // still toggle cells. The matrix UI's cascade simply won't\n // produce the implied badge until they migrate.\n if (\n grantedVia !== undefined &&\n /column .*granted_via.* does not exist/i.test(error.message)\n ) {\n const fallbackRow: Record<string, unknown> = {\n role_id,\n resource,\n [actionCol]: value,\n };\n const { error: retryErr } = await rbac\n .from(\"role_permissions\")\n .upsert(fallbackRow, { onConflict: \"role_id,resource\" });\n if (retryErr) {\n throw new Error(`setRolePermissionCell: ${retryErr.message}`);\n }\n return;\n }\n throw new Error(`setRolePermissionCell: ${error.message}`);\n }\n },\n\n async batchSetRolePermissionCells(writes) {\n if (writes.length === 0) {\n return;\n }\n // Group writes by (role_id, resource) so the upsert payload has\n // at most one row per matrix cell — otherwise the upsert would\n // need conflict resolution on its own input.\n const byKey = new Map<string, Record<string, unknown>>();\n for (const w of writes) {\n const key = `${w.role_id}::${w.resource}`;\n const existing = byKey.get(key) ?? {\n role_id: w.role_id,\n resource: w.resource,\n };\n existing[ACTION_COLUMN[w.action]] = w.value;\n if (w.grantedVia !== undefined) {\n existing[GRANTED_VIA_COLUMN[w.action]] = w.value ? w.grantedVia : null;\n }\n byKey.set(key, existing);\n }\n const payload = Array.from(byKey.values());\n const { error } = await rbac\n .from(\"role_permissions\")\n .upsert(payload, { onConflict: \"role_id,resource\" });\n if (error) {\n throw new Error(`batchSetRolePermissionCells: ${error.message}`);\n }\n },\n\n syncResourceDependencies,\n\n async listResourceDependencies() {\n // `.order(...)` returns an awaitable filter chain in the\n // Supabase JS runtime — using it here keeps the mock interface\n // in this file happy without widening it.\n const { data, error } = await rbac\n .from(\"resource_dependencies\")\n .select(\"parent_resource, child_resource, action\")\n .order(\"parent_resource\", { ascending: true });\n if (error) {\n // Pre-0.4.0 SQL: table doesn't exist. Treat as \"no\n // dependencies declared\" so legacy callers don't blow up.\n if (\n /resource_dependencies/i.test(error.message) &&\n /does not exist/i.test(error.message)\n ) {\n return [];\n }\n throw new Error(`listResourceDependencies: ${error.message}`);\n }\n return (data ?? []) as AdminResourceDependency[];\n },\n\n async applyTemplateDefaults({ role_id, only_missing = true }) {\n const { data, error } = await rbac.rpc(\"apply_template_defaults\", {\n p_role_id: role_id,\n p_only_missing: only_missing,\n });\n if (error) {\n throw new Error(`applyTemplateDefaults: ${error.message}`);\n }\n if (typeof data === \"number\") return data;\n return Number(data ?? 0);\n },\n\n async listCompanies() {\n const { data, error } = await rbac\n .from(\"companies\")\n .select(\"*\")\n .order(\"name\", { ascending: true });\n if (error) {\n throw new Error(`listCompanies: ${error.message}`);\n }\n return (data ?? []) as AdminCompany[];\n },\n\n async createCompany(input) {\n const { data, error } = await rbac\n .from(\"companies\")\n .insert({\n name: input.name,\n slug: input.slug ?? null,\n type: input.type ?? null,\n })\n .select(\"*\")\n .single();\n if (error) {\n throw new Error(`createCompany: ${error.message}`);\n }\n return data as AdminCompany;\n },\n\n async listCompanyMembers(companyId) {\n // The package doesn't ship a view that joins users + invitations\n // out of the box because the host's auth.users schema may differ.\n // Adopters that need a richer join replace this with their own\n // transport. Fallback: list raw assignments.\n const { data, error } = await rbac\n .from(\"user_company_roles\")\n .select(\"user_id, role_id, assigned_at\")\n .eq(\"company_id\", companyId);\n if (error) {\n throw new Error(`listCompanyMembers: ${error.message}`);\n }\n const grouped = new Map<string, AdminMember>();\n for (const row of (data ?? []) as Array<{\n user_id: string;\n role_id: string;\n assigned_at: string;\n }>) {\n const existing = grouped.get(row.user_id);\n if (existing) {\n existing.role_ids.push(row.role_id);\n } else {\n grouped.set(row.user_id, {\n user_id: row.user_id,\n email: null,\n full_name: null,\n role_ids: [row.role_id],\n invited_at: row.assigned_at,\n invitation_status: \"accepted\",\n });\n }\n }\n return Array.from(grouped.values());\n },\n\n async inviteCompanyMember({ companyId, email, roleIds }) {\n const { error } = await sb.auth.admin.inviteUserByEmail(email, {\n data: {\n rbac_company_id: companyId,\n rbac_role_ids: roleIds,\n },\n redirectTo: opts.inviteRedirectUrl,\n });\n if (error) {\n throw new Error(`inviteCompanyMember: ${error.message}`);\n }\n return { invited: true };\n },\n };\n}\n","/**\n * React hooks for the admin surface. UI-kit-agnostic — adopters\n * render whatever JSX they like with the data + mutations these\n * expose. A copy-paste reference page styled with Tailwind primitives\n * lives in `examples/react-admin/`.\n *\n * Pattern: each hook returns `{ data, isLoading, error, refresh }`\n * and where applicable `{ mutate }`. We deliberately avoid pulling in\n * react-query as a dependency so the package stays peer-light;\n * adopters that already use react-query can wrap these primitives\n * with an extra hook of their own (5 lines).\n */\n\nimport { createContext, useCallback, useContext, useEffect, useMemo, useState } from \"react\";\n\nimport type { Action, FrontendConfig, ResourceScope } from \"../types.js\";\n\nimport type {\n AdminCompany,\n AdminMember,\n AdminResourceDependency,\n AdminRole,\n AdminRolePermission,\n AdminTransport,\n} from \"./types.js\";\n\n// ─────────────────────────────────────────────────────────────────\n// Context — adopter mounts <AdminTransportProvider> once\n// ─────────────────────────────────────────────────────────────────\n\nconst AdminTransportContext = createContext<AdminTransport | null>(null);\n\nexport interface AdminTransportProviderProps {\n transport: AdminTransport;\n children: React.ReactNode;\n}\n\nexport function AdminTransportProvider(props: AdminTransportProviderProps) {\n return (\n <AdminTransportContext.Provider value={props.transport}>\n {props.children}\n </AdminTransportContext.Provider>\n );\n}\n\nfunction useAdminTransport(): AdminTransport {\n const t = useContext(AdminTransportContext);\n if (!t) {\n throw new Error(\n \"auth-rbac admin hooks require <AdminTransportProvider> — wrap your admin pages with one.\",\n );\n }\n return t;\n}\n\n// ─────────────────────────────────────────────────────────────────\n// Tiny generic async-state helper. Avoids reinventing react-query\n// while keeping the boilerplate per-hook to a single line.\n// ─────────────────────────────────────────────────────────────────\n\ninterface AsyncState<T> {\n data: T | null;\n isLoading: boolean;\n error: Error | null;\n}\n\nfunction useAsync<T>(loader: () => Promise<T>, deps: ReadonlyArray<unknown>) {\n const [state, setState] = useState<AsyncState<T>>({\n data: null,\n isLoading: true,\n error: null,\n });\n\n const refresh = useCallback(async () => {\n setState((s) => ({ ...s, isLoading: true, error: null }));\n try {\n const data = await loader();\n setState({ data, isLoading: false, error: null });\n } catch (e) {\n setState({\n data: null,\n isLoading: false,\n error: e instanceof Error ? e : new Error(String(e)),\n });\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, deps);\n\n useEffect(() => {\n void refresh();\n }, [refresh]);\n\n return { ...state, refresh };\n}\n\n// ─────────────────────────────────────────────────────────────────\n// Reads\n// ─────────────────────────────────────────────────────────────────\n\nexport function useAdminRoles(args: {\n scope: ResourceScope;\n companyId?: string | null;\n templatesOnly?: boolean;\n}) {\n const transport = useAdminTransport();\n return useAsync(\n () => transport.listRoles(args),\n [transport, args.scope, args.companyId, args.templatesOnly],\n );\n}\n\nexport function useAdminRolePermissions(roleId: string | null) {\n const transport = useAdminTransport();\n return useAsync(\n async () =>\n roleId == null ? [] : transport.listRolePermissions(roleId),\n [transport, roleId],\n );\n}\n\nexport function useAdminCompanies() {\n const transport = useAdminTransport();\n return useAsync(() => transport.listCompanies(), [transport]);\n}\n\nexport function useAdminCompanyMembers(companyId: string | null) {\n const transport = useAdminTransport();\n return useAsync(\n async () =>\n companyId == null ? [] : transport.listCompanyMembers(companyId),\n [transport, companyId],\n );\n}\n\n// ─────────────────────────────────────────────────────────────────\n// Mutations — return `{ mutate, isPending, error }`. Adopters wrap\n// these in their own toast / error-boundary as needed.\n// ─────────────────────────────────────────────────────────────────\n\ninterface MutationState {\n isPending: boolean;\n error: Error | null;\n}\n\nfunction useMutation<TArgs extends unknown[], TResult>(\n fn: (...args: TArgs) => Promise<TResult>,\n) {\n const [state, setState] = useState<MutationState>({\n isPending: false,\n error: null,\n });\n\n const mutate = useCallback(\n async (...args: TArgs): Promise<TResult> => {\n setState({ isPending: true, error: null });\n try {\n const result = await fn(...args);\n setState({ isPending: false, error: null });\n return result;\n } catch (e) {\n const err = e instanceof Error ? e : new Error(String(e));\n setState({ isPending: false, error: err });\n throw err;\n }\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [fn],\n );\n\n return { mutate, ...state };\n}\n\nexport function useCreateRole() {\n const transport = useAdminTransport();\n return useMutation(transport.createRole);\n}\n\nexport function useUpdateRole() {\n const transport = useAdminTransport();\n return useMutation(transport.updateRole);\n}\n\nexport function useDeleteRole() {\n const transport = useAdminTransport();\n return useMutation(transport.deleteRole);\n}\n\nexport function useSetRolePermissionCell() {\n const transport = useAdminTransport();\n return useMutation(transport.setRolePermissionCell);\n}\n\nexport function useApplyTemplateDefaults() {\n const transport = useAdminTransport();\n return useMutation(transport.applyTemplateDefaults);\n}\n\n/**\n * 0.4.0+. Materialised dependency edges. Loaded once per admin\n * session — the underlying table mutates only on app boot (via\n * `syncResources` → `syncResourceDependencies`).\n */\nexport function useAdminResourceDependencies() {\n const transport = useAdminTransport();\n return useAsync(\n () => transport.listResourceDependencies(),\n [transport],\n );\n}\n\nexport function useCreateCompany() {\n const transport = useAdminTransport();\n return useMutation(transport.createCompany);\n}\n\nexport function useInviteCompanyMember() {\n const transport = useAdminTransport();\n return useMutation(transport.inviteCompanyMember);\n}\n\n// ─────────────────────────────────────────────────────────────────\n// Convenience: hold a role's full state (role + permission grid)\n// in one hook, with a `setCell` mutator that optimistically updates\n// the local cache and writes through to the transport.\n// ─────────────────────────────────────────────────────────────────\n\nexport interface RolePermissionGrid {\n // resource → action → boolean\n [resource: string]: { [A in Action]: boolean };\n}\n\n/**\n * 0.4.0+. Per-cell origin tracking — `null` means a direct admin\n * grant, a string is the name of the parent resource whose\n * `dependsOn` edge implied the row. Used by the matrix UI to render\n * the \"Implied by …\" badge.\n */\nexport interface RolePermissionOriginGrid {\n [resource: string]: { [A in Action]: string | null };\n}\n\nexport function useRolePermissionGrid(roleId: string | null) {\n const { data, isLoading, error, refresh } = useAdminRolePermissions(roleId);\n const dependencies = useAdminResourceDependencies();\n const setCell = useSetRolePermissionCell();\n const transport = useAdminTransport();\n const [isCascading, setCascading] = useState(false);\n const [cascadeError, setCascadeError] = useState<Error | null>(null);\n\n const grid = useMemo<RolePermissionGrid>(() => {\n const out: RolePermissionGrid = {};\n for (const row of data ?? []) {\n out[row.resource] = {\n read: row.can_read,\n write: row.can_write,\n update: row.can_update,\n delete: row.can_delete,\n };\n }\n return out;\n }, [data]);\n\n const originGrid = useMemo<RolePermissionOriginGrid>(() => {\n const out: RolePermissionOriginGrid = {};\n for (const row of data ?? []) {\n out[row.resource] = {\n read: row.read_granted_via ?? null,\n write: row.write_granted_via ?? null,\n update: row.update_granted_via ?? null,\n delete: row.delete_granted_via ?? null,\n };\n }\n return out;\n }, [data]);\n\n // Index dependency edges by parent for O(1) cascade lookup.\n const edgesByParent = useMemo(() => {\n const map = new Map<\n string,\n ReadonlyArray<{ child: string; action: Action }>\n >();\n for (const edge of dependencies.data ?? []) {\n const list = map.get(edge.parent_resource) ?? [];\n map.set(edge.parent_resource, [\n ...list,\n { child: edge.child_resource, action: edge.action },\n ]);\n }\n return map;\n }, [dependencies.data]);\n\n const updateCell = useCallback(\n async (resource: string, action: Action, value: boolean) => {\n if (!roleId) {\n return;\n }\n // Direct grant (or direct revoke) — origin column flips to NULL.\n // The cascade below handles implied rows separately.\n const writes: Array<{\n role_id: string;\n resource: string;\n action: Action;\n value: boolean;\n grantedVia: string | null;\n }> = [\n { role_id: roleId, resource, action, value, grantedVia: null },\n ];\n\n if (value) {\n // Toggle-on cascade — for each dependsOn edge whose action\n // matches, add an implied row UNLESS the child already has\n // the action directly granted (don't downgrade direct →\n // implied). Same-action only: a `read` toggle cascades read\n // to children that declare read on the edge.\n const edges = edgesByParent.get(resource) ?? [];\n for (const edge of edges) {\n if (edge.action !== action) {\n continue;\n }\n const childRow = (data ?? []).find((r) => r.resource === edge.child);\n const childValue =\n childRow?.[ACTION_FIELD[action] as keyof typeof childRow] === true;\n const childOrigin =\n (childRow?.[\n ORIGIN_FIELD[action] as keyof typeof childRow\n ] as string | null | undefined) ?? null;\n if (childValue && childOrigin == null) {\n // Already direct-granted — leave alone so we don't\n // downgrade to implied.\n continue;\n }\n writes.push({\n role_id: roleId,\n resource: edge.child,\n action,\n value: true,\n grantedVia: resource,\n });\n }\n }\n // No cascade on toggle-off — per-cell override semantics.\n // Children stay as they are; the admin can revoke each one\n // individually if needed.\n\n setCascading(true);\n setCascadeError(null);\n try {\n const [first, ...rest] = writes;\n if (first && rest.length === 0) {\n await setCell.mutate(first);\n } else {\n await transport.batchSetRolePermissionCells(writes);\n }\n void refresh();\n } catch (e) {\n setCascadeError(e instanceof Error ? e : new Error(String(e)));\n throw e;\n } finally {\n setCascading(false);\n }\n },\n [roleId, setCell, refresh, edgesByParent, data, transport],\n );\n\n return {\n grid,\n originGrid,\n isLoading: isLoading || dependencies.isLoading,\n error: error ?? dependencies.error,\n refresh,\n updateCell,\n isUpdating: setCell.isPending || isCascading,\n updateError: setCell.error ?? cascadeError,\n };\n}\n\nconst ACTION_FIELD: Record<Action, string> = {\n read: \"can_read\",\n write: \"can_write\",\n update: \"can_update\",\n delete: \"can_delete\",\n};\n\nconst ORIGIN_FIELD: Record<Action, string> = {\n read: \"read_granted_via\",\n write: \"write_granted_via\",\n update: \"update_granted_via\",\n delete: \"delete_granted_via\",\n};\n","/**\n * Headless permissions matrix.\n *\n * Owns:\n * - reading the role's current permission grid\n * - debounced write-through on every cell toggle\n * - grouping resources by `group` for a sectioned UI\n *\n * Owns NOTHING about styling — the consumer renders all JSX via the\n * single `children` render-prop. A copy-paste reference styled with\n * Tailwind + Radix lives in `examples/react-admin/`.\n *\n * @example minimum viable adoption\n *\n * <PermissionsMatrix\n * roleId={role.id}\n * resources={resources.filter(r => r.scope === role.scope)}\n * >\n * {({ groups, isCellEnabled, setCell, isLoading }) =>\n * groups.map((g) => (\n * <section key={g.group}>\n * <h3>{g.group}</h3>\n * {g.resources.map((r) => (\n * <div key={r.resource}>\n * <span>{r.label}</span>\n * {([\"read\", \"write\", \"update\", \"delete\"] as const).map((a) => (\n * <input\n * key={a}\n * type=\"checkbox\"\n * checked={isCellEnabled(r.resource, a)}\n * disabled={isLoading}\n * onChange={(e) => setCell(r.resource, a, e.target.checked)}\n * />\n * ))}\n * </div>\n * ))}\n * </section>\n * ))\n * }\n * </PermissionsMatrix>\n */\n\nimport { useMemo } from \"react\";\n\nimport type {\n Action,\n ResourceDescriptor,\n} from \"../types.js\";\nimport { groupResources } from \"../client.js\";\n\nimport { useRolePermissionGrid } from \"./hooks.js\";\n\nexport interface MatrixGroup {\n group: string;\n resources: ResourceDescriptor[];\n}\n\nexport interface MatrixRenderArgs {\n /** Resources grouped by their `group` label, original insertion order. */\n groups: MatrixGroup[];\n /** Read a single cell from the current grid. */\n isCellEnabled: (resource: string, action: Action) => boolean;\n /**\n * Origin of a single cell — `'direct'` for a direct admin grant\n * (or off), or the name of the parent resource whose `dependsOn`\n * edge implied the row. The consumer renders an \"Implied by …\"\n * badge whenever this returns a non-`'direct'` value.\n *\n * Available since 0.4.0. With pre-0.4.0 SQL (no granted_via\n * columns) this always returns `'direct'`.\n */\n cellOrigin: (resource: string, action: Action) => \"direct\" | string;\n /**\n * Write a single cell. Optimistic in the local cache + writes\n * through. On toggle-on, also writes implied rows for every\n * `dependsOn` edge whose `actions` include the toggled action —\n * those rows carry the parent's name in\n * `<action>_granted_via`. Toggle-off never cascades.\n */\n setCell: (resource: string, action: Action, value: boolean) => Promise<void>;\n isLoading: boolean;\n isUpdating: boolean;\n error: Error | null;\n /** All four actions, exposed for the consumer to render headers. */\n actions: ReadonlyArray<Action>;\n}\n\nexport interface PermissionsMatrixProps {\n roleId: string | null;\n resources: ReadonlyArray<ResourceDescriptor>;\n children: (args: MatrixRenderArgs) => React.ReactNode;\n}\n\nconst ACTIONS = [\"read\", \"write\", \"update\", \"delete\"] as const;\n\nexport function PermissionsMatrix(props: PermissionsMatrixProps) {\n const { grid, originGrid, isLoading, error, updateCell, isUpdating } =\n useRolePermissionGrid(props.roleId);\n\n const groups = useMemo<MatrixGroup[]>(\n () => groupResources(props.resources),\n [props.resources],\n );\n\n const isCellEnabled = (resource: string, action: Action): boolean => {\n return grid[resource]?.[action] ?? false;\n };\n\n const cellOrigin = (\n resource: string,\n action: Action,\n ): \"direct\" | string => {\n const origin = originGrid[resource]?.[action];\n return origin == null ? \"direct\" : origin;\n };\n\n const setCell = async (resource: string, action: Action, value: boolean) => {\n await updateCell(resource, action, value);\n };\n\n return (\n <>\n {props.children({\n groups,\n isCellEnabled,\n cellOrigin,\n setCell,\n isLoading,\n isUpdating,\n error,\n actions: ACTIONS,\n })}\n </>\n );\n}\n","/**\n * Transport-agnostic client: turns an adopter-supplied\n * `AuthRbacFetcher` into a permission resolver. The React provider\n * wraps this; non-React consumers (Node scripts, edge functions)\n * can use it directly.\n */\n\nimport type {\n Action,\n AuthRbacFetcher,\n PermissionMap,\n ResourceDescriptor,\n ResourceRegistry,\n ResourceScope,\n UserProfile,\n} from \"./types.js\";\n\nexport interface AuthRbacClientOptions {\n fetcher: AuthRbacFetcher;\n /**\n * The host project's full resource list. Required so the resolver\n * can look up a resource's scope without a DB round-trip per call.\n * Re-using the same array the host syncs into the\n * `rbac.resources` table at boot keeps everything in lockstep.\n */\n resources: ResourceRegistry;\n}\n\nexport interface CanOptions {\n /**\n * Override the active company. Omit to use the company the\n * caller has currently activated (the React provider tracks\n * this; for direct client use you must pass it).\n */\n companyId?: string | null;\n}\n\n/**\n * Pure resolver. Given a hydrated profile it answers boolean\n * questions instantly — no I/O. The `resourceMap` is built once at\n * construction so per-call work is two map lookups.\n */\nexport function buildPermissionResolver(\n resources: ResourceRegistry,\n profile: UserProfile,\n defaultCompanyId: string | null,\n) {\n const scopeByResource = new Map<string, ResourceScope>(\n resources.map((r) => [r.resource, r.scope]),\n );\n\n const can = (\n resource: string,\n action: Action,\n options?: CanOptions,\n ): boolean => {\n if (profile.is_super_admin) {\n return true;\n }\n const scope = scopeByResource.get(resource);\n if (!scope) {\n // Unknown resource — fail closed.\n return false;\n }\n if (scope === \"system\") {\n return readGrid(profile.system_permissions, resource, action);\n }\n const companyId = options?.companyId ?? defaultCompanyId;\n if (!companyId) {\n return false;\n }\n const membership = profile.memberships.find(\n (m) => m.company_id === companyId,\n );\n if (!membership) {\n return false;\n }\n return readGrid(membership.permissions, resource, action);\n };\n\n /**\n * Direct-grant lookup: returns true only if the user has the\n * action granted on the resource as a direct admin grant —\n * `<action>_granted_via IS NULL` in `rbac.role_permissions`.\n * Implied rows (granted as a side-effect of a parent resource's\n * `dependsOn` cascade) return false here.\n *\n * Use for top-level navigation / list-page gating: a Verwalter\n * with only `leases:read` direct gets the Leases sidebar item but\n * not Tenants / Units / Properties, even though `can(...)` returns\n * true for those (because the implied rows let the lease detail\n * page render its joined data).\n *\n * Available since 0.4.0. For older SQL that doesn't return\n * `direct_*` maps, every cell answers false — equivalent to\n * \"no direct grants known\". Adopters running pre-0.4.0 SQL should\n * keep using `can(...)`.\n */\n const canAccessSection = (\n resource: string,\n action: Action = \"read\",\n options?: CanOptions,\n ): boolean => {\n if (profile.is_super_admin) {\n return true;\n }\n const scope = scopeByResource.get(resource);\n if (!scope) {\n return false;\n }\n if (scope === \"system\") {\n return readDirect(profile, action, resource);\n }\n const companyId = options?.companyId ?? defaultCompanyId;\n if (!companyId) {\n return false;\n }\n const membership = profile.memberships.find(\n (m) => m.company_id === companyId,\n );\n if (!membership) {\n return false;\n }\n return readDirectMembership(membership, action, resource);\n };\n\n return {\n can,\n canAccessSection,\n /** Permission map for the active (or specified) company. */\n activePermissions: (companyId?: string | null): PermissionMap => {\n const id = companyId ?? defaultCompanyId;\n if (!id) {\n return {};\n }\n return (\n profile.memberships.find((m) => m.company_id === id)?.permissions ?? {}\n );\n },\n systemPermissions: (): PermissionMap => profile.system_permissions,\n };\n}\n\nfunction readDirect(\n profile: UserProfile,\n action: Action,\n resource: string,\n): boolean {\n const map =\n action === \"read\"\n ? profile.system_direct_reads\n : action === \"write\"\n ? profile.system_direct_writes\n : action === \"update\"\n ? profile.system_direct_updates\n : profile.system_direct_deletes;\n return map?.[resource] === true;\n}\n\nfunction readDirectMembership(\n membership: { direct_reads?: Readonly<Record<string, boolean>>;\n direct_writes?: Readonly<Record<string, boolean>>;\n direct_updates?: Readonly<Record<string, boolean>>;\n direct_deletes?: Readonly<Record<string, boolean>>; },\n action: Action,\n resource: string,\n): boolean {\n const map =\n action === \"read\"\n ? membership.direct_reads\n : action === \"write\"\n ? membership.direct_writes\n : action === \"update\"\n ? membership.direct_updates\n : membership.direct_deletes;\n return map?.[resource] === true;\n}\n\nfunction readGrid(\n map: PermissionMap,\n resource: string,\n action: Action,\n): boolean {\n const grid = map[resource];\n if (!grid) {\n return false;\n }\n return grid[action];\n}\n\n/**\n * Helper: groups a resource registry by `group` for the matrix UI.\n * Returns groups in insertion order with their resources.\n */\nexport function groupResources(\n registry: ResourceRegistry,\n): Array<{ group: string; resources: ResourceDescriptor[] }> {\n const order: string[] = [];\n const buckets = new Map<string, ResourceDescriptor[]>();\n for (const r of registry) {\n const key = r.group ?? \"Sonstige\";\n if (!buckets.has(key)) {\n buckets.set(key, []);\n order.push(key);\n }\n buckets.get(key)!.push(r);\n }\n return order.map((g) => ({ group: g, resources: buckets.get(g)! }));\n}\n\nexport type AuthRbacClient = ReturnType<typeof buildPermissionResolver>;\nexport type { AuthRbacClientOptions as ClientOptions };\n","/**\n * Headless roles-list controller. Tracks selection + create/delete\n * mutations; consumer renders the list, the new-role dialog, and\n * the destructive-action confirmation.\n */\n\nimport { useCallback, useState } from \"react\";\n\nimport type { ResourceScope } from \"../types.js\";\n\nimport {\n useAdminRoles,\n useCreateRole,\n useDeleteRole,\n} from \"./hooks.js\";\nimport type { AdminRole } from \"./types.js\";\n\nexport interface RolesListRenderArgs {\n roles: AdminRole[];\n isLoading: boolean;\n error: Error | null;\n\n selectedRoleId: string | null;\n selectRole: (id: string | null) => void;\n\n createRole: (input: {\n name: string;\n description?: string;\n }) => Promise<AdminRole>;\n isCreating: boolean;\n createError: Error | null;\n\n deleteRole: (id: string) => Promise<void>;\n isDeleting: boolean;\n deleteError: Error | null;\n\n refresh: () => Promise<void>;\n}\n\nexport interface RolesListProps {\n scope: ResourceScope;\n /** Required for company-scope. Pass `null` for templates. */\n companyId?: string | null;\n /** Pre-select the first role on load. Default: true. */\n autoSelectFirst?: boolean;\n children: (args: RolesListRenderArgs) => React.ReactNode;\n}\n\nexport function RolesList(props: RolesListProps) {\n const { scope, companyId, autoSelectFirst = true } = props;\n\n const list = useAdminRoles({ scope, companyId });\n const create = useCreateRole();\n const remove = useDeleteRole();\n\n const [selectedRoleId, setSelectedRoleId] = useState<string | null>(null);\n\n // Auto-select first role on load.\n if (\n autoSelectFirst &&\n selectedRoleId == null &&\n list.data != null &&\n list.data.length > 0\n ) {\n setSelectedRoleId(list.data[0]!.id);\n }\n\n const createRole = useCallback(\n async (input: { name: string; description?: string }) => {\n const role = await create.mutate({\n scope,\n companyId: companyId ?? null,\n name: input.name,\n description: input.description,\n });\n await list.refresh();\n setSelectedRoleId(role.id);\n return role;\n },\n [create, scope, companyId, list],\n );\n\n const deleteRole = useCallback(\n async (id: string) => {\n await remove.mutate(id);\n if (selectedRoleId === id) {\n setSelectedRoleId(null);\n }\n await list.refresh();\n },\n [remove, list, selectedRoleId],\n );\n\n return (\n <>\n {props.children({\n roles: list.data ?? [],\n isLoading: list.isLoading,\n error: list.error,\n selectedRoleId,\n selectRole: setSelectedRoleId,\n createRole,\n isCreating: create.isPending,\n createError: create.error,\n deleteRole,\n isDeleting: remove.isPending,\n deleteError: remove.error,\n refresh: list.refresh,\n })}\n </>\n );\n}\n","/**\n * Headless invite-member form state. Tracks email + selected role\n * ids, runs basic local validation, and exposes a submit handler\n * that calls the configured transport (Supabase Auth invite by\n * default).\n */\n\nimport { useCallback, useState } from \"react\";\n\nimport { useAdminRoles, useInviteCompanyMember } from \"./hooks.js\";\nimport type { AdminRole } from \"./types.js\";\n\nexport interface InviteMemberFormRenderArgs {\n // form state\n email: string;\n setEmail: (v: string) => void;\n selectedRoleIds: Set<string>;\n toggleRole: (roleId: string) => void;\n resetForm: () => void;\n\n // catalog\n roles: AdminRole[];\n rolesLoading: boolean;\n rolesError: Error | null;\n\n // submission\n submit: () => Promise<void>;\n isSubmitting: boolean;\n submitError: Error | null;\n submittedSuccessfully: boolean;\n\n // validation\n isValid: boolean;\n errors: { email?: string; roles?: string };\n}\n\nexport interface InviteMemberFormProps {\n companyId: string;\n /** Called after a successful invite — typically clears a dialog. */\n onSuccess?: () => void;\n children: (args: InviteMemberFormRenderArgs) => React.ReactNode;\n}\n\nexport function InviteMemberForm(props: InviteMemberFormProps) {\n const rolesQuery = useAdminRoles({\n scope: \"company\",\n companyId: props.companyId,\n });\n const invite = useInviteCompanyMember();\n\n const [email, setEmail] = useState(\"\");\n const [selectedRoleIds, setSelectedRoleIds] = useState<Set<string>>(\n new Set(),\n );\n const [submittedSuccessfully, setSubmittedSuccessfully] = useState(false);\n\n const toggleRole = useCallback((roleId: string) => {\n setSelectedRoleIds((prev) => {\n const next = new Set(prev);\n if (next.has(roleId)) {\n next.delete(roleId);\n } else {\n next.add(roleId);\n }\n return next;\n });\n }, []);\n\n const resetForm = useCallback(() => {\n setEmail(\"\");\n setSelectedRoleIds(new Set());\n setSubmittedSuccessfully(false);\n }, []);\n\n const errors: InviteMemberFormRenderArgs[\"errors\"] = {};\n if (email.trim() && !/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email.trim())) {\n errors.email = \"Bitte gib eine gültige E-Mail-Adresse ein.\";\n }\n if (selectedRoleIds.size === 0) {\n errors.roles = \"Bitte mindestens eine Rolle auswählen.\";\n }\n const isValid =\n email.trim().length > 0 &&\n Object.keys(errors).length === 0;\n\n const submit = useCallback(async () => {\n if (!isValid) {\n return;\n }\n await invite.mutate({\n companyId: props.companyId,\n email: email.trim(),\n roleIds: Array.from(selectedRoleIds),\n });\n setSubmittedSuccessfully(true);\n props.onSuccess?.();\n }, [invite, props, email, selectedRoleIds, isValid]);\n\n return (\n <>\n {props.children({\n email,\n setEmail,\n selectedRoleIds,\n toggleRole,\n resetForm,\n roles: rolesQuery.data ?? [],\n rolesLoading: rolesQuery.isLoading,\n rolesError: rolesQuery.error,\n submit,\n isSubmitting: invite.isPending,\n submitError: invite.error,\n submittedSuccessfully,\n isValid,\n errors,\n })}\n </>\n );\n}\n"],"mappings":"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","names":["import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime"]}
|