feat(5.20): US-012 audit evenimente medii + teste e2e

log_event best-effort (refoloseste conn apelantului, fara PII in context) la:
- rar_env_activat / rar_env_dezactivat: activare/dezactivare mediu in cont_rar_medii
- rar_env_default_schimbat: schimbare efectiva default in cont_rar_medii si in
  toggle-ul din statusbar (fragment_status_toggle_env)
- rar_env_blocat: tinta indisponibila — 422 pe canalul API (router.py) + WARNING
  pe caile de import web (fallback existent neschimbat, doar logging adaugat)

tests/test_e2e_rar_env.py: lant import->queued cu rar_env corect (ambele canale),
activare Productie logata, tinta indisponibila blocata + logata.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Claude Agent
2026-07-02 20:26:28 +00:00
parent 0a1df31126
commit 3d3eb71a1e
3 changed files with 415 additions and 6 deletions

View File

@@ -175,6 +175,14 @@ def create_prezentari(
try:
env = rezolva_rar_env(conn, acct, req.rar_env)
except MediuIndisponibil as e:
# US-012: audit blocare mediu indisponibil (tip='rar_env_blocat').
log_event(
"rar_env_blocat",
nivel="WARNING",
account_id=acct,
context={"env": e.env},
conn=conn,
)
raise HTTPException(
status_code=422,
detail=err_eroare(
@@ -364,6 +372,14 @@ def valideaza_prezentari(
try:
env = rezolva_rar_env(conn, acct, req.rar_env)
except MediuIndisponibil as e:
# US-012: audit blocare mediu indisponibil pe dry-run (tip='rar_env_blocat').
log_event(
"rar_env_blocat",
nivel="WARNING",
account_id=acct,
context={"env": e.env},
conn=conn,
)
raise HTTPException(
status_code=422,
detail=err_eroare(

View File

@@ -3026,7 +3026,17 @@ async def web_upload_import(
# La 0 medii: rezolva_rar_env cade pe ancora globala (rar_env config), non-blocant.
try:
upload_env = rezolva_rar_env(conn, account_id, rar_env or None)
except (ValueError, MediuIndisponibil):
except MediuIndisponibil as e:
# US-012: audit mediu cerut dar indisponibil (fallback silentios, non-blocant).
log_event(
"rar_env_blocat",
nivel="WARNING",
account_id=account_id,
context={"env": e.env},
conn=conn,
)
upload_env = rar_env_efectiv_cont(conn, account_id) or get_settings().rar_env or "test"
except ValueError:
upload_env = rar_env_efectiv_cont(conn, account_id) or get_settings().rar_env or "test"
# Stagingul in DB (tranzactie explicita)
@@ -3237,7 +3247,17 @@ async def web_save_mapare_coloane(
form_rar_env = str(form.get("rar_env") or "").strip() or None
try:
mapare_env = rezolva_rar_env(conn, account_id, form_rar_env)
except (ValueError, MediuIndisponibil):
except MediuIndisponibil as e:
# US-012: audit mediu cerut dar indisponibil la mapare coloane (fallback silentios).
log_event(
"rar_env_blocat",
nivel="WARNING",
account_id=account_id,
context={"env": e.env},
conn=conn,
)
mapare_env = rar_env_efectiv_cont(conn, account_id) or get_settings().rar_env or "test"
except ValueError:
mapare_env = rar_env_efectiv_cont(conn, account_id) or get_settings().rar_env or "test"
# Computa preview
@@ -3265,7 +3285,17 @@ def web_preview_import(
# Rezolva mediul pentru preview (din query param sau default cont)
try:
preview_env = rezolva_rar_env(conn, account_id, rar_env)
except (ValueError, MediuIndisponibil):
except MediuIndisponibil as e:
# US-012: audit mediu cerut dar indisponibil la preview (fallback silentios).
log_event(
"rar_env_blocat",
nivel="WARNING",
account_id=account_id,
context={"env": e.env},
conn=conn,
)
preview_env = rar_env_efectiv_cont(conn, account_id) or get_settings().rar_env or "test"
except ValueError:
preview_env = rar_env_efectiv_cont(conn, account_id) or get_settings().rar_env or "test"
result = _web_compute_preview(conn, import_id, account_id, rar_env=preview_env)
if isinstance(result, str):
@@ -3909,7 +3939,17 @@ async def web_confirma_import(
# Rezolva mediul RAR tinta al lotului (US-009): form > default cont > ancora globala.
try:
env = rezolva_rar_env(conn, account_id, rar_env_cerut)
except (ValueError, MediuIndisponibil):
except MediuIndisponibil as e:
# US-012: audit mediu cerut dar indisponibil la commit import (fallback silentios).
log_event(
"rar_env_blocat",
nivel="WARNING",
account_id=account_id,
context={"env": e.env},
conn=conn,
)
env = rar_env_efectiv_cont(conn, account_id) or get_settings().rar_env or "test"
except ValueError:
env = rar_env_efectiv_cont(conn, account_id) or get_settings().rar_env or "test"
# Enqueue in tranzactie explicita — INSERT ON CONFLICT DO NOTHING (TOCTOU)
@@ -4613,11 +4653,15 @@ async def cont_rar_medii(request: Request) -> HTMLResponse:
conn = get_connection()
try:
# Starea curenta din DB (inainte de update) — necesara pt logica de confirmare prod.
# Starea curenta din DB (inainte de update) — necesara pt logica de confirmare prod
# si pt a loga DOAR schimbari reale (US-012).
row_before = conn.execute(
"SELECT rar_prod_enabled FROM accounts WHERE id=?", (acct,)
"SELECT rar_test_enabled, rar_prod_enabled, rar_env_default FROM accounts WHERE id=?",
(acct,),
).fetchone()
was_test_enabled = bool(row_before["rar_test_enabled"]) if row_before else False
was_prod_enabled = bool(row_before["rar_prod_enabled"]) if row_before else False
prev_env_default = row_before["rar_env_default"] if row_before else None
# Confirmare obligatorie la PRIMA activare Productie (constientizare L.142).
# Nu se cere daca Productie era deja activata (confirmare unica per-activare).
@@ -4636,6 +4680,7 @@ async def cont_rar_medii(request: Request) -> HTMLResponse:
)
# --- Procesare Testare ---
# Tipuri de audit US-012: 'rar_env_activat' / 'rar_env_dezactivat' / 'rar_env_default_schimbat'.
if test_enabled_form:
if test_email and test_parola:
# Ambele campuri completate -> valideaza prin login pe RAR Testare.
@@ -4647,6 +4692,14 @@ async def cont_rar_medii(request: Request) -> HTMLResponse:
(enc, acct),
)
creds_test_mesaj = "Credentiale Testare salvate si validate."
# Activare reala: creds noi salvate (schimbare efectiva indiferent de starea anterioara).
log_event(
"rar_env_activat",
account_id=acct,
mesaj="Credentiale Testare salvate si validate.",
context={"env": "test"},
conn=conn,
)
else:
# Login esuat: nu schimbam creds sau enabled; eroare per-env.
creds_test_eroare = mesaj
@@ -4656,9 +4709,27 @@ async def cont_rar_medii(request: Request) -> HTMLResponse:
else:
# Activat fara creds noi -> marcheaza enabled (creds existente, daca sunt, raman).
conn.execute("UPDATE accounts SET rar_test_enabled=1 WHERE id=?", (acct,))
# Loga activare doar daca era dezactivat (0->1 e schimbare reala).
if not was_test_enabled:
log_event(
"rar_env_activat",
account_id=acct,
mesaj="Mediu Testare activat (creds existente).",
context={"env": "test"},
conn=conn,
)
else:
# Dezactivat -> disabled=0; creds raman pentru posibila re-activare ulterioara.
conn.execute("UPDATE accounts SET rar_test_enabled=0 WHERE id=?", (acct,))
# Loga dezactivare doar daca era activat (1->0 e schimbare reala).
if was_test_enabled:
log_event(
"rar_env_dezactivat",
account_id=acct,
mesaj="Mediu Testare dezactivat.",
context={"env": "test"},
conn=conn,
)
# --- Procesare Productie ---
if prod_enabled_form:
@@ -4671,14 +4742,40 @@ async def cont_rar_medii(request: Request) -> HTMLResponse:
(enc, acct),
)
creds_prod_mesaj = "Credentiale Productie salvate si validate."
# Activare reala: creds noi salvate.
log_event(
"rar_env_activat",
account_id=acct,
mesaj="Credentiale Productie salvate si validate.",
context={"env": "prod"},
conn=conn,
)
else:
creds_prod_eroare = mesaj
elif prod_email or prod_parola:
creds_prod_eroare = "Email si parola Productie trebuie completate impreuna."
else:
conn.execute("UPDATE accounts SET rar_prod_enabled=1 WHERE id=?", (acct,))
# Loga activare doar daca era dezactivat (0->1).
if not was_prod_enabled:
log_event(
"rar_env_activat",
account_id=acct,
mesaj="Mediu Productie activat (creds existente).",
context={"env": "prod"},
conn=conn,
)
else:
conn.execute("UPDATE accounts SET rar_prod_enabled=0 WHERE id=?", (acct,))
# Loga dezactivare doar daca era activat (1->0).
if was_prod_enabled:
log_event(
"rar_env_dezactivat",
account_id=acct,
mesaj="Mediu Productie dezactivat.",
context={"env": "prod"},
conn=conn,
)
# --- Mediu implicit (validat post-update contra mediilor disponibile) ---
if rar_env_default_form and rar_env_default_form in ("test", "prod"):
@@ -4695,6 +4792,15 @@ async def cont_rar_medii(request: Request) -> HTMLResponse:
(rar_env_default_form, acct),
)
creds_default_mesaj = "Mediu implicit actualizat."
# Loga schimbarea default doar daca valoarea s-a schimbat efectiv (US-012).
if rar_env_default_form != prev_env_default:
log_event(
"rar_env_default_schimbat",
account_id=acct,
mesaj=f"Mediu implicit schimbat in '{rar_env_default_form}'.",
context={"env": rar_env_default_form},
conn=conn,
)
else:
creds_default_eroare = (
"Mediul ales nu e disponibil — activeaza-l si adauga credentiale valide intai."
@@ -4744,6 +4850,14 @@ async def fragment_status_toggle_env(request: Request) -> HTMLResponse:
"UPDATE accounts SET rar_env_default=? WHERE id=?",
(env_nou, acct),
)
# US-012: audit comutare mediu implicit din statusbar.
log_event(
"rar_env_default_schimbat",
account_id=acct,
mesaj=f"Mediu implicit comutat in '{env_nou}' via statusbar.",
context={"env": env_nou},
conn=conn,
)
conn.commit()
ctx = _build_status_ctx(request, conn, account_id, tab_activ="acasa")