Files
gh-christianlouis-dmarq/backend/app/tests/test_workspace_operator.py
T
2026-05-23 20:10:30 +02:00

162 lines
5.3 KiB
Python

from datetime import datetime, timedelta
from fastapi.testclient import TestClient
from sqlalchemy.orm import Session
from app.models.alert import AlertHistory
from app.models.domain import Domain
from app.models.mail_source import MailSource
from app.models.mail_source_import import MailSourceImport
from app.models.report import DMARCReport
from app.models.workspace import Workspace
from app.models.workspace_access import WorkspaceAuditLog
def _workspace(db_session: Session, slug: str, name: str) -> Workspace:
workspace = Workspace(slug=slug, name=name, active=True)
db_session.add(workspace)
db_session.flush()
return workspace
def test_operator_view_summarizes_each_workspace(
authed_client: TestClient,
db_session: Session,
):
"""MSP operators can see health, import, alert, drift, and retention summaries."""
now = datetime.utcnow()
alpha = _workspace(db_session, "alpha", "Alpha Client")
beta = _workspace(db_session, "beta", "Beta Client")
alpha_domain = Domain(
workspace_id=alpha.id,
name="alpha.example",
active=True,
verified=True,
)
beta_domain = Domain(
workspace_id=beta.id,
name="beta.example",
active=True,
verified=False,
)
alpha_source = MailSource(
workspace_id=alpha.id,
name="Alpha inbox",
method="IMAP",
enabled=True,
)
beta_source = MailSource(
workspace_id=beta.id,
name="Beta inbox",
method="IMAP",
enabled=False,
)
db_session.add_all([alpha_domain, beta_domain, alpha_source, beta_source])
db_session.flush()
db_session.add_all(
[
DMARCReport(
domain_id=alpha_domain.id,
report_id="alpha-report",
org_name="Google",
begin_date=1,
end_date=2,
),
MailSourceImport(
mail_source_id=alpha_source.id,
trigger="manual",
status="success",
finished_at=now,
),
MailSourceImport(
mail_source_id=beta_source.id,
trigger="manual",
status="failed",
finished_at=now,
),
AlertHistory(
fingerprint="beta-alert",
rule="missing_reports",
severity="warning",
domain="beta.example",
title="Missing reports",
detail="No reports received",
is_active=True,
),
WorkspaceAuditLog(
workspace_id=beta.id,
actor_type="api_key",
action="mail_source.updated",
entity_type="mail_source",
entity_name="Beta inbox",
created_at=now - timedelta(days=1),
),
]
)
db_session.commit()
response = authed_client.get("/api/v1/operator/workspaces")
assert response.status_code == 200
by_slug = {item["workspace"]["slug"]: item for item in response.json()["workspaces"]}
assert by_slug["alpha"]["health"]["status"] == "healthy"
assert by_slug["alpha"]["reports"]["aggregate_total"] == 1
assert by_slug["alpha"]["mail_sources"]["last_import_status"] == "success"
assert by_slug["beta"]["health"]["status"] == "critical"
assert by_slug["beta"]["health"]["active_alerts"] == 1
assert by_slug["beta"]["health"]["failed_imports_7d"] == 1
assert by_slug["beta"]["health"]["drift_events_7d"] == 1
assert by_slug["beta"]["recent_drift"][0]["action"] == "mail_source.updated"
def test_operator_view_does_not_include_inactive_workspaces(
authed_client: TestClient,
db_session: Session,
):
"""Inactive workspaces are not listed in the cross-workspace operator view."""
_workspace(db_session, "active", "Active Client")
inactive = Workspace(slug="inactive", name="Inactive Client", active=False)
db_session.add(inactive)
db_session.commit()
response = authed_client.get("/api/v1/operator/workspaces")
assert response.status_code == 200
slugs = {item["workspace"]["slug"] for item in response.json()["workspaces"]}
assert slugs == {"active"}
def test_workspace_retention_update_is_audited(
authed_client: TestClient,
db_session: Session,
):
"""Operators can update workspace retention controls with an audit record."""
workspace = _workspace(db_session, "client", "Client")
db_session.commit()
response = authed_client.put(
f"/api/v1/operator/workspaces/{workspace.id}/retention",
json={
"aggregate_reports_days": 730,
"forensic_reports_days": 120,
"tls_reports_days": 365,
},
headers={"x-forwarded-for": "203.0.113.9"},
)
assert response.status_code == 200
db_session.refresh(workspace)
assert workspace.report_retention_days == 730
assert workspace.forensic_retention_days == 120
assert workspace.tls_report_retention_days == 365
assert response.json()["retention"]["aggregate_reports_days"] == 730
audit = (
db_session.query(WorkspaceAuditLog)
.filter(WorkspaceAuditLog.action == "workspace.retention_updated")
.one()
)
assert audit.workspace_id == workspace.id
assert audit.ip_address == "203.0.113.9"
assert "730" in (audit.details or "")