Specs stay at repo root (cross-VM). Move deploy and code into logical projects with README per domain, updated manifest.yaml, and symlinks at legacy paths for VM122 backward compatibility.
102 lines
3.5 KiB
Python
102 lines
3.5 KiB
Python
"""Unit tests — Spec 027 RBAC matrix."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import importlib.util
|
|
import sys
|
|
import unittest
|
|
from pathlib import Path
|
|
|
|
API_ROOT = Path(__file__).resolve().parents[1]
|
|
|
|
|
|
def _load(name: str, rel_path: str):
|
|
path = API_ROOT / rel_path
|
|
spec = importlib.util.spec_from_file_location(name, path)
|
|
if spec is None or spec.loader is None:
|
|
raise ImportError(path)
|
|
mod = importlib.util.module_from_spec(spec)
|
|
sys.modules[name] = mod
|
|
spec.loader.exec_module(mod)
|
|
return mod
|
|
|
|
|
|
permissions = _load("permissions_027", "app/permissions.py")
|
|
registry = _load("registry_027", "app/modules/registry.py")
|
|
|
|
ASSIGNABLE_ROLES = permissions.ASSIGNABLE_ROLES
|
|
HUMAN_ROLES = permissions.HUMAN_ROLES
|
|
can_create_foss_order = permissions.can_create_foss_order
|
|
can_manage_billing = permissions.can_manage_billing
|
|
can_read_billing = permissions.can_read_billing
|
|
can_read_crm_leads = permissions.can_read_crm_leads
|
|
can_validate_billing = permissions.can_validate_billing
|
|
is_assignable_role = permissions.is_assignable_role
|
|
ROLE_MODULE_DEFAULTS = registry.ROLE_MODULE_DEFAULTS
|
|
role_module_defaults = registry.role_module_defaults
|
|
|
|
|
|
class TestSpec027Permissions(unittest.TestCase):
|
|
def test_human_role_count(self):
|
|
self.assertGreaterEqual(len(HUMAN_ROLES), 13)
|
|
|
|
def test_assignable_excludes_super_admin(self):
|
|
self.assertNotIn("super_admin", ASSIGNABLE_ROLES)
|
|
self.assertIn("sales_admin", ASSIGNABLE_ROLES)
|
|
self.assertIn("sales_support", ASSIGNABLE_ROLES)
|
|
|
|
def test_sales_admin_billing_validate(self):
|
|
self.assertTrue(can_validate_billing("sales_admin"))
|
|
self.assertTrue(can_manage_billing("sales_admin"))
|
|
self.assertTrue(can_read_billing("sales_admin"))
|
|
|
|
def test_sales_support_no_billing_validate(self):
|
|
self.assertFalse(can_validate_billing("sales_support"))
|
|
self.assertFalse(can_manage_billing("sales_support"))
|
|
self.assertTrue(can_read_billing("sales_support"))
|
|
|
|
def test_finance_billing(self):
|
|
self.assertTrue(can_validate_billing("finance"))
|
|
self.assertTrue(can_create_foss_order("finance"))
|
|
|
|
def test_sales_roles_crm(self):
|
|
self.assertTrue(can_read_crm_leads("sales_admin"))
|
|
self.assertTrue(can_read_crm_leads("sales_support"))
|
|
self.assertTrue(can_read_crm_leads("marketing"))
|
|
|
|
def test_registration_roles(self):
|
|
for role in (
|
|
"ops_lead",
|
|
"technician",
|
|
"noc",
|
|
"sales_admin",
|
|
"sales_support",
|
|
"finance",
|
|
"marketing",
|
|
"seo",
|
|
"developer",
|
|
"devops",
|
|
"security_analyst",
|
|
"content_editor",
|
|
"agentic_operator",
|
|
):
|
|
self.assertTrue(is_assignable_role(role), role)
|
|
|
|
def test_role_module_defaults(self):
|
|
sales_admin_mods = role_module_defaults("sales_admin")
|
|
self.assertIsNotNone(sales_admin_mods)
|
|
assert sales_admin_mods is not None
|
|
self.assertIn("billing-recurrence", sales_admin_mods)
|
|
self.assertNotIn("billing-recurrence", role_module_defaults("sales_support") or set())
|
|
|
|
def test_ops_roles_no_module_filter(self):
|
|
self.assertIsNone(role_module_defaults("ops_lead"))
|
|
self.assertIsNone(role_module_defaults("technician"))
|
|
|
|
def test_all_defaults_registered(self):
|
|
for role, mods in ROLE_MODULE_DEFAULTS.items():
|
|
self.assertIn("core", mods, role)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|