feat(tests): add more tests and make them pass
This commit is contained in:
+333
-28
@@ -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 ==='
|
||||
|
||||
Reference in New Issue
Block a user