tests: cleanup structure

This commit is contained in:
2026-02-20 01:04:02 +01:00
parent 11e42f080e
commit 6adc62f9ec
14 changed files with 897 additions and 746 deletions
+186
View File
@@ -0,0 +1,186 @@
-- =============================================================================
-- Test Setup - Creates test data for all tests
-- =============================================================================
-- This file creates organizations, roles, users, activities, views, and contexts
-- that are used across multiple test files.
-- =============================================================================
-- Clean up any previous test
DROP EXTENSION IF EXISTS morbac_pg CASCADE;
DROP SCHEMA IF EXISTS morbac CASCADE;
-- Install the extension
CREATE EXTENSION morbac_pg;
-- Verify schema and tables exist
\echo '=== Schema and Tables Created ==='
SELECT schemaname, tablename
FROM pg_tables
WHERE schemaname = 'morbac'
ORDER BY tablename;
\echo ''
\echo '=== Setup: Organizations ==='
-- Create two organizations
INSERT INTO morbac.orgs (id, name) VALUES
('11111111-1111-1111-1111-111111111111', 'Acme Corp'),
('22222222-2222-2222-2222-222222222222', 'Beta Inc');
-- Create hierarchical organization (Acme Subsidiary under Acme Corp)
INSERT INTO morbac.orgs (id, name, parent_id) VALUES
('33333333-3333-3333-3333-333333333333', 'Acme Subsidiary', '11111111-1111-1111-1111-111111111111');
SELECT
o.name,
COALESCE(p.name, 'None') as parent_organization
FROM morbac.orgs o
LEFT JOIN morbac.orgs p ON o.parent_id = p.id
ORDER BY o.parent_id NULLS FIRST, o.name;
\echo ''
\echo '=== Setup: Roles ==='
-- Create roles in Acme Corp
INSERT INTO morbac.roles (id, org_id, name, description) VALUES
('aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', '11111111-1111-1111-1111-111111111111', 'admin', 'Administrator role'),
('bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb', '11111111-1111-1111-1111-111111111111', 'employee', 'Regular employee'),
('cccccccc-cccc-cccc-cccc-cccccccccccc', '11111111-1111-1111-1111-111111111111', 'contractor', 'External contractor'),
('ffffffff-ffff-ffff-ffff-ffffffffffff', '11111111-1111-1111-1111-111111111111', 'viewer', 'Read-only viewer');
-- Create roles in Beta Inc
INSERT INTO morbac.roles (id, org_id, name, description) VALUES
('dddddddd-dddd-dddd-dddd-dddddddddddd', '22222222-2222-2222-2222-222222222222', 'manager', 'Manager role'),
('eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee', '22222222-2222-2222-2222-222222222222', 'staff', 'Staff member');
SELECT r.name as role, o.name as organization
FROM morbac.roles r
JOIN morbac.orgs o ON r.org_id = o.id
ORDER BY o.name, r.name;
\echo ''
\echo '=== Setup: User Role Assignments ==='
-- User Alice (admin at Acme)
INSERT INTO morbac.user_roles (user_id, role_id, org_id) VALUES
('aaaaaaaa-0000-0000-0000-000000000001', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', '11111111-1111-1111-1111-111111111111');
-- User Bob (employee at Acme)
INSERT INTO morbac.user_roles (user_id, role_id, org_id) VALUES
('bbbbbbbb-0000-0000-0000-000000000002', 'bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb', '11111111-1111-1111-1111-111111111111');
-- User Charlie (contractor at Acme AND staff at Beta - multi-org user)
INSERT INTO morbac.user_roles (user_id, role_id, org_id) VALUES
('cccccccc-0000-0000-0000-000000000003', 'cccccccc-cccc-cccc-cccc-cccccccccccc', '11111111-1111-1111-1111-111111111111'),
('cccccccc-0000-0000-0000-000000000003', 'eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee', '22222222-2222-2222-2222-222222222222');
-- User Diana (manager at Beta)
INSERT INTO morbac.user_roles (user_id, role_id, org_id) VALUES
('dddddddd-0000-0000-0000-000000000004', 'dddddddd-dddd-dddd-dddd-dddddddddddd', '22222222-2222-2222-2222-222222222222');
SELECT
ur.user_id,
r.name as role,
o.name as organization
FROM morbac.user_roles ur
JOIN morbac.roles r ON ur.role_id = r.id
JOIN morbac.orgs o ON ur.org_id = o.id
ORDER BY ur.user_id;
\echo ''
\echo '=== Setup: Activities and Views ==='
INSERT INTO morbac.activities (name, description) VALUES
('read', 'Read/view data'),
('write', 'Create/modify data'),
('delete', 'Delete data'),
('approve', 'Approve actions');
INSERT INTO morbac.views (name, description) VALUES
('documents', 'Document resources'),
('reports', 'Report resources'),
('sensitive_data', 'Sensitive/confidential data'),
('temp_documents', 'Temporary documents'),
('future_documents', 'Future documents'),
('active_documents', 'Active documents');
\echo ''
\echo '=== Setup: Additional Contexts ==='
-- Business hours context (simplified - always true for this test)
CREATE OR REPLACE FUNCTION morbac.context_business_hours()
RETURNS BOOLEAN
LANGUAGE plpgsql
STABLE
AS $$
BEGIN
RETURN TRUE;
END;
$$;
INSERT INTO morbac.contexts (name, description, evaluator) VALUES
('business_hours', 'During business hours', 'morbac.context_business_hours'::regproc);
-- Weekend context (always false for test)
CREATE OR REPLACE FUNCTION morbac.context_weekend()
RETURNS BOOLEAN
LANGUAGE plpgsql
STABLE
AS $$
BEGIN
RETURN FALSE;
END;
$$;
INSERT INTO morbac.contexts (name, description, evaluator) VALUES
('weekend', 'During weekend', 'morbac.context_weekend'::regproc);
\echo ''
\echo '=== Setup: Policy DSL ==='
-- Acme Corp policies
INSERT INTO morbac.policy (org_name, role_name, activity, view, modality, context_name) VALUES
-- Admins can do everything on documents
('Acme Corp', 'admin', 'read', 'documents', 'permission', 'always'),
('Acme Corp', 'admin', 'write', 'documents', 'permission', 'always'),
('Acme Corp', 'admin', 'delete', 'documents', 'permission', 'always'),
-- Employees can read and write documents
('Acme Corp', 'employee', 'read', 'documents', 'permission', 'always'),
('Acme Corp', 'employee', 'write', 'documents', 'permission', 'business_hours'),
-- Contractors can only read documents
('Acme Corp', 'contractor', 'read', 'documents', 'permission', 'always'),
-- PROHIBITION: Contractors cannot access sensitive data
('Acme Corp', 'contractor', 'read', 'sensitive_data', 'prohibition', 'always'),
('Acme Corp', 'contractor', 'write', 'sensitive_data', 'prohibition', 'always'),
-- OBLIGATION: Employees must review reports weekly
('Acme Corp', 'employee', 'read', 'reports', 'obligation', 'always'),
-- Admins can access reports
('Acme Corp', 'admin', 'read', 'reports', 'permission', 'always'),
('Acme Corp', 'admin', 'approve', 'reports', 'permission', 'always');
-- Beta Inc policies
INSERT INTO morbac.policy (org_name, role_name, activity, view, modality, context_name) VALUES
-- Managers have full access
('Beta Inc', 'manager', 'read', 'documents', 'permission', 'always'),
('Beta Inc', 'manager', 'write', 'documents', 'permission', 'always'),
('Beta Inc', 'manager', 'read', 'reports', 'permission', 'always'),
-- Staff can read documents
('Beta Inc', 'staff', 'read', 'documents', 'permission', 'always'),
-- PROHIBITION: No document modifications on weekends (example)
('Beta Inc', 'staff', 'write', 'documents', 'prohibition', 'weekend'),
-- RECOMMENDATION: Staff should review reports
('Beta Inc', 'staff', 'read', 'reports', 'recommendation', 'always');
-- Compile policy
SELECT * FROM morbac.compile_policy();
\echo ''
\echo '=== Setup Complete ==='
+179
View File
@@ -0,0 +1,179 @@
-- ============================================================================
-- 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
--
-- Prerequisites: Assumes 00_setup.sql has been run to set up base data
-- ============================================================================
\echo ''
\echo '=== Authorization Decisions ==='
-- Test Alice (admin at Acme)
\echo 'Alice (admin at Acme Corp):'
SELECT
'read documents' as action,
morbac.is_allowed(
'aaaaaaaa-0000-0000-0000-000000000001'::uuid,
'11111111-1111-1111-1111-111111111111'::uuid,
'read',
'documents'
) as allowed;
SELECT
'delete documents' as action,
morbac.is_allowed(
'aaaaaaaa-0000-0000-0000-000000000001'::uuid,
'11111111-1111-1111-1111-111111111111'::uuid,
'delete',
'documents'
) as allowed;
-- Test Bob (employee at Acme)
\echo ''
\echo 'Bob (employee at Acme Corp):'
SELECT
'read documents' as action,
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;
\echo ''
\echo '=== Authorization Decision Tests Completed ==='
+41
View File
@@ -0,0 +1,41 @@
-- ============================================================================
-- MORBAC PostgreSQL Extension - Activity and View Hierarchies Tests
-- ============================================================================
-- This test file covers activity and view hierarchy tests including:
-- - Activity hierarchy (e.g., write implies read)
-- - View hierarchy (e.g., sensitive_data is a type of documents)
-- - Effective activities and views
-- - Permission inheritance through hierarchies
--
-- Prerequisites: Assumes 00_setup.sql has been run to set up base data
-- ============================================================================
\echo ''
\echo '=== Activity and View Hierarchies ==='
-- Define activity hierarchy: write implies read
INSERT INTO morbac.activity_hierarchy (senior_activity, junior_activity) VALUES
('write', 'read');
-- Define view hierarchy: sensitive_data is a type of documents
INSERT INTO morbac.view_hierarchy (senior_view, junior_view) VALUES
('sensitive_data', 'documents');
\echo 'Activities implied by write:'
SELECT * FROM morbac.get_effective_activities('write');
\echo 'Views for sensitive_data (should include documents):'
SELECT * FROM morbac.get_effective_views('sensitive_data');
\echo 'Bob has permission for read+documents, so write+documents should work (activity hierarchy):'
SELECT
'write documents (via activity hierarchy)' as action,
morbac.is_allowed(
'bbbbbbbb-0000-0000-0000-000000000002'::uuid,
'11111111-1111-1111-1111-111111111111'::uuid,
'write',
'documents'
) as allowed;
\echo ''
\echo '=== Activity and View Hierarchies Tests Completed ==='
+36
View File
@@ -0,0 +1,36 @@
-- ============================================================================
-- MORBAC PostgreSQL Extension - Delegation Tests
-- ============================================================================
-- This test file covers delegation functionality including:
-- - Temporary role delegation
-- - Delegated permission inheritance
-- - Comprehensive role reporting (direct + delegated)
-- - Time-limited delegation (valid_from/valid_until)
--
-- Prerequisites: Assumes 00_setup.sql has been run to set up base data
-- ============================================================================
\echo ''
\echo '=== Delegation ==='
-- Alice delegates admin role to user Frank temporarily
INSERT INTO morbac.delegations (delegator_id, delegatee_id, role_id, org_id, valid_from, valid_until) VALUES
('aaaaaaaa-0000-0000-0000-000000000001', 'ffffffff-0000-0000-0000-000000000006', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', '11111111-1111-1111-1111-111111111111', now(), now() + interval '1 day');
\echo 'Frank (via delegation from Alice) should have admin permissions:'
SELECT
'delete documents (delegated)' as action,
morbac.is_allowed(
'ffffffff-0000-0000-0000-000000000006'::uuid,
'11111111-1111-1111-1111-111111111111'::uuid,
'delete',
'documents'
) as allowed;
\echo 'Frank effective roles (should include delegated admin):'
SELECT r.name, cr.source
FROM morbac.get_comprehensive_roles('ffffffff-0000-0000-0000-000000000006'::uuid, '11111111-1111-1111-1111-111111111111'::uuid) cr
JOIN morbac.roles r ON cr.role_id = r.id;
\echo ''
\echo '=== Delegation Tests Completed ==='
+54
View File
@@ -0,0 +1,54 @@
-- ============================================================================
-- MORBAC PostgreSQL Extension - Constraint Tests
-- ============================================================================
-- This test file covers various constraints including:
-- - Separation of Duty (SoD) conflicts
-- - Negative role assignments
-- - Role cardinality constraints (min/max users per role)
--
-- Prerequisites: Assumes 00_setup.sql has been run to set up base data
-- ============================================================================
\echo ''
\echo '=== Separation of Duty ==='
-- Define SoD conflict: auditor and accountant roles are mutually exclusive
INSERT INTO morbac.roles (id, org_id, name, description) VALUES
('11111111-1111-1111-1111-111111111111', '11111111-1111-1111-1111-111111111111', 'auditor', 'Auditor role'),
('22222222-2222-2222-2222-222222222222', '11111111-1111-1111-1111-111111111111', 'accountant', 'Accountant role');
INSERT INTO morbac.sod_conflicts (role_a_id, role_b_id, org_id, description) VALUES
('11111111-1111-1111-1111-111111111111', '22222222-2222-2222-2222-222222222222', '11111111-1111-1111-1111-111111111111', 'Auditors and accountants are mutually exclusive');
-- Assign user to auditor role
INSERT INTO morbac.user_roles (user_id, role_id, org_id) VALUES
('99999999-0000-0000-0000-000000000009', '11111111-1111-1111-1111-111111111111', '11111111-1111-1111-1111-111111111111');
\echo 'Check SoD violation if we try to assign accountant role to auditor:'
SELECT morbac.check_sod_violation(
'99999999-0000-0000-0000-000000000009'::uuid,
'22222222-2222-2222-2222-222222222222'::uuid,
'11111111-1111-1111-1111-111111111111'::uuid
) as would_violate_sod;
\echo ''
\echo '=== Negative Role Assignment ==='
-- Explicitly prohibit contractor from ever being admin
INSERT INTO morbac.negative_role_assignments (user_id, role_id, org_id, reason) VALUES
('cccccccc-0000-0000-0000-000000000003', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', '11111111-1111-1111-1111-111111111111', 'Contractors cannot be administrators');
\echo 'Charlie cannot have admin role even if explicitly assigned (negative assignment takes precedence).'
\echo ''
\echo '=== Cardinality Constraints ==='
-- Set max 2 users for admin role
INSERT INTO morbac.role_cardinality (role_id, min_users, max_users, description) VALUES
('aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 1, 2, 'Admin role limited to 2 users minimum 1');
\echo 'Check cardinality when adding user (1 admin exists, max is 2, should be OK):'
SELECT morbac.check_cardinality_violation('aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'::uuid, TRUE) as violation;
\echo ''
\echo '=== Constraint Tests Completed ==='
+82
View File
@@ -0,0 +1,82 @@
-- ============================================================================
-- MORBAC PostgreSQL Extension - Temporal Constraint Tests
-- ============================================================================
-- This test file covers temporal constraints including:
-- - Rules with valid_from timestamps (future activation)
-- - Rules with valid_until timestamps (expiration)
-- - Rules with both valid_from and valid_until (time windows)
-- - Authorization decisions respecting temporal bounds
--
-- Prerequisites: Assumes 00_setup.sql has been run to set up base data
-- ============================================================================
\echo ''
\echo '=== Temporal Constraints on Rules ==='
-- Create a time-limited rule (expires in the past)
INSERT INTO morbac.rules (org_id, role_id, activity, view, context_id, modality, valid_until)
VALUES (
'11111111-1111-1111-1111-111111111111',
'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', -- employee role
'write',
'temp_documents',
(SELECT id FROM morbac.contexts WHERE name = 'always'),
'permission',
'2020-01-01 00:00:00+00' -- Expired rule
);
-- Create a future rule (not yet active)
INSERT INTO morbac.rules (org_id, role_id, activity, view, context_id, modality, valid_from)
VALUES (
'11111111-1111-1111-1111-111111111111',
'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa',
'write',
'future_documents',
(SELECT id FROM morbac.contexts WHERE name = 'always'),
'permission',
'2030-01-01 00:00:00+00' -- Future rule
);
-- Create an active time-bounded rule
INSERT INTO morbac.rules (org_id, role_id, activity, view, context_id, modality, valid_from, valid_until)
VALUES (
'11111111-1111-1111-1111-111111111111',
'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa',
'write',
'active_documents',
(SELECT id FROM morbac.contexts WHERE name = 'always'),
'permission',
'2020-01-01 00:00:00+00', -- Started in the past
'2030-12-31 23:59:59+00' -- Ends in the future
);
\echo 'Alice (employee) access to temporal-constrained documents:'
SELECT
'write to temp_documents (expired rule)' as action,
morbac.is_allowed(
'aaaaaaaa-0000-0000-0000-000000000001'::uuid,
'11111111-1111-1111-1111-111111111111'::uuid,
'write',
'temp_documents'
) as allowed
UNION ALL
SELECT
'write to future_documents (not yet active)' as action,
morbac.is_allowed(
'aaaaaaaa-0000-0000-0000-000000000001'::uuid,
'11111111-1111-1111-1111-111111111111'::uuid,
'write',
'future_documents'
) as allowed
UNION ALL
SELECT
'write to active_documents (currently valid)' as action,
morbac.is_allowed(
'aaaaaaaa-0000-0000-0000-000000000001'::uuid,
'11111111-1111-1111-1111-111111111111'::uuid,
'write',
'active_documents'
) as allowed;
\echo ''
\echo '=== Temporal Constraint Tests Completed ==='
+30
View File
@@ -0,0 +1,30 @@
-- ============================================================================
-- MORBAC PostgreSQL Extension - Cross-Organizational Rules Tests
-- ============================================================================
-- This test file covers cross-organizational authorization including:
-- - Cross-organization rules (access between different orgs)
-- - Inter-organizational collaboration scenarios
-- - Cross-org permission validation
--
-- Prerequisites: Assumes 00_setup.sql has been run to set up base data
-- ============================================================================
\echo ''
\echo '=== Cross-Organization Rules ==='
-- Allow Beta managers to read Acme documents (inter-org collaboration)
INSERT INTO morbac.cross_org_rules (source_org_id, target_org_id, role_id, activity, view, context_id, modality) VALUES
('22222222-2222-2222-2222-222222222222', '11111111-1111-1111-1111-111111111111', 'dddddddd-dddd-dddd-dddd-dddddddddddd', 'read', 'documents', (SELECT id FROM morbac.contexts WHERE name = 'always'), 'permission');
\echo 'Diana (manager at Beta) can read Acme documents via cross-org rule:'
SELECT
'read Acme documents from Beta' as action,
morbac.is_allowed(
'dddddddd-0000-0000-0000-000000000004'::uuid,
'11111111-1111-1111-1111-111111111111'::uuid,
'read',
'documents'
) as allowed;
\echo ''
\echo '=== Cross-Organization Rules Tests Completed ==='
+64
View File
@@ -0,0 +1,64 @@
-- ============================================================================
-- MORBAC PostgreSQL Extension - Audit Logging Tests
-- ============================================================================
-- This test file covers audit logging functionality including:
-- - Enabling audit on tables
-- - Auditing INSERT operations
-- - Auditing UPDATE operations
-- - Auditing DELETE operations
-- - Audit log queries and reporting
-- - Disabling audit
--
-- Prerequisites: Assumes 00_setup.sql has been run to set up base data
-- ============================================================================
\echo ''
\echo '=== Audit Logging ==='
-- Enable audit on user_roles table
SELECT morbac.enable_audit('user_roles');
\echo 'Audit trigger created for user_roles table'
-- Perform some auditable operations
INSERT INTO morbac.user_roles (user_id, role_id, org_id)
VALUES (
'ffffffff-0000-0000-0000-000000000001'::uuid,
'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', -- employee role
'11111111-1111-1111-1111-111111111111'
);
-- Update an existing user_role
UPDATE morbac.user_roles
SET active = false
WHERE user_id = 'aaaaaaaa-0000-0000-0000-000000000001'::uuid
AND role_id = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa';
-- Delete a user role
DELETE FROM morbac.user_roles
WHERE user_id = 'ffffffff-0000-0000-0000-000000000001'::uuid
AND role_id = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa';
\echo 'Audit log entries for user_roles operations:'
SELECT
operation,
record_id,
CASE
WHEN old_data IS NOT NULL THEN old_data->>'active'
ELSE 'N/A'
END as old_active,
CASE
WHEN new_data IS NOT NULL THEN new_data->>'active'
ELSE 'N/A'
END as new_active,
session_user,
timestamp
FROM morbac.audit_log
WHERE table_name = 'user_roles'
ORDER BY timestamp;
\echo 'Disable audit on user_roles:'
SELECT morbac.disable_audit('user_roles');
\echo ''
\echo '=== Audit Logging Tests Completed ==='
+37
View File
@@ -0,0 +1,37 @@
-- ============================================================================
-- 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
--
-- Prerequisites: Assumes 00_setup.sql has been run to set up base data
-- ============================================================================
\echo ''
\echo '=== Administration Rules ==='
-- 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');
\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;
\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;
\echo ''
\echo '=== Administration Rules Tests Completed ==='
+91
View File
@@ -0,0 +1,91 @@
-- ============================================================================
-- MORBAC PostgreSQL Extension - Utility Functions and Context Tests
-- ============================================================================
-- This test file covers utility functions and context evaluation including:
-- - Obligations (pending_obligations)
-- - Recommendations (pending_recommendations)
-- - Context evaluation (eval_context)
-- - User role queries (user_roles_in_org, user_has_role)
-- - Policy compilation and idempotency
-- - Adding new policy entries
--
-- Prerequisites: Assumes 00_setup.sql has been run to set up base data
-- ============================================================================
\echo ''
\echo '=== Obligations and Recommendations ==='
\echo 'Obligations for Bob (employee at Acme):'
SELECT * FROM morbac.pending_obligations(
'bbbbbbbb-0000-0000-0000-000000000002'::uuid,
'11111111-1111-1111-1111-111111111111'::uuid
);
\echo ''
\echo 'Recommendations for Charlie (staff at Beta):'
SELECT * FROM morbac.pending_recommendations(
'cccccccc-0000-0000-0000-000000000003'::uuid,
'22222222-2222-2222-2222-222222222222'::uuid
);
\echo ''
\echo '=== Utility Functions ==='
\echo 'Roles for Charlie at Acme Corp:'
SELECT * FROM morbac.user_roles_in_org(
'cccccccc-0000-0000-0000-000000000003'::uuid,
'11111111-1111-1111-1111-111111111111'::uuid
);
\echo ''
\echo 'Roles for Charlie at Beta Inc:'
SELECT * FROM morbac.user_roles_in_org(
'cccccccc-0000-0000-0000-000000000003'::uuid,
'22222222-2222-2222-2222-222222222222'::uuid
);
\echo ''
\echo 'Does Alice have admin role at Acme Corp?'
SELECT morbac.user_has_role(
'aaaaaaaa-0000-0000-0000-000000000001'::uuid,
'11111111-1111-1111-1111-111111111111'::uuid,
'admin'
) as has_admin_role;
\echo ''
\echo '=== Context Evaluation ==='
\echo 'Evaluating always context:'
SELECT morbac.eval_context(
(SELECT id FROM morbac.contexts WHERE name = 'always')
) as result;
\echo ''
\echo 'Evaluating business_hours context:'
SELECT morbac.eval_context(
(SELECT id FROM morbac.contexts WHERE name = 'business_hours')
) as result;
\echo ''
\echo 'Evaluating weekend context:'
SELECT morbac.eval_context(
(SELECT id FROM morbac.contexts WHERE name = 'weekend')
) as result;
\echo ''
\echo '=== Policy Re-compilation (Idempotency Test) ==='
\echo 'Compiling policy again (should show 0 new rules, idempotent):'
SELECT * FROM morbac.compile_policy();
\echo ''
\echo '=== Adding New Policy Entry ==='
INSERT INTO morbac.policy (org_name, role_name, activity, view, modality, context_name) VALUES
('Acme Corp', 'admin', 'approve', 'documents', 'permission', 'always');
\echo 'Compiling new policy entry:'
SELECT * FROM morbac.compile_policy();
\echo ''
\echo '=== Utility Functions and Context Tests Completed ==='
+50
View File
@@ -0,0 +1,50 @@
# Test Organization
Tests are organized in the `tests/` directory:
- **00_setup.sql** - Common setup (organizations, roles, users, activities, views)
- **01_authorization.sql** - Basic authorization tests
- **02_hierarchies.sql** - Role, org, activity, view hierarchy tests
- **03_delegation.sql** - Role delegation tests
- **04_constraints.sql** - SoD and cardinality constraint tests
- **05_temporal.sql** - Temporal validity tests
- **06_cross_org.sql** - Cross-organization access tests
- **07_audit.sql** - Audit logging tests
- **08_admin.sql** - Administration permission tests
- **09_utilities.sql** - Utility function tests
## Running Tests
```bash
# Run all tests (creates temp database, runs tests, cleans up)
make test
# Run tests manually with persistent database
createdb morbac_test
./tests/run_tests.sh morbac_test
# Database remains for inspection
dropdb morbac_test # when done
# Run individual test file
psql -d morbac_test -f tests/01_authorization.sql
```
## Test Data
All tests use common setup from `00_setup.sql`:
**Organizations:**
- Acme Corp (11111111-1111-1111-1111-111111111111)
- Beta Inc (22222222-2222-2222-2222-222222222222)
- Acme Subsidiary (child of Acme Corp)
**Test Users:**
- Alice: aaaaaaaa-0000-0000-0000-000000000001 (admin at Acme)
- Bob: bbbbbbbb-0000-0000-0000-000000000002 (employee at Acme)
- Charlie: cccccccc-0000-0000-0000-000000000003 (contractor at Acme, staff at Beta)
- Dave: dddddddd-0000-0000-0000-000000000004 (manager at Beta)
- Eve: eeeeeeee-0000-0000-0000-000000000005 (viewer at Acme)
**Activities:** read, write, delete, manage, export, approve
**Views:** documents, reports, confidential_data, public_data, financial_records, projects
+46
View File
@@ -0,0 +1,46 @@
#!/bin/bash
# =============================================================================
# Test Runner for morbac_pg Extension
# =============================================================================
# Runs all tests in order, loading setup data and executing each test file.
# Usage: ./run_tests.sh [database_name]
# =============================================================================
set -e
# Database name (default: morbac_test)
DB="${1:-morbac_test}"
TEST_DIR="$(dirname "$0")"
echo "======================================"
echo "morbac_pg Extension Test Suite"
echo "======================================"
echo "Database: $DB"
echo ""
# Install extension
echo "=== Installing Extension ==="
psql -d "$DB" -f "$TEST_DIR/../morbac_pg.sql"
# Load common setup
echo ""
echo "=== Loading Test Setup ==="
psql -d "$DB" -f "$TEST_DIR/00_setup.sql"
# Run all test files in order
echo ""
echo "=== Running Tests ==="
for test_file in "$TEST_DIR"/[0-9][0-9]_*.sql; do
if [ -f "$test_file" ]; then
test_name=$(basename "$test_file" .sql)
echo ""
echo "--- Running: $test_name ---"
psql -d "$DB" -f "$test_file"
fi
done
echo ""
echo "======================================"
echo "All Tests Completed"
echo "======================================"