feat(tests): add more tests and make them pass
This commit is contained in:
+406
-167
@@ -1,179 +1,418 @@
|
||||
-- ============================================================================
|
||||
-- MORBAC PostgreSQL Extension - Authorization Decision Tests
|
||||
-- ============================================================================
|
||||
-- This test file covers authorization decision tests including:
|
||||
-- - Basic authorization decisions (is_allowed function)
|
||||
-- - Role hierarchy inheritance
|
||||
-- - Organization hierarchy
|
||||
-- - Prohibition precedence
|
||||
-- - Multi-organization user access
|
||||
-- =============================================================================
|
||||
-- Authorization Decision Tests
|
||||
-- =============================================================================
|
||||
-- Tests the core is_allowed() function across a variety of scenarios.
|
||||
-- No activity or view hierarchy is active yet (added in 02_hierarchies.sql).
|
||||
--
|
||||
-- Prerequisites: Assumes 00_setup.sql has been run to set up base data
|
||||
-- ============================================================================
|
||||
-- Users and their roles at GlobalTech HQ:
|
||||
-- Alice — ceo (permission: inherits all via hierarchy)
|
||||
-- Bob — director (inherits manager -> employee -> intern)
|
||||
-- Carol — manager (inherits employee -> intern)
|
||||
-- Dave — employee (inherits intern)
|
||||
-- Eve — intern
|
||||
-- Frank — contractor (has prohibition on financial/hr data)
|
||||
-- Grace — hr_manager
|
||||
-- Heidi — auditor
|
||||
-- Ivan — accountant
|
||||
-- Judy — engineer@Engineering + sales_rep@Sales (multi-org)
|
||||
-- Karl — no role
|
||||
-- Leo — employee
|
||||
--
|
||||
-- Prerequisites: 00_setup.sql
|
||||
-- =============================================================================
|
||||
|
||||
\echo ''
|
||||
\echo '=== Authorization Decisions ==='
|
||||
\echo '================================================================'
|
||||
\echo '01 — CORE AUTHORIZATION DECISIONS'
|
||||
\echo '================================================================'
|
||||
|
||||
-- Test Alice (admin at Acme)
|
||||
\echo 'Alice (admin at Acme Corp):'
|
||||
SELECT
|
||||
'read documents' as action,
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Section 1: Basic permission grants
|
||||
-- ---------------------------------------------------------------------------
|
||||
\echo ''
|
||||
\echo '--- 1. Basic permission grants ---'
|
||||
|
||||
-- Dave (employee) can read documents — has explicit permission
|
||||
SELECT morbac.t('Dave (employee) reads documents',
|
||||
morbac.is_allowed_nocache(
|
||||
'30000000-0000-0000-0000-000000000004'::uuid,
|
||||
'10000000-0000-0000-0000-000000000001'::uuid,
|
||||
'read', 'documents'
|
||||
), TRUE);
|
||||
|
||||
-- Dave (employee) can write documents — context is business_hours (evaluates TRUE)
|
||||
SELECT morbac.t('Dave (employee) writes documents [business_hours context=true]',
|
||||
morbac.is_allowed_nocache(
|
||||
'30000000-0000-0000-0000-000000000004'::uuid,
|
||||
'10000000-0000-0000-0000-000000000001'::uuid,
|
||||
'write', 'documents'
|
||||
), TRUE);
|
||||
|
||||
-- Dave (employee) can read reports
|
||||
SELECT morbac.t('Dave (employee) reads reports',
|
||||
morbac.is_allowed_nocache(
|
||||
'30000000-0000-0000-0000-000000000004'::uuid,
|
||||
'10000000-0000-0000-0000-000000000001'::uuid,
|
||||
'read', 'reports'
|
||||
), TRUE);
|
||||
|
||||
-- Eve (intern) can read public data only
|
||||
SELECT morbac.t('Eve (intern) reads public_data',
|
||||
morbac.is_allowed_nocache(
|
||||
'30000000-0000-0000-0000-000000000005'::uuid,
|
||||
'10000000-0000-0000-0000-000000000001'::uuid,
|
||||
'read', 'public_data'
|
||||
), TRUE);
|
||||
|
||||
-- Grace (hr_manager) can write hr_data
|
||||
SELECT morbac.t('Grace (hr_manager) writes hr_data',
|
||||
morbac.is_allowed_nocache(
|
||||
'30000000-0000-0000-0000-000000000007'::uuid,
|
||||
'10000000-0000-0000-0000-000000000001'::uuid,
|
||||
'write', 'hr_data'
|
||||
), TRUE);
|
||||
|
||||
-- Heidi (auditor) can read financial_data
|
||||
SELECT morbac.t('Heidi (auditor) reads financial_data',
|
||||
morbac.is_allowed_nocache(
|
||||
'30000000-0000-0000-0000-000000000008'::uuid,
|
||||
'10000000-0000-0000-0000-000000000001'::uuid,
|
||||
'read', 'financial_data'
|
||||
), TRUE);
|
||||
|
||||
-- Ivan (accountant) can write financial_data
|
||||
SELECT morbac.t('Ivan (accountant) writes financial_data',
|
||||
morbac.is_allowed_nocache(
|
||||
'30000000-0000-0000-0000-000000000009'::uuid,
|
||||
'10000000-0000-0000-0000-000000000001'::uuid,
|
||||
'write', 'financial_data'
|
||||
), TRUE);
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Section 2: Default deny — no rule exists for the combination
|
||||
-- ---------------------------------------------------------------------------
|
||||
\echo ''
|
||||
\echo '--- 2. Default deny (no permission rule) ---'
|
||||
|
||||
-- Dave (employee) cannot delete documents — no delete permission for employee
|
||||
SELECT morbac.t('Dave (employee) deletes documents [no permission]',
|
||||
morbac.is_allowed_nocache(
|
||||
'30000000-0000-0000-0000-000000000004'::uuid,
|
||||
'10000000-0000-0000-0000-000000000001'::uuid,
|
||||
'delete', 'documents'
|
||||
), FALSE);
|
||||
|
||||
-- Eve (intern) cannot read documents — intern only has public_data permission
|
||||
SELECT morbac.t('Eve (intern) reads documents [intern has no docs permission]',
|
||||
morbac.is_allowed_nocache(
|
||||
'30000000-0000-0000-0000-000000000005'::uuid,
|
||||
'10000000-0000-0000-0000-000000000001'::uuid,
|
||||
'read', 'documents'
|
||||
), FALSE);
|
||||
|
||||
-- Dave (employee) cannot read financial_data — no rule for employee -> financial_data
|
||||
SELECT morbac.t('Dave (employee) reads financial_data [no permission before view hierarchy]',
|
||||
morbac.is_allowed_nocache(
|
||||
'30000000-0000-0000-0000-000000000004'::uuid,
|
||||
'10000000-0000-0000-0000-000000000001'::uuid,
|
||||
'read', 'financial_data'
|
||||
), FALSE);
|
||||
|
||||
-- Grace (hr_manager) cannot read audit_logs — no rule for hr_manager -> audit_logs
|
||||
SELECT morbac.t('Grace (hr_manager) reads audit_logs [no permission]',
|
||||
morbac.is_allowed_nocache(
|
||||
'30000000-0000-0000-0000-000000000007'::uuid,
|
||||
'10000000-0000-0000-0000-000000000001'::uuid,
|
||||
'read', 'audit_logs'
|
||||
), FALSE);
|
||||
|
||||
-- Dave (employee) cannot approve documents — no approve permission for employee
|
||||
SELECT morbac.t('Dave (employee) approves documents [no permission]',
|
||||
morbac.is_allowed_nocache(
|
||||
'30000000-0000-0000-0000-000000000004'::uuid,
|
||||
'10000000-0000-0000-0000-000000000001'::uuid,
|
||||
'approve', 'documents'
|
||||
), FALSE);
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Section 3: Default deny — user has no role at all
|
||||
-- ---------------------------------------------------------------------------
|
||||
\echo ''
|
||||
\echo '--- 3. Default deny (user has no role) ---'
|
||||
|
||||
-- Karl has no role anywhere — all actions denied
|
||||
SELECT morbac.t('Karl (no role) reads documents',
|
||||
morbac.is_allowed_nocache(
|
||||
'30000000-0000-0000-0000-000000000011'::uuid,
|
||||
'10000000-0000-0000-0000-000000000001'::uuid,
|
||||
'read', 'documents'
|
||||
), FALSE);
|
||||
|
||||
-- Completely unknown user UUID — EXPECT FALSE
|
||||
SELECT morbac.t('Unknown user reads documents',
|
||||
morbac.is_allowed_nocache(
|
||||
'ffffffff-ffff-ffff-ffff-ffffffffffff'::uuid,
|
||||
'10000000-0000-0000-0000-000000000001'::uuid,
|
||||
'read', 'documents'
|
||||
), FALSE);
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Section 4: Prohibition overrides permission (prohibition precedence)
|
||||
-- ---------------------------------------------------------------------------
|
||||
\echo ''
|
||||
\echo '--- 4. Prohibition overrides permission ---'
|
||||
|
||||
-- Frank (contractor) reads documents — permission granted, no prohibition
|
||||
SELECT morbac.t('Frank (contractor) reads documents [has permission]',
|
||||
morbac.is_allowed_nocache(
|
||||
'30000000-0000-0000-0000-000000000006'::uuid,
|
||||
'10000000-0000-0000-0000-000000000001'::uuid,
|
||||
'read', 'documents'
|
||||
), TRUE);
|
||||
|
||||
-- Frank (contractor) reads financial_data — PROHIBITED
|
||||
SELECT morbac.t('Frank (contractor) reads financial_data [prohibited]',
|
||||
morbac.is_allowed_nocache(
|
||||
'30000000-0000-0000-0000-000000000006'::uuid,
|
||||
'10000000-0000-0000-0000-000000000001'::uuid,
|
||||
'read', 'financial_data'
|
||||
), FALSE);
|
||||
|
||||
-- Frank (contractor) reads hr_data — prohibited
|
||||
SELECT morbac.t('Frank (contractor) reads hr_data [prohibited]',
|
||||
morbac.is_allowed_nocache(
|
||||
'30000000-0000-0000-0000-000000000006'::uuid,
|
||||
'10000000-0000-0000-0000-000000000001'::uuid,
|
||||
'read', 'hr_data'
|
||||
), FALSE);
|
||||
|
||||
-- Add a permission for contractor on financial_data, then confirm prohibition still wins
|
||||
INSERT INTO morbac.rules (org_id, role_id, activity, view, context_id, modality)
|
||||
VALUES (
|
||||
'10000000-0000-0000-0000-000000000001',
|
||||
'20000000-0001-0000-0000-000000000009', -- contractor
|
||||
'read', 'financial_data',
|
||||
(SELECT id FROM morbac.contexts WHERE name = 'always'),
|
||||
'permission'
|
||||
);
|
||||
|
||||
-- Prohibition must always win over permission
|
||||
SELECT morbac.t('Frank (contractor) reads financial_data after adding permission [prohibition wins]',
|
||||
morbac.is_allowed_nocache(
|
||||
'30000000-0000-0000-0000-000000000006'::uuid,
|
||||
'10000000-0000-0000-0000-000000000001'::uuid,
|
||||
'read', 'financial_data'
|
||||
), FALSE);
|
||||
|
||||
-- Clean up the extra rule
|
||||
DELETE FROM morbac.rules
|
||||
WHERE org_id = '10000000-0000-0000-0000-000000000001'
|
||||
AND role_id = '20000000-0001-0000-0000-000000000009'
|
||||
AND activity = 'read' AND view = 'financial_data' AND modality = 'permission';
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Section 5: Context filtering — rule only applies when context is TRUE
|
||||
-- ---------------------------------------------------------------------------
|
||||
\echo ''
|
||||
\echo '--- 5. Context filtering ---'
|
||||
|
||||
-- Add a rule that only applies after_hours (context evaluates FALSE)
|
||||
INSERT INTO morbac.rules (org_id, role_id, activity, view, context_id, modality)
|
||||
VALUES (
|
||||
'10000000-0000-0000-0000-000000000001',
|
||||
'20000000-0001-0000-0000-000000000004', -- employee
|
||||
'export', 'documents',
|
||||
(SELECT id FROM morbac.contexts WHERE name = 'after_hours'),
|
||||
'permission'
|
||||
);
|
||||
|
||||
-- Context evaluates FALSE so the rule does not apply
|
||||
SELECT morbac.t('Dave (employee) exports documents [after_hours context=false]',
|
||||
morbac.is_allowed_nocache(
|
||||
'30000000-0000-0000-0000-000000000004'::uuid,
|
||||
'10000000-0000-0000-0000-000000000001'::uuid,
|
||||
'export', 'documents'
|
||||
), FALSE);
|
||||
|
||||
-- Replace with business_hours context (evaluates TRUE)
|
||||
UPDATE morbac.rules
|
||||
SET context_id = (SELECT id FROM morbac.contexts WHERE name = 'business_hours')
|
||||
WHERE org_id = '10000000-0000-0000-0000-000000000001'
|
||||
AND role_id = '20000000-0001-0000-0000-000000000004'
|
||||
AND activity = 'export' AND view = 'documents';
|
||||
|
||||
-- Context evaluates TRUE
|
||||
SELECT morbac.t('Dave (employee) exports documents [business_hours context=true]',
|
||||
morbac.is_allowed_nocache(
|
||||
'30000000-0000-0000-0000-000000000004'::uuid,
|
||||
'10000000-0000-0000-0000-000000000001'::uuid,
|
||||
'export', 'documents'
|
||||
), TRUE);
|
||||
|
||||
-- Clean up the extra rule
|
||||
DELETE FROM morbac.rules
|
||||
WHERE org_id = '10000000-0000-0000-0000-000000000001'
|
||||
AND role_id = '20000000-0001-0000-0000-000000000004'
|
||||
AND activity = 'export' AND view = 'documents';
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Section 6: Wrong organization — user has no role in the target org
|
||||
-- ---------------------------------------------------------------------------
|
||||
\echo ''
|
||||
\echo '--- 6. Wrong organization ---'
|
||||
|
||||
-- Dave (employee at GlobalTech) has no role in Engineering Dept
|
||||
SELECT morbac.t('Dave (GlobalTech employee) reads Engineering documents [no role in Engineering]',
|
||||
morbac.is_allowed_nocache(
|
||||
'30000000-0000-0000-0000-000000000004'::uuid,
|
||||
'10000000-0000-0000-0000-000000000002'::uuid,
|
||||
'read', 'documents'
|
||||
), FALSE);
|
||||
|
||||
-- Judy (engineer at Engineering) has no role in GlobalTech
|
||||
SELECT morbac.t('Judy (Engineering engineer) reads GlobalTech financial_data [no role in GlobalTech]',
|
||||
morbac.is_allowed_nocache(
|
||||
'30000000-0000-0000-0000-000000000010'::uuid,
|
||||
'10000000-0000-0000-0000-000000000001'::uuid,
|
||||
'read', 'financial_data'
|
||||
), FALSE);
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Section 7: Multi-organization user — access scoped to each org independently
|
||||
-- ---------------------------------------------------------------------------
|
||||
\echo ''
|
||||
\echo '--- 7. Multi-org user (Judy) ---'
|
||||
|
||||
-- Judy is engineer at Engineering — can read documents there
|
||||
SELECT morbac.t('Judy (engineer) reads Engineering documents',
|
||||
morbac.is_allowed_nocache(
|
||||
'30000000-0000-0000-0000-000000000010'::uuid,
|
||||
'10000000-0000-0000-0000-000000000002'::uuid,
|
||||
'read', 'documents'
|
||||
), TRUE);
|
||||
|
||||
-- Judy is sales_rep at Sales — can write contracts there
|
||||
SELECT morbac.t('Judy (sales_rep) writes Sales contracts',
|
||||
morbac.is_allowed_nocache(
|
||||
'30000000-0000-0000-0000-000000000010'::uuid,
|
||||
'10000000-0000-0000-0000-000000000003'::uuid,
|
||||
'write', 'contracts'
|
||||
), TRUE);
|
||||
|
||||
-- Judy's engineering permissions do NOT carry to Sales
|
||||
SELECT morbac.t('Judy writes documents at Sales [engineer perms dont carry over]',
|
||||
morbac.is_allowed_nocache(
|
||||
'30000000-0000-0000-0000-000000000010'::uuid,
|
||||
'10000000-0000-0000-0000-000000000003'::uuid,
|
||||
'write', 'documents'
|
||||
), FALSE);
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Section 8: Role hierarchy inheritance
|
||||
-- ---------------------------------------------------------------------------
|
||||
\echo ''
|
||||
\echo '--- 8. Role hierarchy inheritance ---'
|
||||
|
||||
-- Carol (manager) inherits employee permissions — can read documents (employee perm)
|
||||
SELECT morbac.t('Carol (manager, inherits employee) reads documents',
|
||||
morbac.is_allowed_nocache(
|
||||
'30000000-0000-0000-0000-000000000003'::uuid,
|
||||
'10000000-0000-0000-0000-000000000001'::uuid,
|
||||
'read', 'documents'
|
||||
), TRUE);
|
||||
|
||||
-- Carol (manager) has own permission — can approve documents
|
||||
SELECT morbac.t('Carol (manager) approves documents [own permission]',
|
||||
morbac.is_allowed_nocache(
|
||||
'30000000-0000-0000-0000-000000000003'::uuid,
|
||||
'10000000-0000-0000-0000-000000000001'::uuid,
|
||||
'approve', 'documents'
|
||||
), TRUE);
|
||||
|
||||
-- Bob (director) inherits manager -> employee chain — can read documents
|
||||
SELECT morbac.t('Bob (director, inherits manager+employee) reads documents',
|
||||
morbac.is_allowed_nocache(
|
||||
'30000000-0000-0000-0000-000000000002'::uuid,
|
||||
'10000000-0000-0000-0000-000000000001'::uuid,
|
||||
'read', 'documents'
|
||||
), TRUE);
|
||||
|
||||
-- Bob (director) inherits manager — can approve documents
|
||||
SELECT morbac.t('Bob (director, inherits manager) approves documents',
|
||||
morbac.is_allowed_nocache(
|
||||
'30000000-0000-0000-0000-000000000002'::uuid,
|
||||
'10000000-0000-0000-0000-000000000001'::uuid,
|
||||
'approve', 'documents'
|
||||
), TRUE);
|
||||
|
||||
-- Alice (CEO) inherits the entire hierarchy — can do everything below
|
||||
SELECT morbac.t('Alice (CEO, inherits all) reads documents',
|
||||
morbac.is_allowed_nocache(
|
||||
'30000000-0000-0000-0000-000000000001'::uuid,
|
||||
'10000000-0000-0000-0000-000000000001'::uuid,
|
||||
'read', 'documents'
|
||||
), TRUE);
|
||||
|
||||
SELECT morbac.t('Alice (CEO, inherits all) approves documents',
|
||||
morbac.is_allowed_nocache(
|
||||
'30000000-0000-0000-0000-000000000001'::uuid,
|
||||
'10000000-0000-0000-0000-000000000001'::uuid,
|
||||
'approve', 'documents'
|
||||
), TRUE);
|
||||
|
||||
SELECT morbac.t('Alice (CEO, inherits all) deletes documents',
|
||||
morbac.is_allowed_nocache(
|
||||
'30000000-0000-0000-0000-000000000001'::uuid,
|
||||
'10000000-0000-0000-0000-000000000001'::uuid,
|
||||
'delete', 'documents'
|
||||
), TRUE);
|
||||
|
||||
-- Eve (intern) cannot approve — intern has no approve permission
|
||||
SELECT morbac.t('Eve (intern) approves documents [intern has no approve permission]',
|
||||
morbac.is_allowed_nocache(
|
||||
'30000000-0000-0000-0000-000000000005'::uuid,
|
||||
'10000000-0000-0000-0000-000000000001'::uuid,
|
||||
'approve', 'documents'
|
||||
), FALSE);
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Section 9: is_allowed_nocache produces same result as is_allowed
|
||||
-- ---------------------------------------------------------------------------
|
||||
\echo ''
|
||||
\echo '--- 9. is_allowed vs is_allowed_nocache consistency ---'
|
||||
|
||||
SELECT morbac.t('Dave reads documents: cached = nocache',
|
||||
morbac.is_allowed(
|
||||
'aaaaaaaa-0000-0000-0000-000000000001'::uuid,
|
||||
'11111111-1111-1111-1111-111111111111'::uuid,
|
||||
'read',
|
||||
'documents'
|
||||
) as allowed;
|
||||
'30000000-0000-0000-0000-000000000004'::uuid,
|
||||
'10000000-0000-0000-0000-000000000001'::uuid,
|
||||
'read', 'documents'
|
||||
) IS NOT DISTINCT FROM morbac.is_allowed_nocache(
|
||||
'30000000-0000-0000-0000-000000000004'::uuid,
|
||||
'10000000-0000-0000-0000-000000000001'::uuid,
|
||||
'read', 'documents'
|
||||
), TRUE);
|
||||
|
||||
SELECT
|
||||
'delete documents' as action,
|
||||
SELECT morbac.t('Dave deletes documents: cached = nocache',
|
||||
morbac.is_allowed(
|
||||
'aaaaaaaa-0000-0000-0000-000000000001'::uuid,
|
||||
'11111111-1111-1111-1111-111111111111'::uuid,
|
||||
'delete',
|
||||
'documents'
|
||||
) as allowed;
|
||||
'30000000-0000-0000-0000-000000000004'::uuid,
|
||||
'10000000-0000-0000-0000-000000000001'::uuid,
|
||||
'delete', 'documents'
|
||||
) IS NOT DISTINCT FROM morbac.is_allowed_nocache(
|
||||
'30000000-0000-0000-0000-000000000004'::uuid,
|
||||
'10000000-0000-0000-0000-000000000001'::uuid,
|
||||
'delete', 'documents'
|
||||
), TRUE);
|
||||
|
||||
-- Test Bob (employee at Acme)
|
||||
\echo ''
|
||||
\echo 'Bob (employee at Acme Corp):'
|
||||
SELECT
|
||||
'read documents' as action,
|
||||
SELECT morbac.t('Frank reads financial_data (prohibited): cached = nocache',
|
||||
morbac.is_allowed(
|
||||
'bbbbbbbb-0000-0000-0000-000000000002'::uuid,
|
||||
'11111111-1111-1111-1111-111111111111'::uuid,
|
||||
'read',
|
||||
'documents'
|
||||
) as allowed;
|
||||
|
||||
SELECT
|
||||
'delete documents' as action,
|
||||
morbac.is_allowed(
|
||||
'bbbbbbbb-0000-0000-0000-000000000002'::uuid,
|
||||
'11111111-1111-1111-1111-111111111111'::uuid,
|
||||
'delete',
|
||||
'documents'
|
||||
) as allowed;
|
||||
|
||||
-- Test Charlie (contractor at Acme)
|
||||
\echo ''
|
||||
\echo 'Charlie (contractor at Acme Corp):'
|
||||
SELECT
|
||||
'read documents' as action,
|
||||
morbac.is_allowed(
|
||||
'cccccccc-0000-0000-0000-000000000003'::uuid,
|
||||
'11111111-1111-1111-1111-111111111111'::uuid,
|
||||
'read',
|
||||
'documents'
|
||||
) as allowed;
|
||||
|
||||
SELECT
|
||||
'write documents' as action,
|
||||
morbac.is_allowed(
|
||||
'cccccccc-0000-0000-0000-000000000003'::uuid,
|
||||
'11111111-1111-1111-1111-111111111111'::uuid,
|
||||
'write',
|
||||
'documents'
|
||||
) as allowed;
|
||||
|
||||
-- Test PROHIBITION precedence
|
||||
\echo ''
|
||||
\echo 'Testing PROHIBITION PRECEDENCE:'
|
||||
\echo 'Charlie (contractor) trying to read sensitive_data (should be DENIED by prohibition):'
|
||||
SELECT
|
||||
'read sensitive_data' as action,
|
||||
morbac.is_allowed(
|
||||
'cccccccc-0000-0000-0000-000000000003'::uuid,
|
||||
'11111111-1111-1111-1111-111111111111'::uuid,
|
||||
'read',
|
||||
'sensitive_data'
|
||||
) as allowed;
|
||||
|
||||
-- Test Charlie at Beta Inc (multi-org user)
|
||||
\echo ''
|
||||
\echo 'Charlie as staff at Beta Inc:'
|
||||
SELECT
|
||||
'read documents' as action,
|
||||
morbac.is_allowed(
|
||||
'cccccccc-0000-0000-0000-000000000003'::uuid,
|
||||
'22222222-2222-2222-2222-222222222222'::uuid,
|
||||
'read',
|
||||
'documents'
|
||||
) as allowed;
|
||||
|
||||
-- Test Diana (manager at Beta)
|
||||
\echo ''
|
||||
\echo 'Diana (manager at Beta Inc):'
|
||||
SELECT
|
||||
'write documents' as action,
|
||||
morbac.is_allowed(
|
||||
'dddddddd-0000-0000-0000-000000000004'::uuid,
|
||||
'22222222-2222-2222-2222-222222222222'::uuid,
|
||||
'write',
|
||||
'documents'
|
||||
) as allowed;
|
||||
|
||||
\echo ''
|
||||
\echo '=== Role Hierarchy Inheritance ==='
|
||||
|
||||
-- Assign user Eve only viewer role
|
||||
\echo 'Creating user Eve with only viewer role at Acme:'
|
||||
INSERT INTO morbac.user_roles (user_id, role_id, org_id) VALUES
|
||||
('eeeeeeee-0000-0000-0000-000000000005', 'ffffffff-ffff-ffff-ffff-ffffffffffff', '11111111-1111-1111-1111-111111111111');
|
||||
|
||||
-- Add permission for viewer role
|
||||
INSERT INTO morbac.policy (org_name, role_name, activity, view, modality) VALUES
|
||||
('Acme Corp', 'viewer', 'read', 'documents', 'permission');
|
||||
|
||||
SELECT * FROM morbac.compile_policy();
|
||||
|
||||
\echo ''
|
||||
\echo 'Eve (has viewer role, which employee inherits from):'
|
||||
SELECT
|
||||
'read documents' as action,
|
||||
morbac.is_allowed(
|
||||
'eeeeeeee-0000-0000-0000-000000000005'::uuid,
|
||||
'11111111-1111-1111-1111-111111111111'::uuid,
|
||||
'read',
|
||||
'documents'
|
||||
) as allowed;
|
||||
|
||||
\echo ''
|
||||
\echo 'Bob (employee) should inherit permissions from viewer role:'
|
||||
\echo 'Effective roles for Bob (should include employee and viewer via hierarchy):'
|
||||
SELECT r.name, er.depth
|
||||
FROM morbac.get_effective_roles(
|
||||
'bbbbbbbb-0000-0000-0000-000000000002'::uuid,
|
||||
'11111111-1111-1111-1111-111111111111'::uuid
|
||||
) er
|
||||
JOIN morbac.roles r ON er.role_id = r.id
|
||||
ORDER BY er.depth;
|
||||
|
||||
\echo ''
|
||||
\echo 'Alice (admin) should inherit from both employee and viewer:'
|
||||
SELECT r.name, er.depth
|
||||
FROM morbac.get_effective_roles(
|
||||
'aaaaaaaa-0000-0000-0000-000000000001'::uuid,
|
||||
'11111111-1111-1111-1111-111111111111'::uuid
|
||||
) er
|
||||
JOIN morbac.roles r ON er.role_id = r.id
|
||||
ORDER BY er.depth;
|
||||
|
||||
\echo ''
|
||||
\echo '=== Organization Hierarchy ==='
|
||||
|
||||
\echo 'Ancestors of Acme Subsidiary:'
|
||||
SELECT o.name, oa.depth
|
||||
FROM morbac.get_org_ancestors('33333333-3333-3333-3333-333333333333'::uuid) oa
|
||||
JOIN morbac.orgs o ON oa.org_id = o.id
|
||||
ORDER BY oa.depth;
|
||||
|
||||
\echo ''
|
||||
\echo 'Descendants of Acme Corp (should include subsidiary):'
|
||||
SELECT o.name, od.depth
|
||||
FROM morbac.get_org_descendants('11111111-1111-1111-1111-111111111111'::uuid) od
|
||||
JOIN morbac.orgs o ON od.org_id = o.id
|
||||
ORDER BY od.depth;
|
||||
'30000000-0000-0000-0000-000000000006'::uuid,
|
||||
'10000000-0000-0000-0000-000000000001'::uuid,
|
||||
'read', 'financial_data'
|
||||
) IS NOT DISTINCT FROM morbac.is_allowed_nocache(
|
||||
'30000000-0000-0000-0000-000000000006'::uuid,
|
||||
'10000000-0000-0000-0000-000000000001'::uuid,
|
||||
'read', 'financial_data'
|
||||
), TRUE);
|
||||
|
||||
\echo ''
|
||||
\echo '=== Authorization Decision Tests Completed ==='
|
||||
|
||||
Reference in New Issue
Block a user