Add persistence layer: TOTP auth, game history, restore
- db/ package: async SQLAlchemy engine + Player/Game/Guess models - api/auth.py: passwordless TOTP login (pyotp), session token via socket auth - api/history.py: record guesses/points, DB-backed standings, restore unfinished games on startup, host-only end_game - api/__init__.py: auth-gated handlers, accounts map, rejoin via account - frontend: Auth (QR + code) and History pages, resume/end-game in lobby/table - docker-compose: real PostgreSQL service wired via DATABASE_URL - tests_history.py for the persistence/auth layer; refresh CLAUDE.md Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -10,6 +10,7 @@ export interface PlayerInfo {
|
||||
order: number;
|
||||
name: string;
|
||||
connected: boolean;
|
||||
player_id?: number;
|
||||
}
|
||||
|
||||
export interface MyPlayer {
|
||||
@@ -51,3 +52,44 @@ export interface GameInfo {
|
||||
}
|
||||
|
||||
export type Hand = Record<string, Card>;
|
||||
|
||||
// --- authentication (TOTP) ---
|
||||
|
||||
export interface Account {
|
||||
player_id: number;
|
||||
username: string;
|
||||
}
|
||||
|
||||
export interface Registration {
|
||||
username: string;
|
||||
secret: string;
|
||||
otpauth_uri: string;
|
||||
}
|
||||
|
||||
// --- history ---
|
||||
|
||||
export interface HistoryGame {
|
||||
gid: string;
|
||||
created_at: string | null;
|
||||
ended_at: string | null;
|
||||
players: string[];
|
||||
my_points: number;
|
||||
}
|
||||
|
||||
export interface GameDetailRound {
|
||||
series_number: number;
|
||||
round_number: number;
|
||||
player_id: number;
|
||||
username: string | null;
|
||||
guess: number;
|
||||
points: number;
|
||||
won: boolean;
|
||||
}
|
||||
|
||||
export interface GameDetail {
|
||||
gid: string;
|
||||
created_at: string | null;
|
||||
ended_at: string | null;
|
||||
players: { player_id: number; username: string }[];
|
||||
rounds: GameDetailRound[];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user