feat(5.20): US-007 validare login RAR pe env-ul setului de credentiale

Login de validare loveste base_url_pentru_env(env) (NU ancora globala); endpoint
POST /cont/test-rar-creds + card in _integrare.html; mesaj distinct TESTARE vs
PRODUCTIE la 401 incrucisat (confirmat live).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Claude Agent
2026-06-29 20:46:50 +00:00
parent 19d8aaa7aa
commit 3579a15363
3 changed files with 333 additions and 1 deletions

View File

@@ -90,6 +90,7 @@ from ..mapping import (
)
from ..shared_store import record_human_validation
from ..rar_env import MediuIndisponibil, medii_disponibile_cont, rar_env_efectiv_cont, rezolva_rar_env
from ..rar_client import RarAuthError, RarClient, RarError, base_url_pentru_env
# Campuri canonice cu eticheta umana pentru dropdown mapare coloane
_CANONICAL_FIELDS = [(k, v[0]) for k, v in _CANONICAL_SYNONYMS.items()]
@@ -4034,6 +4035,66 @@ async def web_confirma_import(
# care cere cheie API; sesiunea web e suficienta ca identitate). #
# =========================================================================== #
# ---------------------------------------------------------------------------
# US-007 (PRD 5.20): Validare credentiale RAR env-aware
#
# Premisa confirmata live (2026-06-29): creds de productie NU se valideaza pe RAR
# test si invers (401 incrucisat). Deci login-ul de proba TREBUIE sa loveasca
# endpoint-ul mediului caruia ii apartin credentialele.
#
# Puncte de validare existente:
# - /cont/test-rar-creds (testeaza integrarea RAR, fara efecte secundare)
# Puncte non-aplicabile (nu colecteaza/valideaza creds RAR):
# - signup (/signup): nu colecteaza credentiale RAR — creare cont platforma, nu RAR
# - preview import: nu valideaza credentiale RAR
# Puncte viitoare (US-008):
# - /cont/rar-creds la salvare creds per-mediu (va apela _valideaza_login_rar)
# ---------------------------------------------------------------------------
def _eticheta_mediu_rar(env: str) -> str:
"""Eticheta umana a mediului RAR pentru mesaje de eroare/succes.
'test' -> 'TESTARE', 'prod' -> 'PRODUCTIE'.
"""
return "PRODUCTIE" if env == "prod" else "TESTARE"
def _valideaza_login_rar(
settings,
email: str,
password: str,
env: str,
) -> tuple[bool, str | None]:
"""Valideaza credentialele RAR prin login pe mediul specificat (US-007, PRD 5.20).
Creeaza un RarClient cu base_url-ul mediului `env` (NU base_url-ul global),
deoarece RAR test si RAR prod sunt sisteme separate cu credentiale separate.
Parametri
---------
settings: configuratia aplicatiei (pentru base_url_test/prod si timeout)
email: email-ul contului RAR
password: parola contului RAR
env: mediul tinta: 'test' sau 'prod'
Returneaza
----------
(True, None) la succes (login reusit)
(False, mesaj) la esec; `mesaj` include eticheta mediului ('TESTARE'/'PRODUCTIE'),
ex. 'Credentiale RAR invalide pe TESTARE.'
"""
env_label = _eticheta_mediu_rar(env)
try:
with RarClient(settings, base_url=base_url_pentru_env(settings, env)) as rar:
rar.login(email, password)
return True, None
except RarAuthError:
return False, f"Credentiale RAR invalide pe {env_label}."
except RarError as exc:
return False, f"Eroare la conectare RAR ({env_label}): {exc}"
def _render_cont(
request: Request,
*,
@@ -4365,3 +4426,61 @@ def cont_rar_creds(
)
finally:
conn.close()
@router.post("/cont/test-rar-creds", response_class=HTMLResponse)
def cont_test_rar_creds(
request: Request,
rar_email: str = Form(""),
rar_parola: str = Form(""),
rar_env: str = Form(default=""),
csrf_token: str | None = Form(None),
) -> HTMLResponse:
"""Testeaza credentialele RAR prin login real pe mediul specificat (US-007, PRD 5.20).
Fara efecte secundare: nu salveaza nimic, nu creeaza submission. Pur validare.
Camp parola NICIODATA re-pus in raspuns.
Decizie env (documentata US-007):
- param `rar_env` explicit ('test'/'prod') -> folosit direct
- altfel -> rar_env_efectiv_cont (default-ul contului) sau ancora globala settings.rar_env
- signup nu colecteaza creds RAR, deci nu apeleaza aceasta functie
"""
account_id = require_login(request)
verify_csrf(request, csrf_token)
email = rar_email.strip()
parola = rar_parola.strip()
if not email or not parola:
return templates.TemplateResponse(
"_integrare_test_rezultat.html",
{"request": request, "succes": False,
"mesaj": "Email si parola sunt obligatorii."},
)
# Determina env-ul de validare
settings = get_settings()
env_cerut = (rar_env or "").strip().lower()
if env_cerut in ("test", "prod"):
env = env_cerut
else:
# Fallback: env-ul efectiv al contului (default) sau ancora globala
conn = get_connection()
try:
env = rar_env_efectiv_cont(conn, account_id) or settings.rar_env or "test"
finally:
conn.close()
ok, mesaj_eroare = _valideaza_login_rar(settings, email, parola, env)
if ok:
env_label = _eticheta_mediu_rar(env)
return templates.TemplateResponse(
"_integrare_test_rezultat.html",
{"request": request, "succes": True,
"mesaj": f"Credentiale RAR valide pe {env_label}."},
)
return templates.TemplateResponse(
"_integrare_test_rezultat.html",
{"request": request, "succes": False, "mesaj": mesaj_eroare},
)

View File

@@ -226,7 +226,7 @@
</div>
</div>
{# Formular test conexiune #}
{# Formular test conexiune cheie API #}
<div class="card" style="margin-bottom:16px;">
<h3 style="margin:0 0 12px; font-size:15px;">Testeaza conexiunea</h3>
<form id="form-test-cheie"
@@ -246,6 +246,42 @@
<div id="integrare-test-rezultat" style="margin-top:8px;"></div>
</div>
{# Formular test credentiale RAR (US-007, PRD 5.20) #}
{# Login de proba pe mediul ales — fara efecte secundare, nu salveaza nimic. #}
{# Banner-ul de rezultat include eticheta mediului ("pe TESTARE" / "pe PRODUCTIE"). #}
<div class="card" style="margin-bottom:16px;">
<h3 style="margin:0 0 6px; font-size:15px;">Testeaza credentiale RAR</h3>
<p class="muted" style="font-size:12px; margin:0 0 10px;">
Verifica daca credentialele RAR sunt corecte pe mediul ales. Nu se salveaza nimic.
</p>
<form id="form-test-rar-creds"
hx-post="/cont/test-rar-creds"
hx-target="#rar-test-rezultat"
hx-swap="innerHTML"
style="display:flex; gap:8px; flex-wrap:wrap; align-items:flex-end;">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<div>
<label for="test-rar-email" style="display:block; font-size:13px; color:var(--muted); margin-bottom:4px;">Email RAR</label>
<input type="email" id="test-rar-email" name="rar_email" placeholder="email@service.ro"
style="width:220px;" autocomplete="off">
</div>
<div>
<label for="test-rar-parola" style="display:block; font-size:13px; color:var(--muted); margin-bottom:4px;">Parola RAR</label>
<input type="password" id="test-rar-parola" name="rar_parola"
style="width:160px;" autocomplete="new-password">
</div>
<div>
<label for="test-rar-env" style="display:block; font-size:13px; color:var(--muted); margin-bottom:4px;">Mediu</label>
<select id="test-rar-env" name="rar_env" style="height:36px; padding:0 8px;">
<option value="prod">Productie</option>
<option value="test">Testare</option>
</select>
</div>
<button type="submit">Testeaza RAR</button>
</form>
<div id="rar-test-rezultat" style="margin-top:8px;"></div>
</div>
</div>
<script>