174 lines
5.3 KiB
Python
174 lines
5.3 KiB
Python
from __future__ import annotations
|
|
|
|
import unittest
|
|
from types import SimpleNamespace
|
|
|
|
from govoplan_core.core.access import (
|
|
CAPABILITY_ACCESS_DIRECTORY,
|
|
AccountRef,
|
|
GroupRef,
|
|
UserRef,
|
|
)
|
|
from govoplan_core.core.references import (
|
|
access_scope_reference_options,
|
|
validate_access_scope_reference,
|
|
)
|
|
|
|
|
|
class _Directory:
|
|
users = (
|
|
UserRef(
|
|
id="membership-1",
|
|
account_id="account-1",
|
|
tenant_id="tenant-1",
|
|
email="ada@example.test",
|
|
display_name="Ada",
|
|
),
|
|
UserRef(
|
|
id="membership-2",
|
|
account_id="account-2",
|
|
tenant_id="tenant-1",
|
|
email="inactive@example.test",
|
|
display_name="Inactive",
|
|
status="inactive",
|
|
),
|
|
)
|
|
groups = (
|
|
GroupRef(id="group-1", tenant_id="tenant-1", name="Finance"),
|
|
GroupRef(
|
|
id="group-2",
|
|
tenant_id="tenant-1",
|
|
name="Former team",
|
|
status="inactive",
|
|
),
|
|
)
|
|
|
|
def get_account(self, account_id):
|
|
if account_id not in {"account-1", "account-2"}:
|
|
return None
|
|
return AccountRef(id=account_id, email=f"{account_id}@example.test")
|
|
|
|
def get_user(self, user_id):
|
|
return next((item for item in self.users if item.id == user_id), None)
|
|
|
|
def get_users(self, user_ids):
|
|
return {item.id: item for item in self.users if item.id in set(user_ids)}
|
|
|
|
def users_for_tenant(self, tenant_id):
|
|
return tuple(item for item in self.users if item.tenant_id == tenant_id)
|
|
|
|
def get_group(self, group_id):
|
|
return next((item for item in self.groups if item.id == group_id), None)
|
|
|
|
def get_groups(self, group_ids):
|
|
return {item.id: item for item in self.groups if item.id in set(group_ids)}
|
|
|
|
def groups_for_tenant(self, tenant_id):
|
|
return tuple(item for item in self.groups if item.tenant_id == tenant_id)
|
|
|
|
def groups_for_user(self, user_id, *, tenant_id):
|
|
del user_id
|
|
return self.groups_for_tenant(tenant_id)
|
|
|
|
def display_label(self, subject):
|
|
return subject.label
|
|
|
|
|
|
class _Registry:
|
|
directory = _Directory()
|
|
|
|
def has_capability(self, name):
|
|
return name == CAPABILITY_ACCESS_DIRECTORY
|
|
|
|
def capability(self, name):
|
|
return self.directory if self.has_capability(name) else None
|
|
|
|
|
|
class ReferenceOptionTests(unittest.TestCase):
|
|
def setUp(self) -> None:
|
|
self.principal = SimpleNamespace(
|
|
tenant_id="tenant-1",
|
|
account_id="account-1",
|
|
display_name="Ada",
|
|
email="ada@example.test",
|
|
group_ids=frozenset({"group-1"}),
|
|
)
|
|
|
|
def test_user_values_are_canonical_account_ids(self) -> None:
|
|
options = access_scope_reference_options(
|
|
_Registry(),
|
|
self.principal,
|
|
scope_type="user",
|
|
administrative=True,
|
|
)
|
|
|
|
self.assertEqual(["account-1", "account-2"], [item.value for item in options])
|
|
self.assertEqual("membership-1", options[0].provenance["membership_id"])
|
|
self.assertTrue(options[1].disabled)
|
|
self.assertEqual("inactive", options[1].availability)
|
|
|
|
def test_unavailable_selected_values_remain_readable(self) -> None:
|
|
options = access_scope_reference_options(
|
|
_Registry(),
|
|
self.principal,
|
|
scope_type="group",
|
|
query="missing",
|
|
selected_values=("removed-group",),
|
|
administrative=True,
|
|
)
|
|
|
|
self.assertEqual(1, len(options))
|
|
self.assertEqual("removed-group", options[0].value)
|
|
self.assertEqual("unavailable", options[0].availability)
|
|
self.assertTrue(options[0].disabled)
|
|
|
|
def test_non_administrators_only_receive_permitted_scope_targets(self) -> None:
|
|
users = access_scope_reference_options(
|
|
_Registry(),
|
|
self.principal,
|
|
scope_type="user",
|
|
administrative=False,
|
|
)
|
|
groups = access_scope_reference_options(
|
|
_Registry(),
|
|
self.principal,
|
|
scope_type="group",
|
|
administrative=False,
|
|
)
|
|
|
|
self.assertEqual(["account-1"], [item.value for item in users])
|
|
self.assertEqual(["group-1"], [item.value for item in groups])
|
|
|
|
def test_inactive_targets_are_rejected_but_existing_values_survive(self) -> None:
|
|
with self.assertRaisesRegex(ValueError, "Inactive groups"):
|
|
validate_access_scope_reference(
|
|
_Registry(),
|
|
tenant_id="tenant-1",
|
|
scope_type="group",
|
|
scope_id="group-2",
|
|
)
|
|
self.assertEqual(
|
|
"group-2",
|
|
validate_access_scope_reference(
|
|
_Registry(),
|
|
tenant_id="tenant-1",
|
|
scope_type="group",
|
|
scope_id="group-2",
|
|
preserve_existing="group-2",
|
|
),
|
|
)
|
|
|
|
def test_missing_optional_access_provider_keeps_reduced_mode(self) -> None:
|
|
options = access_scope_reference_options(
|
|
None,
|
|
self.principal,
|
|
scope_type="user",
|
|
)
|
|
|
|
self.assertEqual("account-1", options[0].value)
|
|
self.assertEqual("core", options[0].source_module)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|