feat(tests): add more tests and make them pass

This commit is contained in:
2026-03-22 23:25:48 +01:00
parent 90b96079a0
commit c22d18063b
13 changed files with 3332 additions and 643 deletions
+333 -28
View File
@@ -1,37 +1,342 @@
-- ============================================================================
-- MORBAC PostgreSQL Extension - Administration Rules Tests
-- ============================================================================
-- This test file covers administration rules including:
-- - Administrative activities (create_rule, etc.)
-- - Administrative permission checks (is_admin_allowed)
-- - Role-based administrative access control
-- - Administrative authorization decisions
-- =============================================================================
-- Administration Rules Tests
-- =============================================================================
-- Tests the admin meta-policy system: who can manage policies, roles, and users.
--
-- Prerequisites: Assumes 00_setup.sql has been run to set up base data
-- ============================================================================
-- is_admin_allowed(user_id, org_id, admin_activity, admin_target) is the main API.
-- Helper functions: can_manage_roles(), can_manage_policies(), can_manage_user_role().
--
-- Scenarios:
-- 1. Default deny: no admin rule = no admin access
-- 2. Grant admin permission to a role, verify the role holder can manage
-- 3. Admin prohibition blocks management even with permission
-- 4. Role hierarchy applies: senior role inherits admin permissions
-- 5. Admin helper functions
-- 6. can_manage_user_role() per-role management permission
-- 7. Admin rules are org-scoped
--
-- Company context:
-- Grace (hr_manager) can manage users (assign_role) for employee-level roles
-- Carol (manager) can create rules
-- Alice (CEO) inherits Carol's admin perms via hierarchy
--
-- Prerequisites: 00_setup.sql -> 07_audit.sql
-- =============================================================================
\echo ''
\echo '=== Administration Rules ==='
\echo '================================================================'
\echo '08 — ADMINISTRATION RULES'
\echo '================================================================'
-- Only admin role can create rules
INSERT INTO morbac.admin_rules (org_id, role_id, admin_activity, admin_target, context_id, modality) VALUES
('11111111-1111-1111-1111-111111111111', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'create_rule', 'rules', (SELECT id FROM morbac.contexts WHERE name = 'always'), 'permission');
-- ---------------------------------------------------------------------------
-- Section 1: Default deny — no admin rule means no admin access
-- ---------------------------------------------------------------------------
\echo ''
\echo '--- 1. Default deny: no admin rule ---'
\echo 'Alice (admin) can create rules:'
SELECT morbac.is_admin_allowed(
'aaaaaaaa-0000-0000-0000-000000000001'::uuid,
'11111111-1111-1111-1111-111111111111'::uuid,
'create_rule',
'rules'
) as can_create_rules;
-- Nobody has admin rules yet — all should be denied
SELECT morbac.t('Alice (CEO, no admin rule yet) creates rules [default deny]',
morbac.is_admin_allowed(
'30000000-0000-0000-0000-000000000001'::uuid,
'10000000-0000-0000-0000-000000000001'::uuid,
'create_rule', 'rules'
), FALSE);
\echo 'Bob (employee) cannot create rules:'
SELECT morbac.is_admin_allowed(
'bbbbbbbb-0000-0000-0000-000000000002'::uuid,
'11111111-1111-1111-1111-111111111111'::uuid,
'create_rule',
'rules'
) as can_create_rules;
SELECT morbac.t('Grace (hr_manager, no admin rule) assigns roles [default deny]',
morbac.is_admin_allowed(
'30000000-0000-0000-0000-000000000007'::uuid,
'10000000-0000-0000-0000-000000000001'::uuid,
'assign_role', 'employee'
), FALSE);
-- ---------------------------------------------------------------------------
-- Section 2: Grant admin permissions
-- ---------------------------------------------------------------------------
\echo ''
\echo '--- 2. Grant admin permissions ---'
-- Grant manager role: can create and delete rules
INSERT INTO morbac.admin_rules (org_id, role_id, admin_activity, admin_target, context_id, modality)
VALUES
('10000000-0000-0000-0000-000000000001',
'20000000-0001-0000-0000-000000000003', -- manager
'create_rule', 'rules',
(SELECT id FROM morbac.contexts WHERE name = 'always'),
'permission'),
('10000000-0000-0000-0000-000000000001',
'20000000-0001-0000-0000-000000000003', -- manager
'delete_rule', 'rules',
(SELECT id FROM morbac.contexts WHERE name = 'always'),
'permission');
-- Grant hr_manager role: can assign employee and intern roles
INSERT INTO morbac.admin_rules (org_id, role_id, admin_activity, admin_target, context_id, modality)
VALUES
('10000000-0000-0000-0000-000000000001',
'20000000-0001-0000-0000-000000000008', -- hr_manager
'assign_role', 'employee',
(SELECT id FROM morbac.contexts WHERE name = 'always'),
'permission'),
('10000000-0000-0000-0000-000000000001',
'20000000-0001-0000-0000-000000000008', -- hr_manager
'assign_role', 'intern',
(SELECT id FROM morbac.contexts WHERE name = 'always'),
'permission');
-- Grant director role: can manage roles and policies
INSERT INTO morbac.admin_rules (org_id, role_id, admin_activity, admin_target, context_id, modality)
VALUES
('10000000-0000-0000-0000-000000000001',
'20000000-0001-0000-0000-000000000002', -- director
'manage', 'roles',
(SELECT id FROM morbac.contexts WHERE name = 'always'),
'permission'),
('10000000-0000-0000-0000-000000000001',
'20000000-0001-0000-0000-000000000002', -- director
'manage', 'policies',
(SELECT id FROM morbac.contexts WHERE name = 'always'),
'permission');
-- ---------------------------------------------------------------------------
-- Section 3: Verify admin permissions
-- ---------------------------------------------------------------------------
\echo ''
\echo '--- 3. Verify admin permissions ---'
-- Carol (manager) can create rules
SELECT morbac.t('Carol (manager) creates rules',
morbac.is_admin_allowed(
'30000000-0000-0000-0000-000000000003'::uuid,
'10000000-0000-0000-0000-000000000001'::uuid,
'create_rule', 'rules'
), TRUE);
-- Carol (manager) can delete rules
SELECT morbac.t('Carol (manager) deletes rules',
morbac.is_admin_allowed(
'30000000-0000-0000-0000-000000000003'::uuid,
'10000000-0000-0000-0000-000000000001'::uuid,
'delete_rule', 'rules'
), TRUE);
-- Grace (hr_manager) can assign employee role
SELECT morbac.t('Grace (hr_manager) assigns employee role',
morbac.is_admin_allowed(
'30000000-0000-0000-0000-000000000007'::uuid,
'10000000-0000-0000-0000-000000000001'::uuid,
'assign_role', 'employee'
), TRUE);
-- Grace (hr_manager) can assign intern role
SELECT morbac.t('Grace (hr_manager) assigns intern role',
morbac.is_admin_allowed(
'30000000-0000-0000-0000-000000000007'::uuid,
'10000000-0000-0000-0000-000000000001'::uuid,
'assign_role', 'intern'
), TRUE);
-- Grace (hr_manager) cannot assign manager role (no rule for that)
SELECT morbac.t('Grace (hr_manager) assigns manager role [no admin rule for manager]',
morbac.is_admin_allowed(
'30000000-0000-0000-0000-000000000007'::uuid,
'10000000-0000-0000-0000-000000000001'::uuid,
'assign_role', 'manager'
), FALSE);
-- Dave (employee) has no admin permissions
SELECT morbac.t('Dave (employee) creates rules [no admin rule for employee]',
morbac.is_admin_allowed(
'30000000-0000-0000-0000-000000000004'::uuid,
'10000000-0000-0000-0000-000000000001'::uuid,
'create_rule', 'rules'
), FALSE);
-- ---------------------------------------------------------------------------
-- Section 4: Role hierarchy applies to admin permissions
-- ---------------------------------------------------------------------------
\echo ''
\echo '--- 4. Role hierarchy applies to admin permissions ---'
-- Bob (director) has own admin perm (manage roles/policies) and
-- inherits manager's admin perms (create_rule, delete_rule) via director->manager hierarchy
-- Bob (director) creates rules — inherited from manager via director->manager hierarchy
SELECT morbac.t('Bob (director, inherits manager admin) creates rules',
morbac.is_admin_allowed(
'30000000-0000-0000-0000-000000000002'::uuid,
'10000000-0000-0000-0000-000000000001'::uuid,
'create_rule', 'rules'
), TRUE);
-- Bob (director) manages roles — own admin perm
SELECT morbac.t('Bob (director) manages roles [own admin perm]',
morbac.is_admin_allowed(
'30000000-0000-0000-0000-000000000002'::uuid,
'10000000-0000-0000-0000-000000000001'::uuid,
'manage', 'roles'
), TRUE);
-- Alice (CEO) inherits everything through CEO->director->manager chain
SELECT morbac.t('Alice (CEO, inherits director+manager) manages roles',
morbac.is_admin_allowed(
'30000000-0000-0000-0000-000000000001'::uuid,
'10000000-0000-0000-0000-000000000001'::uuid,
'manage', 'roles'
), TRUE);
SELECT morbac.t('Alice (CEO) manages policies',
morbac.is_admin_allowed(
'30000000-0000-0000-0000-000000000001'::uuid,
'10000000-0000-0000-0000-000000000001'::uuid,
'manage', 'policies'
), TRUE);
-- Eve (intern) inherits nothing useful for admin
SELECT morbac.t('Eve (intern) creates rules [no admin permission in hierarchy]',
morbac.is_admin_allowed(
'30000000-0000-0000-0000-000000000005'::uuid,
'10000000-0000-0000-0000-000000000001'::uuid,
'create_rule', 'rules'
), FALSE);
-- ---------------------------------------------------------------------------
-- Section 5: Admin prohibition overrides permission
-- ---------------------------------------------------------------------------
\echo ''
\echo '--- 5. Admin prohibition overrides permission ---'
-- Carol (manager) currently can create rules. Add a prohibition.
INSERT INTO morbac.admin_rules (org_id, role_id, admin_activity, admin_target, context_id, modality)
VALUES (
'10000000-0000-0000-0000-000000000001',
'20000000-0001-0000-0000-000000000003', -- manager
'create_rule', 'rules',
(SELECT id FROM morbac.contexts WHERE name = 'always'),
'prohibition'
);
-- Prohibition overrides permission
SELECT morbac.t('Carol (manager, now prohibited) creates rules [prohibition wins]',
morbac.is_admin_allowed(
'30000000-0000-0000-0000-000000000003'::uuid,
'10000000-0000-0000-0000-000000000001'::uuid,
'create_rule', 'rules'
), FALSE);
-- Carol can still delete rules (prohibition only applied to create_rule)
SELECT morbac.t('Carol (manager, prohibition only on create) deletes rules [still allowed]',
morbac.is_admin_allowed(
'30000000-0000-0000-0000-000000000003'::uuid,
'10000000-0000-0000-0000-000000000001'::uuid,
'delete_rule', 'rules'
), TRUE);
-- Remove the prohibition for subsequent tests
DELETE FROM morbac.admin_rules
WHERE org_id = '10000000-0000-0000-0000-000000000001'
AND role_id = '20000000-0001-0000-0000-000000000003'
AND admin_activity = 'create_rule' AND admin_target = 'rules'
AND modality = 'prohibition';
-- Carol can again create rules after prohibition removed
SELECT morbac.t('Carol (manager) creates rules after prohibition removed',
morbac.is_admin_allowed(
'30000000-0000-0000-0000-000000000003'::uuid,
'10000000-0000-0000-0000-000000000001'::uuid,
'create_rule', 'rules'
), TRUE);
-- ---------------------------------------------------------------------------
-- Section 6: Admin helper functions
-- ---------------------------------------------------------------------------
\echo ''
\echo '--- 6. Admin helper functions ---'
-- can_manage_roles: wraps is_admin_allowed('manage', 'roles')
SELECT morbac.t('Bob (director) can_manage_roles',
morbac.can_manage_roles(
'30000000-0000-0000-0000-000000000002'::uuid,
'10000000-0000-0000-0000-000000000001'::uuid
), TRUE);
SELECT morbac.t('Dave (employee) can_manage_roles [denied]',
morbac.can_manage_roles(
'30000000-0000-0000-0000-000000000004'::uuid,
'10000000-0000-0000-0000-000000000001'::uuid
), FALSE);
-- can_manage_policies: wraps is_admin_allowed('manage', 'policies')
SELECT morbac.t('Bob (director) can_manage_policies',
morbac.can_manage_policies(
'30000000-0000-0000-0000-000000000002'::uuid,
'10000000-0000-0000-0000-000000000001'::uuid
), TRUE);
SELECT morbac.t('Carol (manager) can_manage_policies [no manage policies rule for manager]',
morbac.can_manage_policies(
'30000000-0000-0000-0000-000000000003'::uuid,
'10000000-0000-0000-0000-000000000001'::uuid
), FALSE);
-- ---------------------------------------------------------------------------
-- Section 7: can_manage_user_role — per-role management check
-- ---------------------------------------------------------------------------
\echo ''
\echo '--- 7. can_manage_user_role ---'
-- Grace (hr_manager) has assign_role perm for 'employee'
-- can_manage_user_role checks is_admin_allowed('assign_role', role_name)
SELECT morbac.t('Grace (hr_manager) can manage employee role assignments',
morbac.can_manage_user_role(
'30000000-0000-0000-0000-000000000007'::uuid, -- Grace
'10000000-0000-0000-0000-000000000001'::uuid,
'20000000-0001-0000-0000-000000000004'::uuid -- employee role
), TRUE);
SELECT morbac.t('Grace (hr_manager) can manage intern role assignments',
morbac.can_manage_user_role(
'30000000-0000-0000-0000-000000000007'::uuid, -- Grace
'10000000-0000-0000-0000-000000000001'::uuid,
'20000000-0001-0000-0000-000000000005'::uuid -- intern role
), TRUE);
SELECT morbac.t('Grace (hr_manager) cannot manage manager role assignments [no rule]',
morbac.can_manage_user_role(
'30000000-0000-0000-0000-000000000007'::uuid, -- Grace
'10000000-0000-0000-0000-000000000001'::uuid,
'20000000-0001-0000-0000-000000000003'::uuid -- manager role
), FALSE);
SELECT morbac.t('Dave (employee) cannot manage any role assignments',
morbac.can_manage_user_role(
'30000000-0000-0000-0000-000000000004'::uuid, -- Dave
'10000000-0000-0000-0000-000000000001'::uuid,
'20000000-0001-0000-0000-000000000005'::uuid -- intern role
), FALSE);
-- ---------------------------------------------------------------------------
-- Section 8: Admin rules are org-scoped
-- ---------------------------------------------------------------------------
\echo ''
\echo '--- 8. Admin rules are org-scoped ---'
-- Carol (manager at GlobalTech) cannot manage Engineering rules
-- (her admin rule is for GlobalTech org only)
SELECT morbac.t('Carol (GlobalTech manager) creates Engineering rules [wrong org]',
morbac.is_admin_allowed(
'30000000-0000-0000-0000-000000000003'::uuid,
'10000000-0000-0000-0000-000000000002'::uuid, -- Engineering org
'create_rule', 'rules'
), FALSE);
-- Alice (CEO at GlobalTech) cannot manage Engineering rules via admin (same org scoping)
SELECT morbac.t('Alice (GlobalTech CEO) creates Engineering rules [org-scoped]',
morbac.is_admin_allowed(
'30000000-0000-0000-0000-000000000001'::uuid,
'10000000-0000-0000-0000-000000000002'::uuid, -- Engineering org
'manage', 'roles'
), FALSE);
\echo ''
\echo '=== Administration Rules Tests Completed ==='