test_domain_template_api.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. from __future__ import annotations
  2. ACTOR_UID = "01900000-0000-7000-8000-000000000101"
  3. class FakeService:
  4. def __init__(self):
  5. self.calls = []
  6. def list_templates(self):
  7. self.calls.append(("list",))
  8. return [{"template_code": "spare_parts", "current_version": 1}]
  9. def get_template(self, template_code):
  10. self.calls.append(("get", template_code))
  11. return {"template_code": template_code, "current_version": 1}
  12. def dry_run(self, definition):
  13. self.calls.append(("dry_run", definition))
  14. return {"valid": True, "diff": {"added_object_types": ["spare_part"]}}
  15. def import_template(self, definition, *, actor_uid):
  16. self.calls.append(("import", definition, actor_uid))
  17. return {"template_code": definition["template_code"], "current_version": 1}
  18. def rollback(self, template_code, *, target_version, actor_uid):
  19. self.calls.append(("rollback", template_code, target_version, actor_uid))
  20. return {"template_code": template_code, "current_version": 2}
  21. def list_imports(self, template_code):
  22. self.calls.append(("audits", template_code))
  23. return [{"operation": "import", "template_code": template_code}]
  24. def _headers(role):
  25. return {"Authorization": f"Bearer {role}"}
  26. def test_domain_template_api_is_readable_and_admin_managed(monkeypatch):
  27. from app import create_app
  28. from app.api.meta_data import domain_templates
  29. service = FakeService()
  30. monkeypatch.setattr(domain_templates, "_service", lambda: service)
  31. monkeypatch.setattr(
  32. "app.core.system.auth.load_identity_from_token",
  33. lambda token, secret: (
  34. {"id": ACTOR_UID, "username": token, "roles": [token]}
  35. if token in {"viewer", "editor", "admin"}
  36. else None
  37. ),
  38. )
  39. app = create_app()
  40. app.config.update(TESTING=True)
  41. client = app.test_client()
  42. listed = client.get("/api/meta/domain-templates", headers=_headers("viewer"))
  43. assert listed.status_code == 200
  44. preview = client.post(
  45. "/api/meta/domain-templates/dry-run",
  46. json={"template_code": "spare_parts"},
  47. headers=_headers("editor"),
  48. )
  49. assert preview.status_code == 200
  50. forbidden = client.post(
  51. "/api/meta/domain-templates/import",
  52. json={"template_code": "spare_parts"},
  53. headers=_headers("editor"),
  54. )
  55. assert forbidden.status_code == 403
  56. imported = client.post(
  57. "/api/meta/domain-templates/import",
  58. json={"template_code": "spare_parts"},
  59. headers=_headers("admin"),
  60. )
  61. assert imported.status_code == 200
  62. assert service.calls[-1][2] == ACTOR_UID
  63. rolled_back = client.post(
  64. "/api/meta/domain-templates/spare_parts/rollback",
  65. json={"target_version": 1},
  66. headers=_headers("admin"),
  67. )
  68. assert rolled_back.status_code == 200
  69. def test_domain_template_paths_have_dedicated_permissions():
  70. from app.core.system.permissions import (
  71. DOMAIN_TEMPLATES_MANAGE,
  72. DOMAIN_TEMPLATES_PREVIEW,
  73. DOMAIN_TEMPLATES_READ,
  74. permission_for_request,
  75. )
  76. assert permission_for_request("/api/meta/domain-templates", "GET") == (
  77. DOMAIN_TEMPLATES_READ,
  78. )
  79. assert permission_for_request("/api/meta/domain-templates/dry-run", "POST") == (
  80. DOMAIN_TEMPLATES_PREVIEW,
  81. )
  82. assert permission_for_request("/api/meta/domain-templates/import", "POST") == (
  83. DOMAIN_TEMPLATES_MANAGE,
  84. )