from app.core.project_permissions import PROJECT_PERMISSION_MODULES, normalize_permission_matrix def test_normalize_permission_matrix_makes_admin_fixed_full_access(): matrix = normalize_permission_matrix({"ADMIN": {}}) for module in PROJECT_PERMISSION_MODULES: assert matrix["ADMIN"][module["key"]] == { "read": True, "write": module.get("writable") is not False, } def test_normalize_permission_matrix_keeps_admin_fixed_even_when_disabled(): payload = { "ADMIN": { module["key"]: {"read": False, "write": False} for module in PROJECT_PERMISSION_MODULES } } matrix = normalize_permission_matrix(payload) for module in PROJECT_PERMISSION_MODULES: assert matrix["ADMIN"][module["key"]] == { "read": True, "write": module.get("writable") is not False, } def test_normalize_permission_matrix_write_implies_read(): matrix = normalize_permission_matrix({ "CRA": { "subjects": {"read": False, "write": True}, } }) assert matrix["CRA"]["subjects"] == {"read": True, "write": True} def test_business_permission_modules_follow_project_menu(): module_labels = [module["label"] for module in PROJECT_PERMISSION_MODULES] assert module_labels == [ "项目成员", "中心管理", "审计日志导出", "项目总览", "项目里程碑", "合同费用管理", "物资管理", "文件版本管理", "立项与伦理", "启动与授权", "参与者管理", "风险问题", "监查稽查", "eTMF", "FAQ", "共享库", ] def test_default_business_permissions_match_role_responsibilities(): matrix = normalize_permission_matrix() assert matrix["PM"]["project_members"] == {"read": True, "write": True} assert matrix["PM"]["sites"] == {"read": True, "write": True} assert matrix["CRA"]["project_members"] == {"read": False, "write": False} assert matrix["CRA"]["audit_export"] == {"read": False, "write": False} assert matrix["PV"]["sites"] == {"read": False, "write": False} assert matrix["IMP"]["audit_export"] == {"read": False, "write": False} assert matrix["QA"]["audit_export"] == {"read": False, "write": False} assert matrix["CRA"]["project_milestones"] == {"read": True, "write": True} assert matrix["CRA"]["subjects"] == {"read": True, "write": True} assert matrix["CRA"]["monitoring_audit"] == {"read": True, "write": True} assert matrix["PV"]["risk_issues"] == {"read": True, "write": True} assert matrix["IMP"]["materials"] == {"read": True, "write": True} assert matrix["PM"]["faq"] == {"read": True, "write": True} assert matrix["CRA"]["faq"] == {"read": True, "write": True} assert matrix["PM"]["project_overview"] == {"read": True, "write": False} assert matrix["CRA"]["project_overview"] == {"read": True, "write": False} assert matrix["PM"]["shared_library"] == {"read": True, "write": True} assert matrix["CRA"]["shared_library"] == {"read": True, "write": True} def test_project_overview_is_read_only_even_when_write_is_submitted(): matrix = normalize_permission_matrix({ "CRA": { "project_overview": {"read": False, "write": True}, } }) assert matrix["CRA"]["project_overview"] == {"read": True, "write": False} def test_pm_can_be_granted_management_backend_permissions(): matrix = normalize_permission_matrix({ "PM": { "project_members": {"read": True, "write": True}, "sites": {"read": True, "write": True}, "audit_export": {"read": True, "write": True}, } }) assert matrix["PM"]["project_members"] == {"read": True, "write": True} assert matrix["PM"]["sites"] == {"read": True, "write": True} assert matrix["PM"]["audit_export"] == {"read": True, "write": True} def test_non_pm_roles_cannot_be_granted_management_backend_permissions(): management_modules = ["project_members", "sites", "audit_export"] matrix = normalize_permission_matrix({ role: { module: {"read": True, "write": True} for module in management_modules } for role in ["CRA", "PV", "IMP", "QA"] }) for role in ["CRA", "PV", "IMP", "QA"]: for module in management_modules: assert matrix[role][module] == {"read": False, "write": False} def test_each_non_admin_role_can_toggle_each_writable_module(): roles = ["PM", "CRA", "PV", "IMP", "QA"] management_modules = {"project_members", "sites", "audit_export"} writable_modules = [ module["key"] for module in PROJECT_PERMISSION_MODULES if module.get("writable") is not False and module["key"] not in management_modules ] for role in roles: enabled = normalize_permission_matrix({ role: { module: {"read": False, "write": True} for module in writable_modules } }) disabled = normalize_permission_matrix({ role: { module["key"]: {"read": False, "write": False} for module in PROJECT_PERMISSION_MODULES } }) for module in writable_modules: assert enabled[role][module] == {"read": True, "write": True} assert disabled[role][module] == {"read": False, "write": False} def test_read_only_modules_never_accept_write_for_any_role(): read_only_modules = [ module["key"] for module in PROJECT_PERMISSION_MODULES if module.get("writable") is False ] payload = { role: { module: {"read": False, "write": True} for module in read_only_modules } for role in ["ADMIN", "PM", "CRA", "PV", "IMP", "QA"] } matrix = normalize_permission_matrix(payload) for role in ["ADMIN", "PM", "CRA", "PV", "IMP", "QA"]: for module in read_only_modules: assert matrix[role][module] == {"read": True, "write": False}