refactor(api): split campaign workflow routers

This commit is contained in:
2026-07-29 20:07:11 +02:00
parent dd9592a192
commit 2199187e8b
22 changed files with 5595 additions and 4437 deletions

View File

@@ -9,7 +9,10 @@ from sqlalchemy import create_engine
from sqlalchemy.orm import Session
from govoplan_access.backend.db.models import Account, Group, User
from govoplan_campaign.backend import router
from govoplan_campaign.backend import router as campaign_api
from govoplan_campaign.backend.routes import campaigns as campaign_routes
from govoplan_campaign.backend.routes import jobs as job_routes
from govoplan_campaign.backend.routes import reports as report_routes
from govoplan_campaign.backend.db.models import Campaign, CampaignJob, CampaignVersion
from govoplan_campaign.backend.reports.aggregate import (
AggregateCampaignReportError,
@@ -37,10 +40,10 @@ def test_full_report_and_job_detail_reject_aggregate_only_principal() -> None:
campaign = SimpleNamespace(id="campaign-1", tenant_id="tenant-1")
with (
patch.object(router, "_get_campaign_for_principal", return_value=campaign),
patch.object(report_routes, "_get_campaign_for_principal", return_value=campaign),
pytest.raises(HTTPException) as full_report_denied,
):
router.campaign_report(
report_routes.campaign_report(
"campaign-1",
session=session,
principal=principal, # type: ignore[arg-type]
@@ -49,10 +52,10 @@ def test_full_report_and_job_detail_reject_aggregate_only_principal() -> None:
assert "campaigns:recipient:read" in full_report_denied.value.detail
with (
patch.object(router, "_get_campaign_for_principal", return_value=campaign),
patch.object(job_routes, "_get_campaign_for_principal", return_value=campaign),
pytest.raises(HTTPException) as job_detail_denied,
):
router.get_job_detail(
job_routes.get_job_detail(
"campaign-1",
"job-1",
session=session,
@@ -61,10 +64,10 @@ def test_full_report_and_job_detail_reject_aggregate_only_principal() -> None:
assert job_detail_denied.value.status_code == 403
with (
patch.object(router, "_get_campaign_for_principal", return_value=campaign),
patch.object(report_routes, "_get_campaign_for_principal", return_value=campaign),
pytest.raises(HTTPException) as report_email_denied,
):
router.email_campaign_report(
report_routes.email_campaign_report(
"campaign-1",
ReportEmailRequest(to=["auditor@example.test"]),
session=session,
@@ -74,10 +77,10 @@ def test_full_report_and_job_detail_reject_aggregate_only_principal() -> None:
assert "campaigns:recipient:export" in report_email_denied.value.detail
with (
patch.object(router, "_get_campaign_for_principal", return_value=campaign),
patch.object(job_routes, "_get_campaign_for_principal", return_value=campaign),
pytest.raises(HTTPException) as diagnostics_denied,
):
router.get_job_diagnostics(
job_routes.get_job_diagnostics(
"campaign-1",
"job-1",
session=session,
@@ -93,14 +96,14 @@ def test_aggregate_route_uses_only_the_safe_projection() -> None:
safe_projection = Mock()
with (
patch.object(router, "_get_campaign_for_principal") as acl,
patch.object(campaign_routes, "_get_campaign_for_principal") as acl,
patch.object(
router,
campaign_routes,
"generate_aggregate_campaign_report",
return_value=safe_projection,
) as generate,
):
result = router.aggregate_campaign_report(
result = campaign_routes.aggregate_campaign_report(
"campaign-1",
session=session,
principal=principal, # type: ignore[arg-type]
@@ -118,7 +121,7 @@ def test_aggregate_route_uses_only_the_safe_projection() -> None:
@pytest.mark.parametrize("path", ["/campaigns/aggregate-reports", "/campaigns/aggregate-reports/{campaign_id}"])
def test_aggregate_routes_require_report_read_permission(path: str) -> None:
route = next(item for item in router.router.routes if item.path == path)
route = next(item for item in campaign_api.router.routes if item.path == path)
dependency = next(item for item in route.dependant.dependencies if item.name == "principal")
with pytest.raises(HTTPException) as denied: