Implement typed effective identity relationships

This commit is contained in:
2026-08-02 14:44:42 +02:00
parent 820ea5eeab
commit 6f6c45f6e2
13 changed files with 1901 additions and 3 deletions
+58
View File
@@ -12,7 +12,9 @@ from govoplan_idm.backend.assignment_lifecycle import SqlIdmAssignmentLifecycle
from govoplan_idm.backend.db.models import (
IdmFunctionAssignmentChange,
IdmFunctionAssignmentChangeEvent,
IdmIdentityRelationship,
IdmOrganizationFunctionAssignment,
IdmTypedGroup,
)
from govoplan_organizations.backend.db import models as organization_models # noqa: F401
@@ -26,6 +28,8 @@ class AssignmentExpiryTests(unittest.TestCase):
IdmOrganizationFunctionAssignment.__table__,
IdmFunctionAssignmentChange.__table__,
IdmFunctionAssignmentChangeEvent.__table__,
IdmTypedGroup.__table__,
IdmIdentityRelationship.__table__,
ChangeSequenceEntry.__table__,
],
)
@@ -204,6 +208,60 @@ class AssignmentExpiryTests(unittest.TestCase):
history = session.query(IdmFunctionAssignmentChangeEvent).all()
self.assertEqual(["expired"], [item.action for item in history])
def test_sweep_emits_relationship_expiry_once(self) -> None:
boundary = datetime(2026, 8, 2, 12, tzinfo=timezone.utc)
with self.database.session() as session:
session.add(
IdmTypedGroup(
id="group-1",
tenant_id="tenant-1",
key="eligible",
name="Eligible",
group_type="business_status",
)
)
session.add(
IdmIdentityRelationship(
id="relationship-due",
tenant_id="tenant-1",
relationship_kind="member",
subject_identity_id="identity-1",
target_group_id="group-1",
valid_until=boundary - timedelta(seconds=1),
status="active",
properties={},
provenance={},
)
)
session.commit()
events: list[PlatformEvent] = []
bus = EventBus()
bus.subscribe("idm.relationship.expired.v1", events.append)
with self.database.SessionLocal() as session, event_bus_context(bus):
result = self.lifecycle.process_expired(
session,
tenant_id="tenant-1",
effective_at=boundary,
)
session.commit()
repeated = self.lifecycle.process_expired(
session,
tenant_id="tenant-1",
effective_at=boundary,
)
session.commit()
self.assertEqual(["relationship-due"], result["relationship_ids"])
self.assertEqual(1, result["expired_relationships"])
self.assertEqual(0, repeated["expired_relationships"])
self.assertEqual(1, len(events))
self.assertEqual("identity-1", events[0].subject.id)
with self.database.session() as session:
item = session.get(IdmIdentityRelationship, "relationship-due")
self.assertEqual(2, item.revision)
self.assertIsNotNone(item.expired_event_at)
if __name__ == "__main__":
unittest.main()