snipe-auth-rbac 0.5.0 → 0.6.1
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 +113 -6
- package/dist/admin/index.cjs.map +1 -1
- package/dist/admin/index.d.cts +99 -20
- package/dist/admin/index.d.ts +99 -20
- package/dist/admin/index.js +112 -6
- package/dist/admin/index.js.map +1 -1
- package/package.json +1 -1
- package/sql/0001_initial.sql +258 -59
package/sql/0001_initial.sql
CHANGED
|
@@ -176,6 +176,35 @@ CREATE TABLE IF NOT EXISTS rbac.resource_dependencies (
|
|
|
176
176
|
CONSTRAINT resource_dependencies_no_self CHECK (parent_resource <> child_resource)
|
|
177
177
|
);
|
|
178
178
|
|
|
179
|
+
-- 0.6.0+: Per-role admin override of implied permissions.
|
|
180
|
+
--
|
|
181
|
+
-- Granting a parent like `properties:read` implies a read on all of
|
|
182
|
+
-- properties.dependsOn at lookup time. Sometimes an admin wants a
|
|
183
|
+
-- role to have the parent but NOT a specific dependent — Anwalt
|
|
184
|
+
-- gets tenants/leases but must not see payments, even though
|
|
185
|
+
-- tenants.dependsOn includes payments.
|
|
186
|
+
--
|
|
187
|
+
-- A row here is a suppression: "this role does NOT have this
|
|
188
|
+
-- (resource, action), even if rbac.resource_dependencies would
|
|
189
|
+
-- otherwise imply it from a direct grant on the parent." Resolver
|
|
190
|
+
-- functions (rbac.user_can, rbac.user_profile) subtract these rows
|
|
191
|
+
-- from the expanded grant set.
|
|
192
|
+
--
|
|
193
|
+
-- Direct grants are unaffected — if the role has a direct
|
|
194
|
+
-- rbac.role_permissions row granting the action, that row takes
|
|
195
|
+
-- precedence over any override on the same cell.
|
|
196
|
+
CREATE TABLE IF NOT EXISTS rbac.role_permission_overrides (
|
|
197
|
+
role_id uuid NOT NULL REFERENCES rbac.roles(id) ON DELETE CASCADE,
|
|
198
|
+
resource text NOT NULL REFERENCES rbac.resources(resource) ON DELETE CASCADE,
|
|
199
|
+
action text NOT NULL CHECK (action IN ('read','write','update','delete')),
|
|
200
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
201
|
+
created_by uuid,
|
|
202
|
+
PRIMARY KEY (role_id, resource, action)
|
|
203
|
+
);
|
|
204
|
+
|
|
205
|
+
CREATE INDEX IF NOT EXISTS role_permission_overrides_resource_action_idx
|
|
206
|
+
ON rbac.role_permission_overrides (resource, action);
|
|
207
|
+
|
|
179
208
|
CREATE OR REPLACE FUNCTION rbac.check_role_resource_scope()
|
|
180
209
|
RETURNS trigger
|
|
181
210
|
LANGUAGE plpgsql
|
|
@@ -284,7 +313,11 @@ BEGIN
|
|
|
284
313
|
|
|
285
314
|
IF v_resource_scope = 'system' THEN
|
|
286
315
|
RETURN EXISTS (
|
|
287
|
-
-- Direct grant on the resource at system scope
|
|
316
|
+
-- Direct grant on the resource at system scope, on a
|
|
317
|
+
-- role without an override on this (resource, action).
|
|
318
|
+
-- 0.6.0+: overrides apply to direct grants too — if an
|
|
319
|
+
-- admin explicitly suppresses payments:read on a role,
|
|
320
|
+
-- the role doesn't get it even if a direct row exists.
|
|
288
321
|
SELECT 1
|
|
289
322
|
FROM rbac.user_system_roles usr
|
|
290
323
|
JOIN rbac.role_permissions rp ON rp.role_id = usr.role_id
|
|
@@ -296,12 +329,19 @@ BEGIN
|
|
|
296
329
|
WHEN 'update' THEN rp.can_update
|
|
297
330
|
WHEN 'delete' THEN rp.can_delete
|
|
298
331
|
END
|
|
332
|
+
AND NOT EXISTS (
|
|
333
|
+
SELECT 1 FROM rbac.role_permission_overrides ovr
|
|
334
|
+
WHERE ovr.role_id = rp.role_id
|
|
335
|
+
AND ovr.resource = p_resource
|
|
336
|
+
AND ovr.action = p_action
|
|
337
|
+
)
|
|
299
338
|
) OR EXISTS (
|
|
300
339
|
-- Implied via a direct grant on any parent at system
|
|
301
340
|
-- scope. resource_dependencies edges are scope-agnostic
|
|
302
341
|
-- (declared per-(parent,child,action)); the SCOPE of the
|
|
303
342
|
-- inheritance is governed by where the parent grant
|
|
304
|
-
-- lives.
|
|
343
|
+
-- lives. Override on the child suppresses the implied
|
|
344
|
+
-- access.
|
|
305
345
|
SELECT 1
|
|
306
346
|
FROM rbac.resource_dependencies d
|
|
307
347
|
JOIN rbac.user_system_roles usr ON true
|
|
@@ -316,6 +356,12 @@ BEGIN
|
|
|
316
356
|
WHEN 'update' THEN rp.can_update
|
|
317
357
|
WHEN 'delete' THEN rp.can_delete
|
|
318
358
|
END
|
|
359
|
+
AND NOT EXISTS (
|
|
360
|
+
SELECT 1 FROM rbac.role_permission_overrides ovr
|
|
361
|
+
WHERE ovr.role_id = rp.role_id
|
|
362
|
+
AND ovr.resource = p_resource
|
|
363
|
+
AND ovr.action = p_action
|
|
364
|
+
)
|
|
319
365
|
);
|
|
320
366
|
END IF;
|
|
321
367
|
|
|
@@ -338,6 +384,12 @@ BEGIN
|
|
|
338
384
|
WHEN 'update' THEN rp.can_update
|
|
339
385
|
WHEN 'delete' THEN rp.can_delete
|
|
340
386
|
END
|
|
387
|
+
AND NOT EXISTS (
|
|
388
|
+
SELECT 1 FROM rbac.role_permission_overrides ovr
|
|
389
|
+
WHERE ovr.role_id = rp.role_id
|
|
390
|
+
AND ovr.resource = p_resource
|
|
391
|
+
AND ovr.action = p_action
|
|
392
|
+
)
|
|
341
393
|
) OR EXISTS (
|
|
342
394
|
-- Implied via a direct grant on any parent in the same
|
|
343
395
|
-- company.
|
|
@@ -356,6 +408,12 @@ BEGIN
|
|
|
356
408
|
WHEN 'update' THEN rp.can_update
|
|
357
409
|
WHEN 'delete' THEN rp.can_delete
|
|
358
410
|
END
|
|
411
|
+
AND NOT EXISTS (
|
|
412
|
+
SELECT 1 FROM rbac.role_permission_overrides ovr
|
|
413
|
+
WHERE ovr.role_id = rp.role_id
|
|
414
|
+
AND ovr.resource = p_resource
|
|
415
|
+
AND ovr.action = p_action
|
|
416
|
+
)
|
|
359
417
|
);
|
|
360
418
|
END $$;
|
|
361
419
|
|
|
@@ -384,6 +442,10 @@ STABLE
|
|
|
384
442
|
SECURITY DEFINER
|
|
385
443
|
SET search_path = rbac, public
|
|
386
444
|
AS $$
|
|
445
|
+
-- 0.6.0+: every grant is computed per-(role,resource) so that
|
|
446
|
+
-- rbac.role_permission_overrides can subtract suppressions on a
|
|
447
|
+
-- per-role basis. Aggregating to per-resource happens AFTER the
|
|
448
|
+
-- per-role overrides filter.
|
|
387
449
|
WITH
|
|
388
450
|
system_roles AS (
|
|
389
451
|
SELECT r.id, r.name, r.is_super, r.frontend_config
|
|
@@ -391,32 +453,72 @@ AS $$
|
|
|
391
453
|
JOIN rbac.roles r ON r.id = usr.role_id
|
|
392
454
|
WHERE usr.user_id = p_user_id
|
|
393
455
|
),
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
456
|
+
system_role_grants AS (
|
|
457
|
+
SELECT usr.role_id, rp.resource,
|
|
458
|
+
rp.can_read AND NOT EXISTS (
|
|
459
|
+
SELECT 1 FROM rbac.role_permission_overrides ovr
|
|
460
|
+
WHERE ovr.role_id = rp.role_id AND ovr.resource = rp.resource AND ovr.action = 'read'
|
|
461
|
+
) AS can_read,
|
|
462
|
+
rp.can_write AND NOT EXISTS (
|
|
463
|
+
SELECT 1 FROM rbac.role_permission_overrides ovr
|
|
464
|
+
WHERE ovr.role_id = rp.role_id AND ovr.resource = rp.resource AND ovr.action = 'write'
|
|
465
|
+
) AS can_write,
|
|
466
|
+
rp.can_update AND NOT EXISTS (
|
|
467
|
+
SELECT 1 FROM rbac.role_permission_overrides ovr
|
|
468
|
+
WHERE ovr.role_id = rp.role_id AND ovr.resource = rp.resource AND ovr.action = 'update'
|
|
469
|
+
) AS can_update,
|
|
470
|
+
rp.can_delete AND NOT EXISTS (
|
|
471
|
+
SELECT 1 FROM rbac.role_permission_overrides ovr
|
|
472
|
+
WHERE ovr.role_id = rp.role_id AND ovr.resource = rp.resource AND ovr.action = 'delete'
|
|
473
|
+
) AS can_delete
|
|
401
474
|
FROM rbac.user_system_roles usr
|
|
402
475
|
JOIN rbac.role_permissions rp ON rp.role_id = usr.role_id
|
|
403
476
|
WHERE usr.user_id = p_user_id
|
|
404
|
-
GROUP BY rp.resource
|
|
405
477
|
),
|
|
406
|
-
|
|
407
|
-
|
|
478
|
+
system_direct AS (
|
|
479
|
+
SELECT resource,
|
|
480
|
+
bool_or(can_read) AS can_read,
|
|
481
|
+
bool_or(can_write) AS can_write,
|
|
482
|
+
bool_or(can_update) AS can_update,
|
|
483
|
+
bool_or(can_delete) AS can_delete
|
|
484
|
+
FROM system_role_grants
|
|
485
|
+
GROUP BY resource
|
|
486
|
+
),
|
|
487
|
+
-- Implied per role: for each parent direct-grant on a role, fan
|
|
488
|
+
-- out via resource_dependencies. Override on (role, child, action)
|
|
489
|
+
-- suppresses the child for that role.
|
|
490
|
+
system_implied_per_role AS (
|
|
491
|
+
SELECT g.role_id,
|
|
492
|
+
d.child_resource AS resource,
|
|
493
|
+
bool_or(d.action = 'read' AND g.can_read AND NOT EXISTS (
|
|
494
|
+
SELECT 1 FROM rbac.role_permission_overrides ovr
|
|
495
|
+
WHERE ovr.role_id = g.role_id AND ovr.resource = d.child_resource AND ovr.action = 'read'
|
|
496
|
+
)) AS can_read,
|
|
497
|
+
bool_or(d.action = 'write' AND g.can_write AND NOT EXISTS (
|
|
498
|
+
SELECT 1 FROM rbac.role_permission_overrides ovr
|
|
499
|
+
WHERE ovr.role_id = g.role_id AND ovr.resource = d.child_resource AND ovr.action = 'write'
|
|
500
|
+
)) AS can_write,
|
|
501
|
+
bool_or(d.action = 'update' AND g.can_update AND NOT EXISTS (
|
|
502
|
+
SELECT 1 FROM rbac.role_permission_overrides ovr
|
|
503
|
+
WHERE ovr.role_id = g.role_id AND ovr.resource = d.child_resource AND ovr.action = 'update'
|
|
504
|
+
)) AS can_update,
|
|
505
|
+
bool_or(d.action = 'delete' AND g.can_delete AND NOT EXISTS (
|
|
506
|
+
SELECT 1 FROM rbac.role_permission_overrides ovr
|
|
507
|
+
WHERE ovr.role_id = g.role_id AND ovr.resource = d.child_resource AND ovr.action = 'delete'
|
|
508
|
+
)) AS can_delete
|
|
509
|
+
FROM system_role_grants g
|
|
510
|
+
JOIN rbac.resource_dependencies d ON d.parent_resource = g.resource
|
|
511
|
+
GROUP BY g.role_id, d.child_resource
|
|
512
|
+
),
|
|
408
513
|
system_implied AS (
|
|
409
|
-
SELECT
|
|
410
|
-
bool_or(
|
|
411
|
-
bool_or(
|
|
412
|
-
bool_or(
|
|
413
|
-
bool_or(
|
|
414
|
-
FROM
|
|
415
|
-
|
|
416
|
-
GROUP BY d.child_resource
|
|
514
|
+
SELECT resource,
|
|
515
|
+
bool_or(can_read) AS can_read,
|
|
516
|
+
bool_or(can_write) AS can_write,
|
|
517
|
+
bool_or(can_update) AS can_update,
|
|
518
|
+
bool_or(can_delete) AS can_delete
|
|
519
|
+
FROM system_implied_per_role
|
|
520
|
+
GROUP BY resource
|
|
417
521
|
),
|
|
418
|
-
-- Expanded = direct UNION implied. bool_or merges duplicate
|
|
419
|
-
-- (resource, action) hits across the two sources.
|
|
420
522
|
system_expanded AS (
|
|
421
523
|
SELECT resource,
|
|
422
524
|
bool_or(can_read) AS can_read,
|
|
@@ -444,29 +546,67 @@ AS $$
|
|
|
444
546
|
WHERE ucr.user_id = p_user_id
|
|
445
547
|
GROUP BY c.id, c.name, c.slug
|
|
446
548
|
),
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
549
|
+
company_role_grants AS (
|
|
550
|
+
SELECT ucr.company_id, ucr.role_id, rp.resource,
|
|
551
|
+
rp.can_read AND NOT EXISTS (
|
|
552
|
+
SELECT 1 FROM rbac.role_permission_overrides ovr
|
|
553
|
+
WHERE ovr.role_id = rp.role_id AND ovr.resource = rp.resource AND ovr.action = 'read'
|
|
554
|
+
) AS can_read,
|
|
555
|
+
rp.can_write AND NOT EXISTS (
|
|
556
|
+
SELECT 1 FROM rbac.role_permission_overrides ovr
|
|
557
|
+
WHERE ovr.role_id = rp.role_id AND ovr.resource = rp.resource AND ovr.action = 'write'
|
|
558
|
+
) AS can_write,
|
|
559
|
+
rp.can_update AND NOT EXISTS (
|
|
560
|
+
SELECT 1 FROM rbac.role_permission_overrides ovr
|
|
561
|
+
WHERE ovr.role_id = rp.role_id AND ovr.resource = rp.resource AND ovr.action = 'update'
|
|
562
|
+
) AS can_update,
|
|
563
|
+
rp.can_delete AND NOT EXISTS (
|
|
564
|
+
SELECT 1 FROM rbac.role_permission_overrides ovr
|
|
565
|
+
WHERE ovr.role_id = rp.role_id AND ovr.resource = rp.resource AND ovr.action = 'delete'
|
|
566
|
+
) AS can_delete
|
|
455
567
|
FROM rbac.user_company_roles ucr
|
|
456
568
|
JOIN rbac.role_permissions rp ON rp.role_id = ucr.role_id
|
|
457
569
|
WHERE ucr.user_id = p_user_id
|
|
458
|
-
|
|
570
|
+
),
|
|
571
|
+
company_direct AS (
|
|
572
|
+
SELECT company_id, resource,
|
|
573
|
+
bool_or(can_read) AS can_read,
|
|
574
|
+
bool_or(can_write) AS can_write,
|
|
575
|
+
bool_or(can_update) AS can_update,
|
|
576
|
+
bool_or(can_delete) AS can_delete
|
|
577
|
+
FROM company_role_grants
|
|
578
|
+
GROUP BY company_id, resource
|
|
579
|
+
),
|
|
580
|
+
company_implied_per_role AS (
|
|
581
|
+
SELECT g.company_id, g.role_id, d.child_resource AS resource,
|
|
582
|
+
bool_or(d.action = 'read' AND g.can_read AND NOT EXISTS (
|
|
583
|
+
SELECT 1 FROM rbac.role_permission_overrides ovr
|
|
584
|
+
WHERE ovr.role_id = g.role_id AND ovr.resource = d.child_resource AND ovr.action = 'read'
|
|
585
|
+
)) AS can_read,
|
|
586
|
+
bool_or(d.action = 'write' AND g.can_write AND NOT EXISTS (
|
|
587
|
+
SELECT 1 FROM rbac.role_permission_overrides ovr
|
|
588
|
+
WHERE ovr.role_id = g.role_id AND ovr.resource = d.child_resource AND ovr.action = 'write'
|
|
589
|
+
)) AS can_write,
|
|
590
|
+
bool_or(d.action = 'update' AND g.can_update AND NOT EXISTS (
|
|
591
|
+
SELECT 1 FROM rbac.role_permission_overrides ovr
|
|
592
|
+
WHERE ovr.role_id = g.role_id AND ovr.resource = d.child_resource AND ovr.action = 'update'
|
|
593
|
+
)) AS can_update,
|
|
594
|
+
bool_or(d.action = 'delete' AND g.can_delete AND NOT EXISTS (
|
|
595
|
+
SELECT 1 FROM rbac.role_permission_overrides ovr
|
|
596
|
+
WHERE ovr.role_id = g.role_id AND ovr.resource = d.child_resource AND ovr.action = 'delete'
|
|
597
|
+
)) AS can_delete
|
|
598
|
+
FROM company_role_grants g
|
|
599
|
+
JOIN rbac.resource_dependencies d ON d.parent_resource = g.resource
|
|
600
|
+
GROUP BY g.company_id, g.role_id, d.child_resource
|
|
459
601
|
),
|
|
460
602
|
company_implied AS (
|
|
461
|
-
SELECT
|
|
462
|
-
|
|
463
|
-
bool_or(
|
|
464
|
-
bool_or(
|
|
465
|
-
bool_or(
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
JOIN rbac.resource_dependencies d ON d.parent_resource = cd.resource
|
|
469
|
-
GROUP BY cd.company_id, d.child_resource
|
|
603
|
+
SELECT company_id, resource,
|
|
604
|
+
bool_or(can_read) AS can_read,
|
|
605
|
+
bool_or(can_write) AS can_write,
|
|
606
|
+
bool_or(can_update) AS can_update,
|
|
607
|
+
bool_or(can_delete) AS can_delete
|
|
608
|
+
FROM company_implied_per_role
|
|
609
|
+
GROUP BY company_id, resource
|
|
470
610
|
),
|
|
471
611
|
company_expanded AS (
|
|
472
612
|
SELECT company_id, resource,
|
|
@@ -481,22 +621,32 @@ AS $$
|
|
|
481
621
|
) u
|
|
482
622
|
GROUP BY company_id, resource
|
|
483
623
|
),
|
|
484
|
-
--
|
|
624
|
+
-- direct_<action> maps reflect the underlying row set on
|
|
625
|
+
-- rbac.role_permissions — NOT post-override. canAccessSection
|
|
626
|
+
-- asks "is there a direct row" for navigation purposes, not "does
|
|
627
|
+
-- the role effectively have the action" — those are different
|
|
628
|
+
-- questions and the UI needs both.
|
|
485
629
|
system_perms AS (
|
|
486
|
-
SELECT resource,
|
|
487
|
-
can_read AS direct_read,
|
|
488
|
-
can_write AS direct_write,
|
|
489
|
-
can_update AS direct_update,
|
|
490
|
-
can_delete AS direct_delete
|
|
491
|
-
FROM
|
|
630
|
+
SELECT rp.resource,
|
|
631
|
+
bool_or(rp.can_read) AS direct_read,
|
|
632
|
+
bool_or(rp.can_write) AS direct_write,
|
|
633
|
+
bool_or(rp.can_update) AS direct_update,
|
|
634
|
+
bool_or(rp.can_delete) AS direct_delete
|
|
635
|
+
FROM rbac.user_system_roles usr
|
|
636
|
+
JOIN rbac.role_permissions rp ON rp.role_id = usr.role_id
|
|
637
|
+
WHERE usr.user_id = p_user_id
|
|
638
|
+
GROUP BY rp.resource
|
|
492
639
|
),
|
|
493
640
|
company_perms AS (
|
|
494
|
-
SELECT company_id, resource,
|
|
495
|
-
can_read AS direct_read,
|
|
496
|
-
can_write AS direct_write,
|
|
497
|
-
can_update AS direct_update,
|
|
498
|
-
can_delete AS direct_delete
|
|
499
|
-
FROM
|
|
641
|
+
SELECT ucr.company_id, rp.resource,
|
|
642
|
+
bool_or(rp.can_read) AS direct_read,
|
|
643
|
+
bool_or(rp.can_write) AS direct_write,
|
|
644
|
+
bool_or(rp.can_update) AS direct_update,
|
|
645
|
+
bool_or(rp.can_delete) AS direct_delete
|
|
646
|
+
FROM rbac.user_company_roles ucr
|
|
647
|
+
JOIN rbac.role_permissions rp ON rp.role_id = ucr.role_id
|
|
648
|
+
WHERE ucr.user_id = p_user_id
|
|
649
|
+
GROUP BY ucr.company_id, rp.resource
|
|
500
650
|
)
|
|
501
651
|
SELECT jsonb_build_object(
|
|
502
652
|
'user_id', p_user_id,
|
|
@@ -807,6 +957,15 @@ DO $$ BEGIN
|
|
|
807
957
|
IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'authenticated') THEN
|
|
808
958
|
EXECUTE 'GRANT EXECUTE ON FUNCTION rbac.is_super_admin() TO authenticated';
|
|
809
959
|
EXECUTE 'GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA rbac TO authenticated';
|
|
960
|
+
-- 0.6.1+: ALTER DEFAULT PRIVILEGES so any future tables
|
|
961
|
+
-- added to the rbac schema (by adopters or by a later
|
|
962
|
+
-- version of this package) automatically get the same
|
|
963
|
+
-- authenticated CRUD grant. Prevents the
|
|
964
|
+
-- "rbac.role_permission_overrides missing UPDATE → upsert
|
|
965
|
+
-- silently rejected" class of bug that hit adopters who
|
|
966
|
+
-- ran 0001 on an existing DB before role_permission_overrides
|
|
967
|
+
-- existed.
|
|
968
|
+
EXECUTE 'ALTER DEFAULT PRIVILEGES IN SCHEMA rbac GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO authenticated';
|
|
810
969
|
END IF;
|
|
811
970
|
IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'service_role') THEN
|
|
812
971
|
EXECUTE 'GRANT ALL ON ALL TABLES IN SCHEMA rbac TO service_role';
|
|
@@ -815,12 +974,27 @@ DO $$ BEGIN
|
|
|
815
974
|
END IF;
|
|
816
975
|
END $$;
|
|
817
976
|
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
977
|
+
-- 0.6.1+: explicit per-table re-grant for the two 0.4.0+ tables.
|
|
978
|
+
-- Belt-and-braces for adopters whose DB has the tables but whose
|
|
979
|
+
-- earlier 0001 run pre-dated the tables (so the schema-wide GRANT
|
|
980
|
+
-- above didn't cover them, and ALTER DEFAULT PRIVILEGES only
|
|
981
|
+
-- applies to tables created AFTER it). Idempotent — re-granting
|
|
982
|
+
-- existing privileges is a no-op.
|
|
983
|
+
DO $$ BEGIN
|
|
984
|
+
IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'authenticated') THEN
|
|
985
|
+
EXECUTE 'GRANT SELECT, INSERT, UPDATE, DELETE ON rbac.resource_dependencies TO authenticated';
|
|
986
|
+
EXECUTE 'GRANT SELECT, INSERT, UPDATE, DELETE ON rbac.role_permission_overrides TO authenticated';
|
|
987
|
+
END IF;
|
|
988
|
+
END $$;
|
|
989
|
+
|
|
990
|
+
ALTER TABLE rbac.companies ENABLE ROW LEVEL SECURITY;
|
|
991
|
+
ALTER TABLE rbac.resources ENABLE ROW LEVEL SECURITY;
|
|
992
|
+
ALTER TABLE rbac.roles ENABLE ROW LEVEL SECURITY;
|
|
993
|
+
ALTER TABLE rbac.role_permissions ENABLE ROW LEVEL SECURITY;
|
|
994
|
+
ALTER TABLE rbac.user_system_roles ENABLE ROW LEVEL SECURITY;
|
|
995
|
+
ALTER TABLE rbac.user_company_roles ENABLE ROW LEVEL SECURITY;
|
|
996
|
+
ALTER TABLE rbac.resource_dependencies ENABLE ROW LEVEL SECURITY;
|
|
997
|
+
ALTER TABLE rbac.role_permission_overrides ENABLE ROW LEVEL SECURITY;
|
|
824
998
|
|
|
825
999
|
-- READ — open to any authenticated user for static config tables;
|
|
826
1000
|
-- own-row only on assignment tables (super-admin sees all).
|
|
@@ -870,6 +1044,31 @@ DROP POLICY IF EXISTS rbac_user_company_roles_write ON rbac.user_company_roles;
|
|
|
870
1044
|
CREATE POLICY rbac_user_company_roles_write ON rbac.user_company_roles FOR ALL TO authenticated
|
|
871
1045
|
USING (rbac.is_super_admin()) WITH CHECK (rbac.is_super_admin());
|
|
872
1046
|
|
|
1047
|
+
-- 0.4.0+ rbac.resource_dependencies — readable to any authenticated
|
|
1048
|
+
-- user (the admin matrix UI consults it on every render to compute
|
|
1049
|
+
-- implied state). Direct writes are super-admin only as defence-in-
|
|
1050
|
+
-- depth; in practice the SECURITY DEFINER RPC
|
|
1051
|
+
-- rbac.replace_resource_dependencies handles every write.
|
|
1052
|
+
DROP POLICY IF EXISTS rbac_resource_dependencies_read ON rbac.resource_dependencies;
|
|
1053
|
+
CREATE POLICY rbac_resource_dependencies_read ON rbac.resource_dependencies
|
|
1054
|
+
FOR SELECT TO authenticated USING (true);
|
|
1055
|
+
|
|
1056
|
+
DROP POLICY IF EXISTS rbac_resource_dependencies_write ON rbac.resource_dependencies;
|
|
1057
|
+
CREATE POLICY rbac_resource_dependencies_write ON rbac.resource_dependencies
|
|
1058
|
+
FOR ALL TO authenticated
|
|
1059
|
+
USING (rbac.is_super_admin()) WITH CHECK (rbac.is_super_admin());
|
|
1060
|
+
|
|
1061
|
+
-- 0.6.0+ rbac.role_permission_overrides — same read-anyone /
|
|
1062
|
+
-- write-super-admin pattern as the rest of the matrix tables.
|
|
1063
|
+
DROP POLICY IF EXISTS rbac_role_permission_overrides_read ON rbac.role_permission_overrides;
|
|
1064
|
+
CREATE POLICY rbac_role_permission_overrides_read ON rbac.role_permission_overrides
|
|
1065
|
+
FOR SELECT TO authenticated USING (true);
|
|
1066
|
+
|
|
1067
|
+
DROP POLICY IF EXISTS rbac_role_permission_overrides_write ON rbac.role_permission_overrides;
|
|
1068
|
+
CREATE POLICY rbac_role_permission_overrides_write ON rbac.role_permission_overrides
|
|
1069
|
+
FOR ALL TO authenticated
|
|
1070
|
+
USING (rbac.is_super_admin()) WITH CHECK (rbac.is_super_admin());
|
|
1071
|
+
|
|
873
1072
|
COMMIT;
|
|
874
1073
|
|
|
875
1074
|
-- Tell PostgREST to refresh schema cache so the policies + grants
|