Skip to content

Add optional multi-account support#18

Open
TreasuryMatt wants to merge 1 commit into
thillygooth:mainfrom
TreasuryMatt:account-system
Open

Add optional multi-account support#18
TreasuryMatt wants to merge 1 commit into
thillygooth:mainfrom
TreasuryMatt:account-system

Conversation

@TreasuryMatt

Copy link
Copy Markdown
Contributor

What

Adds an optional account layer so multiple households can share one Questboard deployment, each with its own settings and game state. Single-player/single-family installs keep working — the first run just auto-migrates existing data into one account.

Why

Right now there's effectively one global "user": the backend reads/writes two global JSON files with no notion of who's asking. This makes it possible for several families to use the same hosted instance without seeing each other's heroes, gold, or config.

How

Backend (backend/main.py) — still single-file, no new dependency (stdlib sqlite3):

  • Replaces state.json / config.json with a SQLite DB: accounts (name, optional PBKDF2-hashed PIN, per-account config + state JSON) and sessions (random bearer tokens).
  • New endpoints: GET/POST /accounts, POST /accounts/{id}/login, GET/POST /account (read/rename current), DELETE /account, POST /logout.
  • /config and /state are now scoped to the caller's session token.
  • Migration: on first start, an existing state.json/config.json folds into a single account (old files left as backup), so current deployments lose nothing.

Frontend:

  • src/api.js — token storage + apiFetch/apiPost; a 401 clears the token and bounces back to the picker.
  • src/components/AccountGate.jsx — landing screen to pick a household, create one, or enter a PIN. A brand-new account flows straight into the existing setup wizard.
  • src/App.jsx — gates on auth, routes all fetches through apiFetch, and adds Rename / Switch / Delete account controls (delete asks you to type the account name to confirm).

Notes

  • Security is intentionally light: PINs are hashed and tokens are random + server-side, but account ids are listable — aimed at a trusted family deployment. Email-based auth could layer on later without changing the storage model.
  • Verified: backend endpoints (create / isolation / PIN / logout + delete invalidation / migration) via FastAPI TestClient; npm run build passes.

🤖 Generated with Claude Code

Lets multiple households share one Questboard deployment, each with its
own settings and game state, while staying single-file and dependency-free.

Backend (backend/main.py)
- Replace the two global JSON files with SQLite (stdlib sqlite3, no new
  dependency): `accounts` (name, optional PBKDF2-hashed PIN, per-account
  config + state JSON) and `sessions` (random bearer tokens).
- New endpoints: GET/POST /accounts, POST /accounts/{id}/login,
  GET/POST /account (read/rename current), DELETE /account, POST /logout.
- /config and /state are now scoped to the caller's session token.
- On first run, an existing state.json/config.json auto-migrates into a
  single account, so current deployments keep their data (old files kept).

Frontend
- api.js: token storage + apiFetch/apiPost; a 401 clears the token and
  returns to the account picker.
- AccountGate.jsx: landing screen to pick a household, create one, or enter
  a PIN. A new account flows straight into the existing setup wizard.
- App.jsx: gate on auth, route fetches through apiFetch, and add
  rename / switch / delete-account controls (delete asks you to type the
  account name to confirm).

Security posture is intentionally light (PINs hashed, tokens random and
server-side, but account ids are listable) — suited to a trusted family
deployment. Email-based auth could layer on later without changing storage.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant