Add secure username/password login portal

Gate the suite behind a self-contained login (no external IdP):

- User model with bcrypt-hashed passwords; admin/user roles
- /api/auth endpoints: login, logout, me, change-password, and
  admin-only user management (list/create/delete/reset/enable)
- Stateless JWT session in an HttpOnly, SameSite=Lax, auto-Secure
  cookie; middleware refuses every /api data route without a session
- login.html + auth-guard.js: login page and per-page guard with a
  top-right "name / Admin / Sign out" pill
- Admin Console now gated on admin role (passphrase gate removed) with
  a User administration card
- manage_users.py CLI to bootstrap the first admin
- Rebuilt help.js into a searchable, multi-topic help center
- Local-dev convenience: app serves html/ so the site + API share one
  origin under uvicorn (inactive in the prod container)
- Docs/env: AUTH_SECRET_KEY, requirements (bcrypt, PyJWT), README

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-25 16:55:54 -05:00
parent a02f7ec511
commit 20afb0e565
18 changed files with 1470 additions and 99 deletions

View File

@@ -27,6 +27,9 @@ services:
POSTGRES_HOST: db
# Optional full-URL override (must be URL-encoded if used).
DATABASE_URL: ${DATABASE_URL:-}
# Signs login session cookies. MUST be set (see server/.env.example).
AUTH_SECRET_KEY: ${AUTH_SECRET_KEY}
AUTH_SESSION_HOURS: ${AUTH_SESSION_HOURS:-12}
restart: unless-stopped
depends_on:
db: