From 6772e3166a59fd868e3ead92cf8baff84e48ca24 Mon Sep 17 00:00:00 2001 From: Adriano Dal Pastro Date: Wed, 20 May 2026 07:42:49 +0000 Subject: [PATCH] fix(setup,ui): risolve errori setup + logo SVG theme-aware - setup: corregge path templates (sibling di api/, non figlio) e firma TemplateResponse - setup: invalida sessione client dopo operazioni che ruotano l'API key (init DB, creazione admin, cambio password, attivazione utente) - api_client: include il nome del campo nei messaggi di errore 422 (FastAPI validation) - ui: nuovo componente _app_logo.html (SVG inline theme-aware) usato su login e navbar --- src/backend/api/routers/setup.py | 4 +-- src/backend/templates/setup/setup.html | 19 ++++++++++ src/frontend/flask_app/services/api_client.py | 18 +++++++--- .../flask_app/templates/auth/login.html | 11 +++--- .../templates/components/_app_logo.html | 35 +++++++++++++++++++ .../templates/components/navbar.html | 12 +++---- 6 files changed, 80 insertions(+), 19 deletions(-) create mode 100644 src/frontend/flask_app/templates/components/_app_logo.html diff --git a/src/backend/api/routers/setup.py b/src/backend/api/routers/setup.py index e4d71ff..c0f1246 100644 --- a/src/backend/api/routers/setup.py +++ b/src/backend/api/routers/setup.py @@ -26,7 +26,7 @@ from src.backend.services.measurement_service import calculate_pass_fail router = APIRouter(prefix="/api/setup", tags=["setup"]) -_templates_dir = Path(__file__).resolve().parent.parent / "templates" +_templates_dir = Path(__file__).resolve().parent.parent.parent / "templates" templates = Jinja2Templates(directory=str(_templates_dir)) @@ -215,7 +215,7 @@ async def _seed_default_station(session: AsyncSession, admin_user: User) -> None async def setup_page(request: Request): """Serve the setup page HTML.""" _check_setup_enabled() - return templates.TemplateResponse("setup/setup.html", {"request": request}) + return templates.TemplateResponse(request, "setup/setup.html") @router.get("/status") diff --git a/src/backend/templates/setup/setup.html b/src/backend/templates/setup/setup.html index 081b256..b7ae7e6 100644 --- a/src/backend/templates/setup/setup.html +++ b/src/backend/templates/setup/setup.html @@ -559,6 +559,19 @@ return data; } + /* Setup operations rotate api_keys (DB init, admin creation, password + * change, user (de)activation). Any Flask session held in this browser + * still carries the old key, so we clear it to force a fresh /auth/login. */ + async function invalidateClientSession() { + try { + await fetch('/auth/logout', { + method: 'POST', + credentials: 'same-origin', + redirect: 'manual', + }); + } catch (_) { /* best-effort */ } + } + /* ------------------------------------------------------------------ */ /* Check DB status */ /* ------------------------------------------------------------------ */ @@ -635,6 +648,7 @@ try { const data = await apiPost('/init-db', { password: setupPassword }); showToast(data.message, 'success'); + await invalidateClientSession(); await checkStatus(); } catch (e) { showToast(e.message, 'error'); @@ -667,6 +681,7 @@ admin_display_name: display, }); showToast(data.message, 'success'); + await invalidateClientSession(); // Clear form document.getElementById('admin-username').value = ''; document.getElementById('admin-password').value = ''; @@ -690,6 +705,7 @@ if (data.measurements_created) msg += ', measurements: ' + data.measurements_created; msg += ')'; showToast(msg, 'success'); + await invalidateClientSession(); await loadUsers(); } catch (e) { showToast(e.message, 'error'); @@ -876,6 +892,7 @@ if (pwd) body.user_password = pwd; var data = await apiPost('/manage-user', body); showToast(data.message, 'success'); + await invalidateClientSession(); closeModal('modal-user'); await loadUsers(); } catch (e) { @@ -908,6 +925,7 @@ new_password: newPwd, }); showToast(data.message, 'success'); + await invalidateClientSession(); closeModal('modal-password'); } catch (e) { showToast(e.message, 'error'); @@ -924,6 +942,7 @@ user_id: userId, }); showToast(data.message, 'success'); + await invalidateClientSession(); await loadUsers(); } catch (e) { showToast(e.message, 'error'); diff --git a/src/frontend/flask_app/services/api_client.py b/src/frontend/flask_app/services/api_client.py index 6f89220..9a401b3 100644 --- a/src/frontend/flask_app/services/api_client.py +++ b/src/frontend/flask_app/services/api_client.py @@ -56,11 +56,21 @@ class APIClient: try: error_body = response.json() detail = error_body.get("detail", str(error_body)) - # FastAPI 422 returns detail as a list of validation errors + # FastAPI 422 returns detail as a list of validation errors: + # [{"type": ..., "loc": ["body", "password"], "msg": "...", ...}, ...] if isinstance(detail, list): - detail = "; ".join( - e.get("msg", str(e)) for e in detail if isinstance(e, dict) - ) or str(detail) + parts = [] + for e in detail: + if not isinstance(e, dict): + parts.append(str(e)) + continue + msg = e.get("msg", str(e)) + loc = e.get("loc") or [] + # Strip leading "body"/"query"/"path" segments; keep field path. + field_path = [str(p) for p in loc if p not in ("body", "query", "path")] + field = ".".join(field_path) if field_path else None + parts.append(f"{field}: {msg}" if field else msg) + detail = "; ".join(parts) or str(detail) except Exception: detail = response.text or f"HTTP {response.status_code}" diff --git a/src/frontend/flask_app/templates/auth/login.html b/src/frontend/flask_app/templates/auth/login.html index d6e4487..882be3f 100644 --- a/src/frontend/flask_app/templates/auth/login.html +++ b/src/frontend/flask_app/templates/auth/login.html @@ -8,13 +8,10 @@
- TieMeasureFlow Logo -

- TieMeasureFlow -

+
+ {% set logo_class = 'h-16 w-auto' %} + {% include 'components/_app_logo.html' %} +

{{ _('Accedi al sistema') }}

diff --git a/src/frontend/flask_app/templates/components/_app_logo.html b/src/frontend/flask_app/templates/components/_app_logo.html new file mode 100644 index 0000000..8f60b26 --- /dev/null +++ b/src/frontend/flask_app/templates/components/_app_logo.html @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + Tie + Measure + Flow + + diff --git a/src/frontend/flask_app/templates/components/navbar.html b/src/frontend/flask_app/templates/components/navbar.html index 1712810..0cdec13 100644 --- a/src/frontend/flask_app/templates/components/navbar.html +++ b/src/frontend/flask_app/templates/components/navbar.html @@ -6,14 +6,14 @@