148 lines
4.5 KiB
Python
148 lines
4.5 KiB
Python
from __future__ import annotations
|
|
|
|
import unittest
|
|
|
|
from govoplan_core.core.access import PrincipalRef
|
|
from govoplan_core.core.policy import (
|
|
DefinitionGovernanceRequest,
|
|
DefinitionScopeRef,
|
|
)
|
|
from govoplan_policy.backend.definition_governance import (
|
|
DefinitionGovernancePolicyProvider,
|
|
)
|
|
|
|
|
|
class DefinitionGovernancePolicyTests(unittest.TestCase):
|
|
def setUp(self) -> None:
|
|
self.policy = DefinitionGovernancePolicyProvider()
|
|
self.actor = PrincipalRef(
|
|
account_id="account-1",
|
|
membership_id="user-1",
|
|
tenant_id="tenant-1",
|
|
group_ids=frozenset({"group-1"}),
|
|
)
|
|
|
|
def _resolve(self, **overrides):
|
|
values = {
|
|
"module_id": "dataflow",
|
|
"definition_ref": "pipeline:1",
|
|
"tenant_id": "tenant-1",
|
|
"definition_scope": DefinitionScopeRef(
|
|
"tenant",
|
|
"tenant-1",
|
|
),
|
|
"target_scope": DefinitionScopeRef("tenant", "tenant-1"),
|
|
"definition_kind": "flow",
|
|
"action": "view",
|
|
"actor": self.actor,
|
|
"status": "active",
|
|
"inherit_to_lower_scopes": False,
|
|
"allow_run": True,
|
|
"allow_reuse": False,
|
|
"allow_automation": False,
|
|
}
|
|
values.update(overrides)
|
|
return self.policy.resolve_definition_action(
|
|
request=DefinitionGovernanceRequest(**values)
|
|
)
|
|
|
|
def test_system_definition_is_read_only_when_inherited(self) -> None:
|
|
view = self._resolve(
|
|
definition_scope=DefinitionScopeRef("system"),
|
|
inherit_to_lower_scopes=True,
|
|
)
|
|
edit = self._resolve(
|
|
definition_scope=DefinitionScopeRef("system"),
|
|
inherit_to_lower_scopes=True,
|
|
action="edit",
|
|
)
|
|
|
|
self.assertTrue(view.allowed)
|
|
self.assertFalse(edit.allowed)
|
|
self.assertEqual(
|
|
["system", "tenant:tenant-1"],
|
|
[step.path for step in view.source_path],
|
|
)
|
|
|
|
def test_templates_cannot_run_or_be_automated(self) -> None:
|
|
run = self._resolve(
|
|
definition_kind="template",
|
|
action="run",
|
|
allow_run=True,
|
|
)
|
|
automated = self._resolve(
|
|
definition_kind="template",
|
|
action="automate",
|
|
allow_run=True,
|
|
allow_automation=True,
|
|
)
|
|
|
|
self.assertFalse(run.allowed)
|
|
self.assertFalse(automated.allowed)
|
|
|
|
def test_reuse_and_automation_are_independent_narrowing_grants(self) -> None:
|
|
reuse = self._resolve(action="reuse", allow_reuse=True)
|
|
automated = self._resolve(
|
|
action="automate",
|
|
allow_run=True,
|
|
allow_automation=False,
|
|
)
|
|
|
|
self.assertTrue(reuse.allowed)
|
|
self.assertFalse(automated.allowed)
|
|
|
|
def test_ancestor_limits_cannot_be_broadened(self) -> None:
|
|
decision = self._resolve(
|
|
action="reuse",
|
|
allow_reuse=True,
|
|
context={
|
|
"ancestor_limits": {"allow_reuse": False},
|
|
"ancestor_source": {
|
|
"scope_type": "system",
|
|
"label": "System template",
|
|
},
|
|
},
|
|
)
|
|
|
|
self.assertFalse(decision.allowed)
|
|
self.assertFalse(
|
|
decision.details["effective_limits"]["allow_reuse"]
|
|
)
|
|
self.assertEqual("system", decision.source_path[0].path)
|
|
|
|
def test_ancestor_inheritance_limit_controls_visibility(self) -> None:
|
|
decision = self._resolve(
|
|
definition_scope=DefinitionScopeRef("system"),
|
|
inherit_to_lower_scopes=True,
|
|
context={
|
|
"ancestor_limits": {
|
|
"inherit_to_lower_scopes": False,
|
|
},
|
|
"ancestor_source": {
|
|
"scope_type": "system",
|
|
"label": "Restricted ancestor",
|
|
},
|
|
},
|
|
)
|
|
|
|
self.assertFalse(decision.allowed)
|
|
self.assertEqual(
|
|
"The system definition is not inherited by lower scopes.",
|
|
decision.reason,
|
|
)
|
|
|
|
def test_group_and_user_scopes_are_visible_only_to_the_actor(self) -> None:
|
|
group = self._resolve(
|
|
definition_scope=DefinitionScopeRef("group", "group-1")
|
|
)
|
|
user = self._resolve(
|
|
definition_scope=DefinitionScopeRef("user", "user-2")
|
|
)
|
|
|
|
self.assertTrue(group.allowed)
|
|
self.assertFalse(user.allowed)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|