"""Dashboard summary API.""" import uuid from datetime import datetime, timedelta, timezone from app.models import Event, Host, Problem def _host(db, name: str) -> Host: h = Host( hostname=name, os_family="linux", product="ssh-monitor", last_seen_at=datetime.now(timezone.utc), ) db.add(h) db.flush() return h def _event(db, host: Host, etype: str, *, received_at: datetime | None = None) -> Event: now = received_at or datetime.now(timezone.utc) e = Event( event_id=str(uuid.uuid4()), host_id=host.id, occurred_at=now, received_at=now, category="security", type=etype, severity="info", title=f"t {etype}", summary="s", payload={}, ) db.add(e) db.flush() return e def test_dashboard_summary_top_and_problems_24h(client, db_session, jwt_headers): h1 = _host(db_session, "web-01") h2 = _host(db_session, "db-01") now = datetime.now(timezone.utc) for _ in range(3): _event(db_session, h1, "ssh.login.failed") _event(db_session, h2, "agent.heartbeat") _event(db_session, h2, "agent.heartbeat") db_session.add( Problem( host_id=h1.id, title="open now", summary="s", severity="high", status="open", rule_id="rule:test", fingerprint="fp1", event_count=1, last_seen_at=now, created_at=now - timedelta(hours=2), updated_at=now - timedelta(hours=2), ) ) db_session.add( Problem( host_id=h2.id, title="resolved today", summary="s", severity="warning", status="resolved", rule_id="rule:test", fingerprint="fp2", event_count=1, last_seen_at=now, created_at=now - timedelta(hours=5), updated_at=now - timedelta(hours=1), ) ) db_session.commit() r = client.get("/api/v1/dashboards/summary", headers=jwt_headers) assert r.status_code == 200 body = r.json() assert body["events_last_24h"] == 5 assert body["problems_open"] == 1 assert body["problems_opened_24h"] == 2 assert body["problems_resolved_24h"] == 1 assert body["top_hosts"][0]["hostname"] == "web-01" assert body["top_hosts"][0]["count"] == 3 types = {row["type"]: row["count"] for row in body["top_event_types"]} assert types["ssh.login.failed"] == 3 assert types["agent.heartbeat"] == 2 def test_dashboard_daily_reports_24h_includes_ssh_and_rdp(client, db_session, jwt_headers): h_ssh = _host(db_session, "ssh-pilot") h_rdp = _host(db_session, "rdp-pilot") h_rdp.product = "rdp-login-monitor" now = datetime.now(timezone.utc) _event(db_session, h_ssh, "report.daily.ssh", received_at=now) _event(db_session, h_rdp, "report.daily.rdp", received_at=now) db_session.commit() r = client.get("/api/v1/dashboards/summary", headers=jwt_headers) assert r.status_code == 200 assert r.json()["daily_reports_24h"] == 2 def test_dashboard_recent_events_ordered_by_received_at(client, db_session, jwt_headers): h = _host(db_session, "live-host") now = datetime.now(timezone.utc) older = _event(db_session, h, "agent.lifecycle", received_at=now - timedelta(minutes=5)) newer = _event(db_session, h, "agent.heartbeat", received_at=now) db_session.commit() r = client.get("/api/v1/dashboards/recent-events?limit=8", headers=jwt_headers) assert r.status_code == 200 rows = r.json() assert len(rows) >= 2 assert rows[0]["id"] == newer.id assert rows[0]["type"] == "agent.heartbeat" assert rows[1]["id"] == older.id