feat(PROJ-17): Admin Dashboard Systemauslastung immer anzeigen
- Systemauslastungs-Sektion wird immer gerendert (nicht nur bei Erfolg) - Fehlermeldung wenn /api/admin/system/stats nicht erreichbar ist - Feature-Status auf In Review gesetzt Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,185 @@
|
||||
# PROJ-1: Nutzer-Authentifizierung & Rollen
|
||||
|
||||
## Status: In Progress
|
||||
**Created:** 2026-03-12
|
||||
**Last Updated:** 2026-03-12
|
||||
|
||||
## Dependencies
|
||||
- PROJ-16 (LDAP / Active Directory Anbindung) — optionale Erweiterung des Login-Flows
|
||||
|
||||
## Rollen-Übersicht
|
||||
|
||||
| Rolle | Zugriff |
|
||||
|-------|---------|
|
||||
| `user` | Suche und Lesen eigener archivierter E-Mails |
|
||||
| `auditor` | Alle E-Mails lesen und suchen (postfachübergreifend) + Audit-Log einsehen und exportieren – keine Konfiguration |
|
||||
| `admin` | Konfiguration, Nutzerverwaltung, Import-Quellen, Systemeinstellungen – kein Zugriff auf E-Mails, kein Audit-Log |
|
||||
|
||||
## User Stories
|
||||
- Als Admin möchte ich mich mit Benutzername/Passwort einloggen, damit nur autorisierte Personen Zugriff haben.
|
||||
- Als Admin möchte ich neue Nutzer anlegen und ihnen eine Rolle zuweisen (`user`, `auditor`, `admin`).
|
||||
- Als Auditor möchte ich den Audit-Log einsehen und als CSV exportieren, ohne Zugriff auf E-Mails oder Konfiguration zu haben.
|
||||
- Als Nutzer möchte ich mich abmelden können, damit meine Session sicher beendet wird.
|
||||
- Als Admin möchte ich Passwörter zurücksetzen können, damit gesperrte Nutzer wieder Zugang erhalten.
|
||||
- Als System möchte ich Sessions nach Inaktivität automatisch beenden, damit unbefugter Zugriff verhindert wird.
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Login-Seite mit E-Mail/Benutzername und Passwort-Formular
|
||||
- [ ] Fehlermeldung bei falschen Zugangsdaten (kein Hinweis ob E-Mail oder Passwort falsch)
|
||||
- [ ] Session-Token wird sicher gespeichert (httpOnly Cookie oder JWT)
|
||||
- [ ] Sessions laufen nach konfigurierbarer Inaktivität ab (Standard: 8 Stunden)
|
||||
- [ ] Drei Rollen: `user`, `auditor`, `admin` – strikt getrennte Zugriffsrechte
|
||||
- [ ] `auditor` hat Zugriff auf alle E-Mails (postfachübergreifend, auch fremde Postfächer) + Audit-Log – keine Konfiguration
|
||||
- [ ] `admin` hat ausschließlich Zugriff auf Konfiguration und Nutzerverwaltung – kein Zugriff auf E-Mails und kein Zugriff auf Audit-Log
|
||||
- [ ] Admin kann Nutzer anlegen, deaktivieren und löschen
|
||||
- [ ] Admin kann Passwörter zurücksetzen (temporäres Passwort)
|
||||
- [ ] Alle API-Endpunkte prüfen Authentifizierung und Rolle
|
||||
- [ ] Logout löscht die Session serverseitig
|
||||
|
||||
## Edge Cases
|
||||
- Login mit deaktiviertem Account → klare Fehlermeldung, kein Zugang
|
||||
- Mehrfaches Fehllogin → Rate-Limiting oder Account-Sperre nach X Versuchen
|
||||
- Session-Token abgelaufen → automatische Weiterleitung zur Login-Seite
|
||||
- Erster Start: Zwei feste Default-User werden beim ersten Start automatisch angelegt:
|
||||
- `admin@archivmail` / `archivmailrockz` (Rolle: `admin`)
|
||||
- `auditor@archivmail` / `archivmailrockz` (Rolle: `auditor`)
|
||||
- Passwörter sollten nach dem ersten Login geändert werden (Hinweis in der UI)
|
||||
- Admin löscht sich selbst → verhindern wenn letzter Admin
|
||||
|
||||
## Technical Requirements
|
||||
- Passwörter mit bcrypt gehasht (min. Cost 12)
|
||||
- Alle Routen außer `/login` erfordern gültige Session
|
||||
- Admin-Routen (`/admin/*`) nur für `admin`-Rolle
|
||||
- Audit-Routen (`/audit/*`) und E-Mail-Suche/Ansicht nur für `auditor`- und `user`-Rolle
|
||||
- `admin` erhält bei E-Mail-Endpunkten HTTP 403 – keine Ausnahmen
|
||||
- Keine Rolle vereint `admin` + `auditor` – strikte Funktionstrennung
|
||||
- Audit-Log-Eintrag bei Login, Logout, fehlgeschlagenem Login
|
||||
|
||||
---
|
||||
<!-- Sections below are added by subsequent skills -->
|
||||
|
||||
## Tech Design (Solution Architect)
|
||||
|
||||
### Systemübersicht: Two-Tier Architektur
|
||||
|
||||
```
|
||||
Browser (Next.js App) Go REST API Backend
|
||||
│ │
|
||||
│ POST /api/auth/login │
|
||||
│ {email, password} │
|
||||
│ ─────────────────────────────────► │
|
||||
│ 1. Lokaler Account? → bcrypt verify
|
||||
│ 2. Nicht gefunden + LDAP aktiv?
|
||||
│ → LDAP-Bind (Service Account)
|
||||
│ → User-DN suchen
|
||||
│ → User-Bind mit Passwort
|
||||
│ → AD-Gruppen → Rolle bestimmen
|
||||
│ → UpsertLDAPUser in PostgreSQL
|
||||
│ 3. Session-Token erstellen
|
||||
│ Session in PostgreSQL speichern
|
||||
│ ◄─────────────────────────────────
|
||||
│ Set-Cookie: session=TOKEN │
|
||||
│ (httpOnly, Secure, SameSite) │
|
||||
│ │
|
||||
│ GET /api/search?q=... │
|
||||
│ Cookie: session=TOKEN │
|
||||
│ ─────────────────────────────────► │
|
||||
│ Session-Middleware: Token prüfen
|
||||
│ Role-Middleware: Route erlaubt?
|
||||
│ ◄─────────────────────────────────
|
||||
│ JSON-Antwort │
|
||||
```
|
||||
|
||||
> **LDAP ist vollständig optional.** Wenn `ldap.enabled: false` (Standard), verhält sich das System exakt wie ohne LDAP. Lokale Accounts funktionieren immer — auch wenn LDAP aktiviert ist (Fallback bei LDAP-Fehler).
|
||||
|
||||
### Komponentenstruktur
|
||||
|
||||
**Next.js Frontend:**
|
||||
```
|
||||
src/app/
|
||||
├── /login ← Login-Seite (öffentlich)
|
||||
├── /search ← Suche + E-Mail-Ansicht (user + auditor)
|
||||
├── /audit ← Audit-Log (nur auditor)
|
||||
└── /admin ← Admin-Bereich (nur admin)
|
||||
|
||||
src/components/
|
||||
├── LoginForm ← E-Mail + Passwort, Fehlermeldungen
|
||||
├── RoleGuard ← Schützt Routen clientseitig, redirect auf /login
|
||||
└── PasswordChangePrompt ← Hinweis bei Default-Passwort
|
||||
```
|
||||
|
||||
**Go Backend:**
|
||||
```
|
||||
HTTP-Server
|
||||
├── POST /api/auth/login ← Session ausstellen
|
||||
├── POST /api/auth/logout ← Session löschen
|
||||
├── Session Middleware ← prüft Token bei allen /api/* Routen
|
||||
├── Role Middleware
|
||||
│ ├── /api/admin/* → nur `admin`
|
||||
│ ├── /api/audit/* → nur `auditor`
|
||||
│ └── /api/* → `user` + `auditor` (admin → 403)
|
||||
├── Password Manager ← bcrypt Hash + Verify
|
||||
├── User Store ← PostgreSQL users-Tabelle
|
||||
└── Bootstrap ← Default-User beim ersten Start
|
||||
```
|
||||
|
||||
### Datenmodell
|
||||
|
||||
**Tabelle `users`:**
|
||||
|
||||
| Feld | Beschreibung |
|
||||
|------|-------------|
|
||||
| `id` | Interne ID |
|
||||
| `email` | Login-E-Mail (eindeutig) |
|
||||
| `password_hash` | bcrypt-Hash (Cost 12) — NULL bei LDAP-Usern |
|
||||
| `role` | `user` / `auditor` / `admin` |
|
||||
| `source` | `local` oder `ldap` — Herkunft des Accounts |
|
||||
| `active` | Deaktivierte Nutzer können sich nicht einloggen |
|
||||
| `created_at` | Erstellungszeitpunkt |
|
||||
| `last_login_at` | Letzter erfolgreicher Login |
|
||||
|
||||
**Tabelle `sessions`:**
|
||||
|
||||
| Feld | Beschreibung |
|
||||
|------|-------------|
|
||||
| `token` | Zufälliger 32-Byte-Token |
|
||||
| `user_id` | Referenz auf `users` |
|
||||
| `expires_at` | Ablaufzeitpunkt (rollierend, +8h bei Aktivität) |
|
||||
| `last_active_at` | Wird bei jeder Anfrage aktualisiert |
|
||||
|
||||
### Technische Entscheidungen
|
||||
|
||||
| Entscheidung | Begründung |
|
||||
|---|---|
|
||||
| **Next.js Frontend + Go REST API** | Klare Trennung: Next.js rendert die UI, Go verwaltet Daten und Sicherheit. Kein Java. |
|
||||
| **Session-Cookie (httpOnly)** | Next.js sendet Cookie automatisch mit – kein manuelles Token-Handling im Frontend-Code nötig |
|
||||
| **Server-side Sessions (nicht JWT)** | Logout und Admin-Deaktivierung wirken sofort – JWT wäre bis Ablauf weiterhin gültig |
|
||||
| **Role-Check im Go-Backend** | Sicherheits-kritische Prüfung liegt im Backend, nicht im Next.js-Client (der wäre manipulierbar) |
|
||||
| **RoleGuard in Next.js zusätzlich** | Verhindert kurzes Aufblitzen falscher Seiten – rein UX, kein Sicherheits-Feature |
|
||||
| **bcrypt Cost 12** | Ausreichend langsam gegen Brute-Force |
|
||||
| **LDAP als optionaler Fallback** | Login versucht erst lokalen Account, dann LDAP – Reihenfolge garantiert, dass lokale Admins immer funktionieren |
|
||||
| **LDAP-User in PostgreSQL gespiegelt** | Nach erstem Login landet LDAP-User in `users`-Tabelle (`source: ldap`) – einheitliche Session-Verwaltung, kein Sonder-Code |
|
||||
| **AD-Gruppen → Rollen-Mapping** | Rolle wird bei jedem Login aus AD-Gruppenmitgliedschaft neu bestimmt – Rollen-Änderung in AD wirkt beim nächsten Login |
|
||||
|
||||
### Abhängigkeiten
|
||||
|
||||
**Go Backend:**
|
||||
|
||||
| Paket | Zweck |
|
||||
|---|---|
|
||||
| `golang.org/x/crypto/bcrypt` | Passwort-Hashing |
|
||||
| `crypto/rand` | Sichere Token-Generierung (Stdlib) |
|
||||
| `github.com/go-ldap/ldap/v3` | LDAP/AD-Authentifizierung (PROJ-16) |
|
||||
|
||||
**Next.js Frontend:**
|
||||
|
||||
| Paket | Zweck |
|
||||
|---|---|
|
||||
| `react-hook-form` + `zod` | Login-Formular-Validierung (bereits im Template) |
|
||||
| `shadcn/ui` | UI-Komponenten (bereits installiert) |
|
||||
|
||||
## QA Test Results
|
||||
_To be added by /qa_
|
||||
|
||||
## Deployment
|
||||
_To be added by /deploy_
|
||||
Reference in New Issue
Block a user