snipe-auth-rbac 0.2.1 → 0.3.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/package.json +1 -1
- package/sql/0001_initial.sql +110 -0
- package/sql/0002_seed_defaults.sql +29 -19
package/package.json
CHANGED
package/sql/0001_initial.sql
CHANGED
|
@@ -509,4 +509,114 @@ DO $$ BEGIN
|
|
|
509
509
|
END IF;
|
|
510
510
|
END $$;
|
|
511
511
|
|
|
512
|
+
-- ─────────────────────────────────────────────────────────────────
|
|
513
|
+
-- 11. Table-level grants + Row-Level Security
|
|
514
|
+
--
|
|
515
|
+
-- The admin module under `snipe-auth-rbac/admin` reads + writes
|
|
516
|
+
-- rbac.* tables directly via PostgREST (`.from('roles').select()`)
|
|
517
|
+
-- so the matrix UI can render. That requires per-table grants —
|
|
518
|
+
-- USAGE on the schema isn't enough on its own.
|
|
519
|
+
--
|
|
520
|
+
-- Strategy:
|
|
521
|
+
-- * GRANT CRUD on every rbac.* table to `authenticated`.
|
|
522
|
+
-- * Layer RLS so reads are wide enough for the admin UI but
|
|
523
|
+
-- writes are super-admin only by default.
|
|
524
|
+
-- * service_role keeps full access (backend / migrations / admin
|
|
525
|
+
-- scripts use service_role).
|
|
526
|
+
--
|
|
527
|
+
-- Adopters who want a different access model (e.g. delegate role
|
|
528
|
+
-- editing to non-super admins) replace the WRITE policies after
|
|
529
|
+
-- this file applies.
|
|
530
|
+
-- ─────────────────────────────────────────────────────────────────
|
|
531
|
+
|
|
532
|
+
-- is_super_admin: convenience helper used by the policies below.
|
|
533
|
+
-- SECURITY DEFINER so a policy can call it without recursing into
|
|
534
|
+
-- RLS on the very tables it inspects.
|
|
535
|
+
CREATE OR REPLACE FUNCTION rbac.is_super_admin()
|
|
536
|
+
RETURNS boolean
|
|
537
|
+
LANGUAGE sql
|
|
538
|
+
STABLE
|
|
539
|
+
SECURITY DEFINER
|
|
540
|
+
SET search_path = rbac, public
|
|
541
|
+
AS $$
|
|
542
|
+
SELECT EXISTS (
|
|
543
|
+
SELECT 1
|
|
544
|
+
FROM rbac.user_system_roles usr
|
|
545
|
+
JOIN rbac.roles r ON r.id = usr.role_id
|
|
546
|
+
WHERE usr.user_id = auth.uid()
|
|
547
|
+
AND r.is_super
|
|
548
|
+
);
|
|
549
|
+
$$;
|
|
550
|
+
|
|
551
|
+
DO $$ BEGIN
|
|
552
|
+
IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'authenticated') THEN
|
|
553
|
+
EXECUTE 'GRANT EXECUTE ON FUNCTION rbac.is_super_admin() TO authenticated';
|
|
554
|
+
EXECUTE 'GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA rbac TO authenticated';
|
|
555
|
+
END IF;
|
|
556
|
+
IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'service_role') THEN
|
|
557
|
+
EXECUTE 'GRANT ALL ON ALL TABLES IN SCHEMA rbac TO service_role';
|
|
558
|
+
EXECUTE 'GRANT ALL ON ALL SEQUENCES IN SCHEMA rbac TO service_role';
|
|
559
|
+
EXECUTE 'ALTER DEFAULT PRIVILEGES IN SCHEMA rbac GRANT ALL ON TABLES TO service_role';
|
|
560
|
+
END IF;
|
|
561
|
+
END $$;
|
|
562
|
+
|
|
563
|
+
ALTER TABLE rbac.companies ENABLE ROW LEVEL SECURITY;
|
|
564
|
+
ALTER TABLE rbac.resources ENABLE ROW LEVEL SECURITY;
|
|
565
|
+
ALTER TABLE rbac.roles ENABLE ROW LEVEL SECURITY;
|
|
566
|
+
ALTER TABLE rbac.role_permissions ENABLE ROW LEVEL SECURITY;
|
|
567
|
+
ALTER TABLE rbac.user_system_roles ENABLE ROW LEVEL SECURITY;
|
|
568
|
+
ALTER TABLE rbac.user_company_roles ENABLE ROW LEVEL SECURITY;
|
|
569
|
+
|
|
570
|
+
-- READ — open to any authenticated user for static config tables;
|
|
571
|
+
-- own-row only on assignment tables (super-admin sees all).
|
|
572
|
+
DROP POLICY IF EXISTS rbac_companies_read ON rbac.companies;
|
|
573
|
+
CREATE POLICY rbac_companies_read ON rbac.companies FOR SELECT TO authenticated USING (true);
|
|
574
|
+
|
|
575
|
+
DROP POLICY IF EXISTS rbac_resources_read ON rbac.resources;
|
|
576
|
+
CREATE POLICY rbac_resources_read ON rbac.resources FOR SELECT TO authenticated USING (true);
|
|
577
|
+
|
|
578
|
+
DROP POLICY IF EXISTS rbac_roles_read ON rbac.roles;
|
|
579
|
+
CREATE POLICY rbac_roles_read ON rbac.roles FOR SELECT TO authenticated USING (true);
|
|
580
|
+
|
|
581
|
+
DROP POLICY IF EXISTS rbac_role_permissions_read ON rbac.role_permissions;
|
|
582
|
+
CREATE POLICY rbac_role_permissions_read ON rbac.role_permissions FOR SELECT TO authenticated USING (true);
|
|
583
|
+
|
|
584
|
+
DROP POLICY IF EXISTS rbac_user_system_roles_read ON rbac.user_system_roles;
|
|
585
|
+
CREATE POLICY rbac_user_system_roles_read ON rbac.user_system_roles FOR SELECT TO authenticated
|
|
586
|
+
USING (user_id = auth.uid() OR rbac.is_super_admin());
|
|
587
|
+
|
|
588
|
+
DROP POLICY IF EXISTS rbac_user_company_roles_read ON rbac.user_company_roles;
|
|
589
|
+
CREATE POLICY rbac_user_company_roles_read ON rbac.user_company_roles FOR SELECT TO authenticated
|
|
590
|
+
USING (user_id = auth.uid() OR rbac.is_super_admin());
|
|
591
|
+
|
|
592
|
+
-- WRITE — super-admin only across the board. Adopters override
|
|
593
|
+
-- after this file applies to delegate role editing further.
|
|
594
|
+
DROP POLICY IF EXISTS rbac_companies_write ON rbac.companies;
|
|
595
|
+
CREATE POLICY rbac_companies_write ON rbac.companies FOR ALL TO authenticated
|
|
596
|
+
USING (rbac.is_super_admin()) WITH CHECK (rbac.is_super_admin());
|
|
597
|
+
|
|
598
|
+
DROP POLICY IF EXISTS rbac_resources_write ON rbac.resources;
|
|
599
|
+
CREATE POLICY rbac_resources_write ON rbac.resources FOR ALL TO authenticated
|
|
600
|
+
USING (rbac.is_super_admin()) WITH CHECK (rbac.is_super_admin());
|
|
601
|
+
|
|
602
|
+
DROP POLICY IF EXISTS rbac_roles_write ON rbac.roles;
|
|
603
|
+
CREATE POLICY rbac_roles_write ON rbac.roles FOR ALL TO authenticated
|
|
604
|
+
USING (rbac.is_super_admin()) WITH CHECK (rbac.is_super_admin());
|
|
605
|
+
|
|
606
|
+
DROP POLICY IF EXISTS rbac_role_permissions_write ON rbac.role_permissions;
|
|
607
|
+
CREATE POLICY rbac_role_permissions_write ON rbac.role_permissions FOR ALL TO authenticated
|
|
608
|
+
USING (rbac.is_super_admin()) WITH CHECK (rbac.is_super_admin());
|
|
609
|
+
|
|
610
|
+
DROP POLICY IF EXISTS rbac_user_system_roles_write ON rbac.user_system_roles;
|
|
611
|
+
CREATE POLICY rbac_user_system_roles_write ON rbac.user_system_roles FOR ALL TO authenticated
|
|
612
|
+
USING (rbac.is_super_admin()) WITH CHECK (rbac.is_super_admin());
|
|
613
|
+
|
|
614
|
+
DROP POLICY IF EXISTS rbac_user_company_roles_write ON rbac.user_company_roles;
|
|
615
|
+
CREATE POLICY rbac_user_company_roles_write ON rbac.user_company_roles FOR ALL TO authenticated
|
|
616
|
+
USING (rbac.is_super_admin()) WITH CHECK (rbac.is_super_admin());
|
|
617
|
+
|
|
512
618
|
COMMIT;
|
|
619
|
+
|
|
620
|
+
-- Tell PostgREST to refresh schema cache so the policies + grants
|
|
621
|
+
-- propagate without a manual reload.
|
|
622
|
+
NOTIFY pgrst, 'reload config';
|
|
@@ -1,32 +1,42 @@
|
|
|
1
1
|
-- snipe-auth-rbac — optional default seed
|
|
2
2
|
--
|
|
3
3
|
-- Companion to 0001_initial.sql that seeds:
|
|
4
|
-
-- * Two system roles (System
|
|
5
|
-
--
|
|
6
|
-
--
|
|
4
|
+
-- * Two system roles (System-Administrator with is_super=true,
|
|
5
|
+
-- System-Support).
|
|
6
|
+
-- * Four generic company-role templates (Inhaber / Verwalter /
|
|
7
|
+
-- Mitarbeiter / Leser) with sensible default_permissions
|
|
8
|
+
-- patterns.
|
|
7
9
|
--
|
|
8
|
-
--
|
|
9
|
-
--
|
|
10
|
-
--
|
|
11
|
-
-- ``rbac.apply_template_defaults(role_id)`` to materialise the matrix.
|
|
10
|
+
-- Names are in German — that's the package's primary target
|
|
11
|
+
-- audience (German property-management / SaaS). Adopters who
|
|
12
|
+
-- prefer English names skip this file and seed their own.
|
|
12
13
|
--
|
|
13
|
-
--
|
|
14
|
-
--
|
|
15
|
-
--
|
|
14
|
+
-- The four templates use only the `default` action set — they
|
|
15
|
+
-- don't reference specific resources or groups, since those are
|
|
16
|
+
-- defined by the host. After registering host resources, run
|
|
17
|
+
-- ``rbac.apply_template_defaults(role_id)`` to materialise the
|
|
18
|
+
-- matrix.
|
|
19
|
+
--
|
|
20
|
+
-- Domain-specific templates (Liegenschaftsverwalter,
|
|
21
|
+
-- Mieterverwalter, Vertrieb, Gutachter, Anwalt, Mieter) belong in
|
|
22
|
+
-- the host's own seed migration where their group/resource
|
|
23
|
+
-- defaults can reference real registered resources.
|
|
16
24
|
--
|
|
17
25
|
-- Idempotent: every INSERT uses ON CONFLICT DO NOTHING. Re-running
|
|
18
|
-
-- the file leaves an existing deployment untouched.
|
|
26
|
+
-- the file leaves an existing deployment untouched. Note: this
|
|
27
|
+
-- means upgrading from v0.3.0 (English names) does NOT auto-rename
|
|
28
|
+
-- — see CHANGELOG for the rename snippet.
|
|
19
29
|
|
|
20
30
|
BEGIN;
|
|
21
31
|
|
|
22
32
|
-- System roles
|
|
23
33
|
INSERT INTO rbac.roles (id, scope, company_id, name, description, is_system, is_super, default_permissions)
|
|
24
34
|
VALUES
|
|
25
|
-
(gen_random_uuid(), 'system', NULL, 'System
|
|
35
|
+
(gen_random_uuid(), 'system', NULL, 'System-Administrator',
|
|
26
36
|
'Plattform-Vollzugriff. Setzt jede Berechtigungsprüfung außer Kraft.',
|
|
27
37
|
true, true,
|
|
28
38
|
'{"default": ["read", "write", "update", "delete"]}'::jsonb),
|
|
29
|
-
(gen_random_uuid(), 'system', NULL, 'System
|
|
39
|
+
(gen_random_uuid(), 'system', NULL, 'System-Support',
|
|
30
40
|
'Lesezugriff auf systemweite Ressourcen für Support-Aufgaben.',
|
|
31
41
|
true, false,
|
|
32
42
|
'{"default": ["read"]}'::jsonb)
|
|
@@ -36,19 +46,19 @@ ON CONFLICT DO NOTHING;
|
|
|
36
46
|
-- Generic shapes only; domain-specific defaults are the host's job.
|
|
37
47
|
INSERT INTO rbac.roles (id, scope, company_id, name, description, is_system, is_super, default_permissions)
|
|
38
48
|
VALUES
|
|
39
|
-
(gen_random_uuid(), 'company', NULL, '
|
|
40
|
-
'Vollzugriff innerhalb
|
|
49
|
+
(gen_random_uuid(), 'company', NULL, 'Inhaber',
|
|
50
|
+
'Vollzugriff innerhalb des eigenen Mandanten.',
|
|
41
51
|
true, false,
|
|
42
52
|
'{"default": ["read", "write", "update", "delete"]}'::jsonb),
|
|
43
|
-
(gen_random_uuid(), 'company', NULL, '
|
|
44
|
-
'Verwaltet Daten
|
|
53
|
+
(gen_random_uuid(), 'company', NULL, 'Verwalter',
|
|
54
|
+
'Verwaltet Daten des Mandanten, kann Rollen ändern. Kein Löschen.',
|
|
45
55
|
true, false,
|
|
46
56
|
'{"default": ["read", "write", "update"]}'::jsonb),
|
|
47
|
-
(gen_random_uuid(), 'company', NULL, '
|
|
57
|
+
(gen_random_uuid(), 'company', NULL, 'Mitarbeiter',
|
|
48
58
|
'Standard-Mitarbeiter mit Lese- und Schreibzugriff.',
|
|
49
59
|
true, false,
|
|
50
60
|
'{"default": ["read", "write"]}'::jsonb),
|
|
51
|
-
(gen_random_uuid(), 'company', NULL, '
|
|
61
|
+
(gen_random_uuid(), 'company', NULL, 'Leser',
|
|
52
62
|
'Nur Lesezugriff.',
|
|
53
63
|
true, false,
|
|
54
64
|
'{"default": ["read"]}'::jsonb)
|