118 lines
3.8 KiB
Python
118 lines
3.8 KiB
Python
from __future__ import annotations
|
|
|
|
import unittest
|
|
from types import SimpleNamespace
|
|
from unittest.mock import patch
|
|
|
|
from fastapi import HTTPException
|
|
|
|
from govoplan_core.auth import ApiPrincipal
|
|
from govoplan_core.core.access import PrincipalRef
|
|
from govoplan_core.core.modules import ModuleManifest
|
|
from govoplan_core.core.views import ViewSurface
|
|
from govoplan_views.backend.router import (
|
|
_catalogue,
|
|
_require_definition_read,
|
|
_require_definition_write,
|
|
)
|
|
|
|
|
|
def principal(
|
|
*,
|
|
account_id: str = "account-1",
|
|
scopes: tuple[str, ...],
|
|
group_ids: tuple[str, ...] = (),
|
|
) -> ApiPrincipal:
|
|
return ApiPrincipal(
|
|
principal=PrincipalRef(
|
|
account_id=account_id,
|
|
membership_id="membership-1",
|
|
tenant_id="tenant-1",
|
|
scopes=frozenset(scopes),
|
|
group_ids=frozenset(group_ids),
|
|
),
|
|
account=object(),
|
|
user=object(),
|
|
)
|
|
|
|
|
|
class ViewDefinitionAuthorizationTests(unittest.TestCase):
|
|
def test_personal_writer_cannot_edit_another_accounts_view(self) -> None:
|
|
actor = principal(scopes=("views:personal_definition:write",))
|
|
|
|
_require_definition_write(actor, "user", "account-1")
|
|
with self.assertRaises(HTTPException) as caught:
|
|
_require_definition_write(actor, "user", "account-2")
|
|
|
|
self.assertEqual(403, caught.exception.status_code)
|
|
|
|
def test_group_reader_is_limited_to_current_memberships(self) -> None:
|
|
actor = principal(
|
|
scopes=("views:group_definition:read",),
|
|
group_ids=("group-1",),
|
|
)
|
|
|
|
_require_definition_read(actor, "group", "group-1")
|
|
with self.assertRaises(HTTPException) as caught:
|
|
_require_definition_read(actor, "group", "group-2")
|
|
|
|
self.assertEqual(403, caught.exception.status_code)
|
|
|
|
def test_tenant_manager_can_manage_owned_views(self) -> None:
|
|
actor = principal(scopes=("views:definition:write",))
|
|
|
|
_require_definition_write(actor, "group", "group-2")
|
|
_require_definition_write(actor, "user", "account-2")
|
|
|
|
def test_catalogue_excludes_surfaces_of_tenant_unavailable_modules(self) -> None:
|
|
actor = principal(scopes=("views:definition:read",))
|
|
registry = SimpleNamespace(
|
|
manifests=lambda: (
|
|
ModuleManifest(id="access", name="Access", version="1"),
|
|
ModuleManifest(id="views", name="Views", version="1"),
|
|
ModuleManifest(id="files", name="Files", version="1"),
|
|
),
|
|
view_surfaces=lambda: (
|
|
ViewSurface(
|
|
id="views.module",
|
|
module_id="views",
|
|
kind="module",
|
|
label="Views",
|
|
),
|
|
ViewSurface(
|
|
id="files.module",
|
|
module_id="files",
|
|
kind="module",
|
|
label="Files",
|
|
),
|
|
),
|
|
)
|
|
tenant = SimpleNamespace(
|
|
settings={
|
|
"module_entitlements": {
|
|
"schema_version": 1,
|
|
"revision": 1,
|
|
"system_policy": {
|
|
"available_modules": ["access", "views"],
|
|
"forced_modules": ["access"],
|
|
},
|
|
"tenant_selection": {
|
|
"enabled_modules": ["views"],
|
|
},
|
|
}
|
|
}
|
|
)
|
|
session = SimpleNamespace(get=lambda model, tenant_id: tenant)
|
|
|
|
with patch(
|
|
"govoplan_views.backend.router.get_registry",
|
|
return_value=registry,
|
|
):
|
|
catalogue = _catalogue(session, actor)
|
|
|
|
self.assertEqual(["views.module"], [surface.id for surface in catalogue])
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|