Auth: nedokoncena registracia sa da dokoncit novym QR kodom

Ucet bez potvrdeneho kodu (auth_token is NULL a totp_last_step == 0)
uz neblokuje meno: opakovany register_account vyda novy secret (stary
QR prestane platit) a login vyhodi RegistrationIncomplete, na ktoru
server odpovie novym QR -- klient sa prepne na registracny tab.
Admin statistiky vykazuju nedokoncene registracie osobitne, Hraci
celkom pocita len potvrdene ucty. Novy event register v analytike.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
tim
2026-07-04 17:34:03 +02:00
co-authored by Claude Fable 5
parent 53274607b1
commit 5b9d6342ad
7 changed files with 124 additions and 20 deletions
+13 -1
View File
@@ -228,7 +228,18 @@ async def get_daily_stats(logged_in_only: bool = False) -> dict:
)
).scalar()
total_players = (await session.execute(select(func.count(Player.id)))).scalar()
# Nedokoncena registracia = kod nebol nikdy potvrdeny (SQL obdoba
# api/auth._is_unconfirmed). "Hraci celkom" pocita len potvrdene ucty,
# nedokoncene sa vykazuju osobitne.
unconfirmed = Player.auth_token.is_(None) & (Player.totp_last_step == 0)
total_players, unconfirmed_players = (
await session.execute(
select(
func.count(Player.id).filter(~unconfirmed),
func.count(Player.id).filter(unconfirmed),
)
)
).one()
peak_hours = (
await session.execute(
@@ -320,6 +331,7 @@ async def get_daily_stats(logged_in_only: bool = False) -> dict:
"completion_rate": finished / total if total else None,
"avg_game_duration_minutes": (avg_duration / 60) if avg_duration else None,
"total_players": total_players,
"unconfirmed_players": unconfirmed_players,
"peak_hours": {int(r.h): r.n for r in peak_hours},
"rounds_per_day": {str(r.day): r.n for r in rounds_rows},
"pageviews_per_day": {str(r.day): r.n for r in pageview_rows},