"""Teste de confirmação — OpenPanel API multidomínio (Spec 028).""" from __future__ import annotations import random import re import string import time from typing import Any from app.vm123 import openpanel_client TEST_PASSWORD = "LbOpenTest805353" DEFAULT_PLAN = "ligbox-site-cms" USER_RE = re.compile(r"^[a-z][a-z0-9]{2,15}$") def _step(name: str, ok: bool, detail: str = "", extra: dict | None = None) -> dict[str, Any]: return {"name": name, "ok": ok, "detail": detail, **(extra or {})} def _default_accounts() -> list[tuple[str, str]]: suffix = "".join(random.choices(string.digits, k=5)) user1 = f"apitest{suffix}" user2 = f"apitestb{suffix}" return [ (user1, f"apitest{suffix}.ligbox.com.br"), (user2, f"apitestb{suffix}.ligbox.com.br"), ] def _normalize_accounts( accounts: list[dict[str, str]] | None, *, auto_names: bool = True, ) -> list[tuple[str, str]]: out: list[tuple[str, str]] = [] if accounts: for row in accounts: username = (row.get("username") or "").strip().lower() domain = (row.get("domain") or "").strip().lower() if not username and not domain: continue if not username and domain: username = re.sub(r"[^a-z0-9]", "", domain.split(".")[0])[:15] if not domain and username: domain = f"{username}.ligbox.com.br" if "." not in username else username if not USER_RE.fullmatch(username): raise ValueError(f"username inválido: {username!r} (a-z, 3-16 chars)") out.append((username, domain)) if not out and auto_names: return _default_accounts() if not out: raise ValueError("informe pelo menos uma conta/domínio ou active auto_names") return out[:5] def run_confirmation_test( *, triggered_by: str = "api", accounts: list[dict[str, str]] | None = None, password: str = TEST_PASSWORD, cleanup: bool = True, auto_names: bool = True, check_reference: bool = True, ) -> dict[str, Any]: """Suite E2E: health → list → N contas/domínios → cleanup opcional.""" started = time.time() steps: list[dict[str, Any]] = [] try: pairs = _normalize_accounts(accounts, auto_names=auto_names) except ValueError as exc: return { "ok": False, "suite": "openpanel-multidomain-api-confirm", "message": str(exc), "steps": [_step("validate_input", False, str(exc))], "steps_passed": 0, "steps_total": 1, "triggered_by": triggered_by, } health = openpanel_client.health() steps.append( _step( "bridge_health", health.get("ok") is True, f"bridge={health.get('bridge')} url={health.get('bridge_url')}", {"response": health}, ) ) if not health.get("ok"): return _result(False, steps, pairs[0][0], triggered_by, started, pairs=pairs) try: listed = openpanel_client.list_users() users = (listed.get("users") or {}).get("data") or [] steps.append(_step("list_users", True, f"{len(users)} contas", {"count": len(users)})) except openpanel_client.OpenPanelBridgeError as exc: steps.append(_step("list_users", False, str(exc))) return _result(False, steps, pairs[0][0], triggered_by, started, pairs=pairs) if check_reference: try: ref = openpanel_client.get_user("diarissima") steps.append( _step( "get_reference_user", ref.get("success") is True, (ref.get("domains") or "")[:80], ) ) except openpanel_client.OpenPanelBridgeError as exc: steps.append(_step("get_reference_user", False, str(exc))) created: list[str] = [] for idx, (username, domain) in enumerate(pairs, start=1): label = f"provision_{username}" try: prov = openpanel_client.provision_user( username=username, password=password, email=f"hosting@{domain}", domain=domain, plan_name=DEFAULT_PLAN, ) ok = prov.get("success") is True if ok: created.append(username) steps.append( _step( label, ok, prov.get("response", {}).get("message", "")[:120], {"username": username, "domain": domain, "index": idx}, ) ) except openpanel_client.OpenPanelBridgeError as exc: steps.append(_step(label, False, str(exc), {"username": username, "domain": domain})) try: listed2 = openpanel_client.list_users() names = {u.get("username") for u in (listed2.get("users") or {}).get("data") or []} expected = {u for u, _ in pairs} found = expected & names steps.append( _step( "verify_multidomain_platform", found == expected, f"encontrados {len(found)}/{len(expected)}: {', '.join(sorted(found))}", {"users_found": sorted(found), "users_expected": sorted(expected)}, ) ) except openpanel_client.OpenPanelBridgeError as exc: steps.append(_step("verify_multidomain_platform", False, str(exc))) deleted = 0 if cleanup: for username in created: try: openpanel_client.delete_user(username) deleted += 1 steps.append(_step(f"cleanup_{username}", True, "removido")) except openpanel_client.OpenPanelBridgeError as exc: steps.append(_step(f"cleanup_{username}", False, str(exc))) else: steps.append(_step("cleanup_skipped", True, f"mantidas: {', '.join(created)}")) all_ok = all(s["ok"] for s in steps) cleanup_ok = (not cleanup) or (deleted == len(created)) return _result( all_ok and cleanup_ok, steps, pairs[0][0], triggered_by, started, pairs=pairs, cleanup=cleanup_ok, ) def _result( ok: bool, steps: list[dict[str, Any]], username: str, triggered_by: str, started: float, *, pairs: list[tuple[str, str]] | None = None, cleanup: bool = True, ) -> dict[str, Any]: passed = sum(1 for s in steps if s["ok"]) return { "ok": ok, "suite": "openpanel-multidomain-api-confirm", "spec": "028-openpanel-ce-ligbox-reengineering", "triggered_by": triggered_by, "test_user": username, "accounts_tested": [{"username": u, "domain": d} for u, d in (pairs or [])], "cleanup_done": cleanup, "steps_passed": passed, "steps_total": len(steps), "steps": steps, "duration_sec": round(time.time() - started, 2), "message": ( "OpenPanel via API multidomínio Ligbox Re-engenharia — CONFIRMADO" if ok else "Falha em um ou mais passos — ver steps" ), }