No self-signup: admins create every account in Config -> Benutzer with a typed start password; a forced password change gates first use. Session- cookie auth protects all /api/* routes; /api/users additionally requires the admin role. See docs/authentication.md. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
61 lines
2.9 KiB
Markdown
61 lines
2.9 KiB
Markdown
# Anmeldung und Benutzerverwaltung
|
||
|
||
Die Leistungsbilanz verlangt eine Anmeldung. Es gibt kein Self-Signup: jeder
|
||
Zugang wird von einem Administrator über **Config → Benutzer** angelegt.
|
||
|
||
## Rollen
|
||
|
||
Es gibt genau zwei Rollen (`src/shared/constants/user-roles.ts`):
|
||
|
||
- **admin** – wie `user`, zusätzlich Zugriff auf den Config-Bereich
|
||
(Benutzerverwaltung, eigenes Konto)
|
||
- **user** – volle Nutzung der Leistungsbilanz (Projekte, Stromkreislisten,
|
||
Grobbilanz, …), kein Zugriff auf Config
|
||
|
||
Es gibt (bewusst, siehe unten) keine konfigurierbare Rechte-Matrix und keine
|
||
Verknüpfung mit einer Mitarbeiter-/Personen-Stammdatentabelle.
|
||
|
||
## Ablauf beim Anlegen eines Zugangs
|
||
|
||
1. Ein Administrator öffnet Config → Benutzer und legt einen neuen Zugang mit
|
||
Anmeldename, Name, Rolle und einem **Startpasswort** an, das er selbst
|
||
eintippt.
|
||
2. Der Zugang startet mit `mustChangePassword = true`.
|
||
3. Beim ersten Anmelden zeigt die Oberfläche statt der App ein Formular, das
|
||
ein eigenes Passwort verlangt, bevor es weitergeht.
|
||
4. "Passwort zurücksetzen" (ebenfalls in Config → Benutzer) setzt ein neues
|
||
Startpasswort und `mustChangePassword` wieder auf `true` – z. B. wenn
|
||
jemand sein Passwort vergessen hat.
|
||
|
||
## Technischer Aufbau
|
||
|
||
- **Datenmodell:** Tabelle `users` (`src/db/schema/users.ts`) –
|
||
`username`, `passwordHash` (scrypt, `src/server/auth/password.ts`), `name`,
|
||
`role`, `active`, `mustChangePassword`.
|
||
- **Sessions:** In-Memory-Store (`src/server/auth/sessions.ts`), Cookie
|
||
`lb_session`, sliding expiry (`AUTH_SESSION_HOURS`, Standard 12h). Ein
|
||
Neustart der API beendet alle Sessions – für einen Single-Container-Dienst
|
||
ein akzeptabler Kompromiss gegenüber einer persistierten Session-Tabelle.
|
||
- **Middleware:** `src/server/auth/auth.middleware.ts` schützt `/api/*`
|
||
(außer `/api/auth/login`, `/api/auth/status`, `/api/auth/logout`) und
|
||
erzwingt den Passwortwechsel, solange `mustChangePassword` gesetzt ist.
|
||
`/api/users/*` verlangt zusätzlich die Rolle `admin`.
|
||
- **Frontend:** `AuthProvider` lädt `/api/auth/me`; `LoginGate`
|
||
(`src/app/layout.tsx`) zeigt Login- bzw. Passwortformular, solange nicht
|
||
angemeldet bzw. `mustChangePassword` gesetzt ist, sonst die App.
|
||
|
||
## Bootstrap-Admin
|
||
|
||
`AUTH_BOOTSTRAP_USERNAME` / `AUTH_BOOTSTRAP_PASSWORT` (Env-Variablen, siehe
|
||
`compose.yaml`) legen beim ersten Start einen Admin an – **nur falls die
|
||
`users`-Tabelle noch komplett leer ist**. Danach werden diese Variablen
|
||
ignoriert; jeder weitere Zugang entsteht über Config → Benutzer. Die Werte
|
||
gehören in eine lokale, nicht versionierte `.env` auf dem Deploy-Host, nicht
|
||
in `compose.yaml` selbst.
|
||
|
||
## Bewusst nicht umgesetzt (Stand jetzt)
|
||
|
||
- Konfigurierbare Rechte-Matrix statt fixer `admin`/`user`-Rollen
|
||
- Konten-Sperre nach Fehlversuchen
|
||
- E-Mail-/Einmal-Link-Passwortvergabe, OIDC/Entra-Anmeldung
|
||
- Verknüpfung von Zugängen mit einer Mitarbeiter-Stammdatentabelle
|