Auth-herding: roller, kontoadmin, token-revokering + søkbar planliste + neon

Auth (app-modus):
- Roller admin/standard. Admin oppretter/sletter kontoer, resetter passord,
  endrer roller (konto-modal). Eksisterende brukere → admin ved migrering;
  bootstrap-bruker via proxy-bypass → admin. Siste admin vernet.
- Tilbakekalling via per-bruker epoke i tokenet: passordbytte, admin-reset,
  «Logg ut alle enheter» og sletting dreper alle aktive sesjoner. Token-format
  endret (3- → 4-delt) — alle logges ut én gang ved oppgradering.

Dagsplan: søkbar/velgbar planliste («📋 Planer») avledet fra planIndex —
finn plan på navn/dato/person uten å gjette dato.

GUI: login-neon trukket inn i hovedappen (header/knapper/KPI-kanter), og
login-siden fikk mer tech (HUD-hjørner, glitch-tittel, scanlines).

40 integrasjonstester (6 nye), alle grønne. README + CLAUDE.md oppdatert.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Jon Vanvik 2026-06-15 14:56:39 +02:00
parent f6268440d9
commit 3f69cd4248
9 changed files with 518 additions and 36 deletions

View file

@ -58,6 +58,20 @@ Egen neon-login (`/login`) med passord. Sesjon er en signert, langlevd cookie
sømløst med WebSocket. Passord hashes med scrypt (Node-kjerne, ingen
avhengigheter), lagret i `data/auth.json`.
**Roller:** `admin` og `standard`. Admin kan opprette/slette kontoer, tilbakestille
passord og endre roller (brukermenyen oppe til høyre → admin-seksjon). Standard
kan endre eget passord og logge ut alle enheter. Ved oppgradering blir alle
eksisterende brukere automatisk admin, og den første som setter passord via
proxy-bypass blir admin (bootstrap). Den siste administratoren kan ikke slettes
eller degraderes.
**Tilbakekalling (herding):** hver bruker har en «epoke» bakt inn i tokenet.
Passordbytte, admin-reset og **«Logg ut alle enheter»** bumper epoken og dreper
alle eksisterende sesjoner umiddelbart (sletting av konto gjør det samme).
Sesjons-cookien er `HttpOnly` + `SameSite=Lax` + `Secure` (over HTTPS) og signert
med HMAC, så den kan ikke forfalskes. (Etter denne oppgraderingen logges alle ut
én gang, siden token-formatet endret seg.)
**Trusted bypass / migrering fra Basic Auth:** Når `TRUST_PROXY_HEADER=1`
(default) regnes en proxy-identitet (X-Remote-User eller Basic Auth) som
innlogget, *selv uten app-passord*. Det gir en trygg overgang:
@ -174,7 +188,10 @@ WantedBy=multi-user.target
(dra for å sortere, kapasitet i timer, datovelger). Kan navngis, flyttes til
en annen dato i ett klikk, og er som hovedregel synlig for alle (med en
«Synlig for alle»-toggle for å gjøre den privat). Andres delte planer kan ses
skrivebeskyttet via «Plan for»-velgeren.
skrivebeskyttet via «Plan for»-velgeren. **Søkbar planliste** («📋 Planer») for
å finne en plan på navn/dato/person uten å gjette datoen.
- **Brukerkontoer med roller** (i app-auth-modus) — admin kan opprette kontoer,
resette passord og styre roller; «Logg ut alle enheter» tilbakekaller økter.
- **Plan-badge på oppgaver** — hvert kort/rad viser om oppgaven er planlagt,
hvilken dag og av hvem.
- **Egendefinerte kategorier** — legg til nye kategorier fra kategori-nedtrekket
@ -205,8 +222,14 @@ optimistisk låsing — send med ved update, få 409 hvis noen andre har lagret.
| GET | `/api/state` | Bruker, auth-status, oppgaver, aktivitet, kjente brukere, online, kategorier, dagens plan, planIndex |
| GET | `/api/auth/status` | Auth-modus, innlogget?, bruker, via, har passord |
| POST | `/api/auth/login` | App-innlogging `{ user, password }` → sesjons-cookie |
| POST | `/api/auth/logout` | Tøm sesjons-cookie |
| POST | `/api/auth/logout` | Tøm sesjons-cookie (denne enheten) |
| POST | `/api/auth/logout-all` | Tilbakekall alle egne økter (bump epoke), behold denne |
| POST | `/api/auth/password` | Sett/endre eget passord `{ password, current? }` |
| GET | `/api/auth/users` | (admin) Liste over kontoer |
| POST | `/api/auth/users` | (admin) Opprett konto `{ user, password, role }` |
| POST | `/api/auth/users/:user/password` | (admin) Tilbakestill passord (logger ut brukeren) |
| PUT | `/api/auth/users/:user/role` | (admin) Sett rolle `{ role }` |
| DELETE | `/api/auth/users/:user` | (admin) Slett konto |
| POST | `/api/tasks` | Opprett oppgave (`title` påkrevd) |
| PUT | `/api/tasks/:id` | Oppdater (delvis OK; send `v` for konfliktsjekk; valgfri `comment` festes som status-kommentar) |
| DELETE | `/api/tasks/:id` | Slett |