feat(campaigns): add accountable work assignments
Module Package Release / publish-packages (push) Successful in 14s

This commit is contained in:
2026-08-22 00:50:03 +02:00
parent c2f083e5f6
commit 2630498026
23 changed files with 3011 additions and 15 deletions
+79
View File
@@ -28,6 +28,8 @@ from govoplan_campaign.backend.db.models import (
CampaignMessageActionAttempt,
CampaignShare,
CampaignVersion,
CampaignWorkAssignment,
CampaignWorkAssignmentEvent,
ImapAppendAttempt,
PostboxDeliveryAttempt,
PrintOutputAttempt,
@@ -47,6 +49,81 @@ GROUP_ID = "group-1"
class CampaignAccessProviderTests(unittest.TestCase):
def test_work_assignment_provenance_keeps_accountability_separate_from_access(self) -> None:
session = _session()
self.addCleanup(_close_session, session)
_seed_access_subjects(session)
campaign = Campaign(
id="campaign-work",
tenant_id=TENANT_ID,
owner_user_id=OTHER_USER_ID,
external_id="work",
name="Work campaign",
)
checked_at = datetime.now(UTC)
assignment = CampaignWorkAssignment(
id="assignment-1",
tenant_id=TENANT_ID,
campaign_id=campaign.id,
purpose="Not disclosed by provenance",
status="open",
assignee_type="account",
assignee_id="account-1",
assignee_label_snapshot="Subject",
assignee_resolution_state="resolved",
resolution_provenance={"policy_code": "assignment_does_not_grant_access"},
resolution_checked_at=checked_at,
assigned_by_user_id=OTHER_USER_ID,
assigned_by_label_snapshot="Other user",
)
event = CampaignWorkAssignmentEvent(
id="assignment-event-1",
tenant_id=TENANT_ID,
campaign_id=campaign.id,
assignment_id=assignment.id,
event_kind="assigned",
actor_user_id=OTHER_USER_ID,
actor_label_snapshot="Other user",
status_snapshot="open",
assignee_type_snapshot="account",
assignee_id_snapshot="account-1",
assignee_label_snapshot="Subject",
resolution_state_snapshot="resolved",
)
session.add_all(
[
campaign,
assignment,
event,
CampaignShare(
id="share-work",
tenant_id=TENANT_ID,
campaign_id=campaign.id,
target_type="group",
target_id=GROUP_ID,
permission="read",
),
]
)
session.commit()
items = CampaignAccessService().explain_resource_provenance(
session,
_principal(
scopes={"campaigns:campaign:read", "campaigns:assignment:read"},
group_ids={GROUP_ID},
),
resource_type="campaign_work_assignment",
resource_id=assignment.id,
action="campaigns:assignment:read",
)
work = next(item for item in items if item.source == "campaigns.work_assignment")
self.assertEqual("accountability_does_not_grant_access", work.details["authorization_mode"])
self.assertEqual(["campaigns:assignment:read"], work.details["permission_actions"])
self.assertFalse(work.details["purpose_disclosed"])
self.assertNotIn("Not disclosed", repr(items))
self.assertTrue(any(item.id == "share-work" for item in items))
def test_collaboration_access_is_explained_independently_from_campaign_edit(self) -> None:
session = _session()
self.addCleanup(_close_session, session)
@@ -975,6 +1052,8 @@ def _session():
Campaign.__table__,
CampaignShare.__table__,
CampaignCollaborationEntry.__table__,
CampaignWorkAssignment.__table__,
CampaignWorkAssignmentEvent.__table__,
CampaignVersion.__table__,
CampaignJob.__table__,
CampaignIssue.__table__,