test_permission_matrix.py 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. def test_fixed_role_permission_matrix_is_monotonic():
  2. from app.core.system.permissions import ROLE_PERMISSIONS
  3. viewer = ROLE_PERMISSIONS["viewer"]
  4. editor = ROLE_PERMISSIONS["editor"]
  5. admin = ROLE_PERMISSIONS["admin"]
  6. assert viewer < editor < admin
  7. assert "governance:read" in viewer
  8. assert "governance:edit" in editor
  9. assert "users:manage" in admin
  10. assert "workflow:activate" in admin
  11. assert "ingestion:run" in editor
  12. assert "data-elements:edit" in editor
  13. assert "ontologies:edit" in editor
  14. assert "governance:responsibilities:read" in viewer
  15. assert "ingestion:admin" in admin
  16. assert "evidence:download" in admin
  17. assert "data-elements:publish" in admin
  18. assert "ontologies:publish" in admin
  19. assert "governance:responsibilities:manage" in admin
  20. def test_data_development_paths_have_specific_write_policies():
  21. from app.core.system.permissions import permission_for_request
  22. assert permission_for_request(
  23. "/api/development/v1/ingestion-jobs", "POST"
  24. ) == ("ingestion:run",)
  25. assert permission_for_request(
  26. "/api/development/v1/ingestion-jobs/job-1/retry", "POST"
  27. ) == ("ingestion:admin",)
  28. assert permission_for_request(
  29. "/api/development/v1/ingestion-jobs/job-1/cancel", "POST"
  30. ) == ("ingestion:run",)
  31. assert permission_for_request(
  32. "/api/development/v1/data-elements", "POST"
  33. ) == ("data-elements:edit",)
  34. assert permission_for_request(
  35. "/api/development/v1/data-elements/element-1/transitions", "POST"
  36. ) == ("data-elements:edit",)
  37. assert permission_for_request(
  38. "/api/development/v1/candidate-decisions", "POST"
  39. ) == ("data-elements:edit",)
  40. def test_business_domain_read_endpoints_are_available_to_viewers():
  41. from app.core.system.permissions import permission_for_request
  42. assert permission_for_request("/api/bd/list", "POST") == (
  43. "governance:read",
  44. )
  45. assert permission_for_request("/api/bd/detail", "POST") == (
  46. "governance:read",
  47. )
  48. assert permission_for_request("/api/bd/save", "POST") == (
  49. "governance:edit",
  50. )
  51. def test_permissions_are_derived_server_side_from_roles():
  52. from app.core.system.permissions import permissions_for_roles
  53. permissions = permissions_for_roles(["viewer", "editor"])
  54. assert "governance:read" in permissions
  55. assert "governance:edit" in permissions
  56. assert "users:manage" not in permissions
  57. def test_every_api_path_has_an_explicit_policy():
  58. from app import create_app
  59. from app.core.system.permissions import permission_for_request
  60. app = create_app()
  61. for rule in app.url_map.iter_rules():
  62. if not rule.rule.startswith("/api/"):
  63. continue
  64. for method in rule.methods - {"HEAD", "OPTIONS"}:
  65. assert permission_for_request(rule.rule, method) is not None, (
  66. method,
  67. rule.rule,
  68. )
  69. def test_knowledge_search_and_ask_posts_are_read_only():
  70. from app.core.system.permissions import READ_GOVERNANCE, permission_for_request
  71. assert permission_for_request("/api/knowledge/search", "POST") == (
  72. READ_GOVERNANCE,
  73. )
  74. assert permission_for_request("/api/knowledge/ask", "POST") == (READ_GOVERNANCE,)
  75. def test_knowledge_admin_routes_require_dedicated_manage_permission():
  76. from app.core.system.permissions import KNOWLEDGE_MANAGE, permission_for_request
  77. assert permission_for_request("/api/knowledge/admin/sync", "GET") == (
  78. KNOWLEDGE_MANAGE,
  79. )
  80. assert permission_for_request(
  81. "/api/knowledge/admin/change-sets/id/retry", "POST"
  82. ) == (KNOWLEDGE_MANAGE,)
  83. def test_data_rule_routes_separate_read_authoring_and_release_permissions():
  84. from app.core.system.permissions import (
  85. DATAFLOW_RELEASE,
  86. RULES_EDIT,
  87. RULES_PUBLISH,
  88. RULES_READ,
  89. permission_for_request,
  90. )
  91. assert permission_for_request("/api/rules/capabilities", "GET") == (
  92. RULES_READ,
  93. )
  94. assert permission_for_request("/api/rules/interpret", "POST") == (
  95. RULES_EDIT,
  96. )
  97. assert permission_for_request("/api/rules/validate", "POST") == (
  98. RULES_EDIT,
  99. )
  100. assert permission_for_request(
  101. "/api/rules/versions/id/publish", "POST"
  102. ) == (RULES_PUBLISH,)
  103. assert permission_for_request(
  104. "/api/rules/production-lines/id/release", "POST"
  105. ) == (DATAFLOW_RELEASE,)
  106. def test_data_factory_actions_have_independent_permissions():
  107. from app.core.system.permissions import (
  108. DATAFLOW_ACTIVATE,
  109. DATAFLOW_CANARY,
  110. DATAFLOW_DEPLOY,
  111. DATAFLOW_ROLLBACK,
  112. RULES_EXECUTE,
  113. permission_for_request,
  114. )
  115. assert permission_for_request("/api/rules/deployments", "POST") == (
  116. DATAFLOW_DEPLOY,
  117. )
  118. assert permission_for_request(
  119. "/api/rules/deployments/id/deploy-disabled", "POST"
  120. ) == (DATAFLOW_DEPLOY,)
  121. assert permission_for_request(
  122. "/api/rules/deployments/id/canary", "POST"
  123. ) == (DATAFLOW_CANARY, RULES_EXECUTE)
  124. assert permission_for_request(
  125. "/api/rules/deployments/id/execute", "POST"
  126. ) == (RULES_EXECUTE,)
  127. assert permission_for_request(
  128. "/api/rules/deployments/id/activate", "POST"
  129. ) == (DATAFLOW_ACTIVATE,)
  130. assert permission_for_request(
  131. "/api/rules/deployments/id/rollback", "POST"
  132. ) == (DATAFLOW_ROLLBACK,)
  133. assert permission_for_request(
  134. "/api/rules/deployments/id/reconcile-deploy", "POST"
  135. ) == (DATAFLOW_DEPLOY,)
  136. assert permission_for_request(
  137. "/api/rules/deployments/id/reconcile-activate", "POST"
  138. ) == (DATAFLOW_ACTIVATE,)
  139. assert permission_for_request(
  140. "/api/rules/deployments/id/reconcile-rollback", "POST"
  141. ) == (DATAFLOW_ROLLBACK,)
  142. assert permission_for_request(
  143. "/api/rules/deployments/id/reconcile-execute", "POST"
  144. ) == (RULES_EXECUTE,)