Harden session handling, add password reset/change, and firm up round polling

Session hardening: / and /admin now respond with Cache-Control: no-store, and
both pages re-derive their auth state on pageshow (event.persisted) as a
safety net against bfcache showing a stale logged-in/out view across
back/forward navigation. The user page also syncs logout across tabs via the
storage event, since localStorage is shared but in-memory JS state isn't.

Password recovery: admin gets a "Reset" button per user (POST
/admin/users/{id}/reset-password) that generates and sets a new password,
shown once — passwords are Argon2-hashed and can never be recovered, only
replaced. Users get self-service password change (POST
/users/me/change-password, requires the current password) under a new
Profilo tab, alongside read-only account info (username, address, balance,
join date).

Round display robustness: the user dashboard now refreshes immediately on
tab visibility change (background tabs get their timers throttled hard),
shows an explicit "connessione persa" state after repeated failed polls
instead of silently freezing on stale data, and polls faster both right when
the countdown hits zero and through the gap where the round is past its
deadline but still waiting for in-flight bets to confirm before the server
actually closes it.
This commit is contained in:
2026-07-22 12:00:09 +02:00
parent 162a63d04a
commit f27fe6243c
9 changed files with 471 additions and 25 deletions
+12 -2
View File
@@ -20,7 +20,7 @@ sola schermata di login.
## Sezioni della dashboard
- **Parametri** — configurazione operativa (vedi tabella sotto)
- **Utenti** — elenco utenti, saldo, accesso alla chiave privata
- **Utenti** — elenco utenti, saldo, accesso alla chiave privata, reset password
- **Round** — storico round: stato, vincitore, importi, txid di payout
- **Transazioni pendenti** — bet/payout/prelievi non ancora confermati, candidati al fee-bump RBF
- **Audit log** — eventi registrati dal sistema (config cambiata, bet, payout, accessi a chiavi private, ecc.)
@@ -126,7 +126,7 @@ curl -X PUT https://<host>/admin/config \
-d '{"fee_address": "plm1q...", "bet_amount_sats": 1000000000, "round_duration_seconds": 600}'
```
## Utenti e chiave privata
## Utenti, chiave privata e reset password
La card "Utenti" elenca id, username, indirizzo e saldo di ogni utente
registrato. Il bottone "Mostra" su ogni riga rivela la chiave privata (WIF)
@@ -137,6 +137,16 @@ falla: il server è già custodial, la chiave master da cui derivano tutte le
chiavi utente vive sul server — questo pannello espone solo qualcosa che
l'operatore può già fare via script.
Il bottone "Reset" nella colonna "Password" genera una **nuova password
casuale** per l'utente e sovrascrive quella esistente — mostrata una sola
volta nel pannello, così puoi comunicarla a chi ti ha chiesto aiuto perché
l'ha dimenticata. Non è un "recupero": le password sono salvate solo come
hash Argon2 (`app/auth/security.py`), quindi quella vecchia **non è mai
recuperabile** né per l'admin né per il codice stesso — l'unica opzione è
sempre sostituirla con una nuova. Anche questa azione è audit-loggata
(`admin_password_reset`) e non esiste alcun flusso self-service equivalente
per l'utente: solo un admin col token può farlo.
## Limiti noti
- Il token è unico e condiviso: non c'è identità per singolo admin né audit