101 lines
3.6 KiB
Python
101 lines
3.6 KiB
Python
"""SSE stream — purge domínio VM112 + Desk (Spec 017 Fase 2)."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import queue
|
|
import threading
|
|
import time
|
|
from collections.abc import Iterator
|
|
from typing import Any
|
|
|
|
from app import auth, vm112_domains
|
|
|
|
|
|
def _sse(payload: dict[str, Any]) -> str:
|
|
return f"data: {json.dumps(payload, ensure_ascii=False)}\n\n"
|
|
|
|
|
|
def purge_sse_generator(domain: str, root_password: str, username: str) -> Iterator[str]:
|
|
domain = domain.lower().strip()
|
|
|
|
conn = auth.db()
|
|
try:
|
|
if not vm112_domains.verify_root_password(conn, root_password):
|
|
yield _sse({
|
|
"type": "error",
|
|
"step": vm112_domains._timeline_entry("Validação Root", "fail", "Senha Root incorrecta"),
|
|
})
|
|
return
|
|
finally:
|
|
conn.close()
|
|
|
|
yield _sse({"type": "step", "step": vm112_domains._timeline_entry("Validação Root + confirmação", "ok")})
|
|
yield _sse({
|
|
"type": "step",
|
|
"step": vm112_domains._timeline_entry(
|
|
"Purge VM112 — em execução",
|
|
"running",
|
|
"Carbonio, site, portal, Cloudflare, Traefik…",
|
|
),
|
|
})
|
|
|
|
vm112_result: dict[str, Any] = {"ok": False}
|
|
for kind, payload in vm112_domains.purge_vm112_with_poll(domain, poll_interval=2.0):
|
|
if kind == "step":
|
|
yield _sse({"type": "step", "step": payload, "phase": "vm112"})
|
|
elif kind == "heartbeat":
|
|
yield _sse({
|
|
"type": "heartbeat",
|
|
"elapsed": payload.get("elapsed", 0),
|
|
"label": "Purge VM112 — em execução",
|
|
})
|
|
elif kind == "final":
|
|
vm112_result = payload
|
|
if not vm112_result.get("ok", False):
|
|
yield _sse({
|
|
"type": "error",
|
|
"step": vm112_domains._timeline_entry(
|
|
"Purge VM112",
|
|
"fail",
|
|
str(vm112_result.get("error") or "falhou"),
|
|
),
|
|
})
|
|
return
|
|
break
|
|
|
|
conn = auth.db()
|
|
desk_counts: dict[str, int] = {}
|
|
try:
|
|
domain_l = domain.lower().strip()
|
|
like = f"%{domain_l}%"
|
|
desk_steps = (
|
|
("Desk — webhook_events", "webhook_events", "DELETE FROM webhook_events WHERE payload LIKE ?", (like,)),
|
|
("Desk — tickets", "tickets", "DELETE FROM tickets WHERE subject LIKE ? OR payload LIKE ?", (like, like)),
|
|
("Desk — audit_domains", "audit_domains", "DELETE FROM audit_domains WHERE domain = ?", (domain_l,)),
|
|
("Desk — assist_sessions", "assist_sessions", "DELETE FROM assist_sessions WHERE domain = ?", (domain_l,)),
|
|
("Desk — audit_checks", "audit_checks", "DELETE FROM audit_checks WHERE domain = ?", (domain_l,)),
|
|
)
|
|
for label, key, sql, params in desk_steps:
|
|
yield _sse({"type": "step", "step": vm112_domains._timeline_entry(label, "running")})
|
|
n = conn.execute(sql, params).rowcount
|
|
desk_counts[key] = n
|
|
yield _sse({
|
|
"type": "step",
|
|
"step": vm112_domains._timeline_entry(label, "ok", f"{n} registo(s) removido(s)"),
|
|
"phase": "desk",
|
|
})
|
|
conn.commit()
|
|
finally:
|
|
conn.close()
|
|
|
|
total_desk = sum(desk_counts.values())
|
|
done_step = vm112_domains._timeline_entry("Purge concluído", "ok", f"Desk: {total_desk} registo(s)")
|
|
yield _sse({
|
|
"type": "done",
|
|
"step": done_step,
|
|
"domain": domain,
|
|
"vm112": vm112_result,
|
|
"desk": desk_counts,
|
|
"by": username,
|
|
})
|