initial commit after split

This commit is contained in:
2026-06-24 01:43:27 +02:00
parent 2406e70597
commit 7f25a3ccdf
125 changed files with 25551 additions and 0 deletions

View File

@@ -0,0 +1,166 @@
from __future__ import annotations
from pathlib import Path
from govoplan_core.core.modules import FrontendModule, MigrationSpec, ModuleContext, ModuleManifest, NavItem, PermissionDefinition, RoleTemplate
from govoplan_core.db.base import Base
from govoplan_campaign.backend.db import models as campaign_models # noqa: F401 - populate Campaign ORM metadata
def _permission(scope: str, label: str, description: str, category: str) -> PermissionDefinition:
module_id, resource, action = scope.split(":", 2)
return PermissionDefinition(
scope=scope,
label=label,
description=description,
category=category,
level="tenant",
module_id=module_id,
resource=resource,
action=action,
)
PERMISSIONS = (
_permission("campaigns:campaign:read", "View campaigns", "Open campaign metadata, versions and permitted message summaries.", "Campaigns"),
_permission("campaigns:campaign:create", "Create campaigns", "Create new campaigns in an accessible tenant scope.", "Campaigns"),
_permission("campaigns:campaign:update", "Edit campaigns", "Edit current working campaign versions.", "Campaigns"),
_permission("campaigns:campaign:copy", "Copy campaigns", "Create campaigns or working versions from existing campaigns.", "Campaigns"),
_permission("campaigns:campaign:archive", "Archive campaigns", "Archive campaigns without destroying audit evidence.", "Campaigns"),
_permission("campaigns:campaign:delete", "Delete campaigns", "Delete draft-only campaigns where retention policy allows it.", "Campaigns"),
_permission("campaigns:campaign:share", "Share campaigns", "Grant or revoke explicit campaign access.", "Campaigns"),
_permission("campaigns:campaign:validate", "Validate campaigns", "Run technical validation and manage validation locks.", "Campaigns"),
_permission("campaigns:campaign:build", "Build campaigns", "Build exact messages and attachment evidence.", "Campaigns"),
_permission("campaigns:campaign:review", "Approve campaign review", "Approve or reject built messages and review conditions.", "Campaigns"),
_permission("campaigns:campaign:send_test", "Mock-send campaigns", "Use mock delivery and verification tools.", "Campaigns"),
_permission("campaigns:campaign:queue", "Queue campaigns", "Place approved executions into the delivery queue.", "Campaigns"),
_permission("campaigns:campaign:control", "Control delivery", "Pause, resume or cancel queued and sending jobs.", "Campaigns"),
_permission("campaigns:campaign:send", "Send campaigns", "Start real SMTP delivery.", "Campaigns"),
_permission("campaigns:campaign:retry", "Retry delivery", "Retry failed or unattempted delivery jobs.", "Campaigns"),
_permission("campaigns:campaign:reconcile", "Reconcile delivery", "Resolve outcome-unknown SMTP attempts after inspection.", "Campaigns"),
_permission("campaigns:recipient:read", "View recipients", "Read recipient lists and recipient-specific campaign data.", "Recipients"),
_permission("campaigns:recipient:write", "Edit recipients", "Create and edit recipient rows and field values.", "Recipients"),
_permission("campaigns:recipient:import", "Import recipients", "Bulk-import recipient lists.", "Recipients"),
_permission("campaigns:recipient:export", "Export recipients", "Export recipient data and reports.", "Recipients"),
_permission("campaigns:report:read", "View reports", "View campaign delivery reports and aggregate outcomes.", "Reports"),
_permission("campaigns:report:export", "Export reports", "Download detailed campaign reports.", "Reports"),
_permission("campaigns:report:send", "Send reports", "Email campaign reports to configured recipients.", "Reports"),
)
ROLE_TEMPLATES = (
RoleTemplate(
slug="campaign_manager",
name="Campaign manager",
description="Prepare, validate and build campaigns without approving real delivery.",
permissions=(
"campaigns:campaign:read",
"campaigns:campaign:create",
"campaigns:campaign:update",
"campaigns:campaign:copy",
"campaigns:campaign:validate",
"campaigns:campaign:build",
"campaigns:recipient:read",
"campaigns:recipient:write",
"campaigns:recipient:import",
"campaigns:report:read",
),
),
RoleTemplate(
slug="campaign_reviewer",
name="Campaign reviewer",
description="Inspect and approve prepared campaign messages.",
permissions=(
"campaigns:campaign:read",
"campaigns:campaign:validate",
"campaigns:campaign:review",
"campaigns:recipient:read",
"campaigns:report:read",
),
),
RoleTemplate(
slug="campaign_sender",
name="Campaign sender",
description="Queue, test, control, send and reconcile prepared campaigns.",
permissions=(
"campaigns:campaign:read",
"campaigns:campaign:send_test",
"campaigns:campaign:queue",
"campaigns:campaign:control",
"campaigns:campaign:send",
"campaigns:campaign:retry",
"campaigns:campaign:reconcile",
"campaigns:recipient:read",
"campaigns:report:read",
"campaigns:report:send",
),
),
)
def _campaigns_router(context: ModuleContext):
del context
from govoplan_campaign.backend.router import router
return router
manifest = ModuleManifest(
id="campaigns",
name="Campaigns",
version="1.0.0",
dependencies=("access", "files", "mail"),
optional_dependencies=(),
permissions=PERMISSIONS,
route_factory=_campaigns_router,
role_templates=ROLE_TEMPLATES,
nav_items=(
NavItem(path="/campaigns", label="Campaigns", icon="mail-check", required_any=("campaigns:campaign:read",), order=20),
NavItem(
path="/operator",
label="Operator Queue",
icon="activity",
required_any=(
"campaigns:campaign:queue",
"campaigns:campaign:retry",
"campaigns:campaign:reconcile",
"campaigns:campaign:control",
"campaigns:campaign:send",
),
order=30,
),
NavItem(path="/reports", label="Reports", icon="file-text", required_any=("campaigns:report:read",), order=70),
),
frontend=FrontendModule(
module_id="campaigns",
package_name="@govoplan/campaign-webui",
nav_items=(
NavItem(path="/campaigns", label="Campaigns", icon="mail-check", required_any=("campaigns:campaign:read",), order=20),
NavItem(
path="/operator",
label="Operator Queue",
icon="activity",
required_any=(
"campaigns:campaign:queue",
"campaigns:campaign:retry",
"campaigns:campaign:reconcile",
"campaigns:campaign:control",
"campaigns:campaign:send",
),
order=30,
),
NavItem(path="/reports", label="Reports", icon="file-text", required_any=("campaigns:report:read",), order=70),
NavItem(path="/address-book", label="Address Book", icon="users", order=80),
NavItem(path="/templates", label="Templates", icon="form", order=90),
),
),
migration_spec=MigrationSpec(
module_id="campaigns",
metadata=Base.metadata,
script_location=str(Path(__file__).with_name("migrations") / "versions"),
),
)
def get_manifest() -> ModuleManifest:
return manifest