- replace bearer auth with session+CSRF flow and add admin user directory - update frontend moderation flow, force password change gate, and new CLI - refresh changelog/docs/feature plan + ensure swagger dev experience
11 KiB
Frontend Migration Guide - API Umstrukturierung
Datum: 16. November 2025
Betrifft: ALLE API-Aufrufe im Frontend
Status: ⚠️ Aktion erforderlich - ALLE Routen prüfen!
<EFBFBD> BREAKING CHANGE: Konsistente /api Prefixes
ALLE API-Routen haben sich geändert!
Vorher (inkonsistent):
// Teils mit /api
fetch('/api/upload/batch')
fetch('/api/manage/xyz')
// Teils OHNE /api - FALSCH!
fetch('/groups/123')
fetch('/groups/123/approve')
fetch('/moderation/groups/123')
Jetzt (konsistent):
// ALLE Routen mit /api Prefix
fetch('/api/upload/batch')
fetch('/api/manage/xyz')
fetch('/api/groups/123') // Public
fetch('/api/admin/groups/123/approve') // Admin
fetch('/api/admin/groups/123') // Admin
🔒 Admin API Authentication
Alle Admin-Endpoints (/api/admin/* und /api/system/*) benötigen jetzt Bearer Token Authentication.
Route-Hierarchie
-
Public API:
/api/*- Öffentlich zugänglich
/api/upload,/api/groups,/api/download, etc.
-
Management API:
/api/manage/*- Token-basiert (UUID aus Upload-Response)
- Für Gruppenbesitzer
-
Admin API:
/api/admin/*⚠️ BEARER TOKEN ERFORDERLICH- Moderation, Logs, Consents
/api/admin/groups,/api/admin/deletion-log, etc.
-
System API:
/api/system/migration/*⚠️ BEARER TOKEN ERFORDERLICH- Wartungsfunktionen
Betroffene Admin-Endpoints
/api/admin/groups- Gruppen auflisten/api/admin/groups/:id- Gruppe abrufen/api/admin/groups/:id/approve- Gruppe genehmigen/api/admin/groups/:id- Gruppe löschen/api/admin/groups/:id/images/:imageId- Bild löschen/api/admin/groups/by-consent- Nach Consent filtern/api/admin/consents/export- Consent-Export/api/admin/social-media/platforms- Plattformen auflisten/api/admin/reorder/:groupId/images- Bilder neu anordnen/api/admin/deletion-log- Deletion Log/api/admin/cleanup/*- Cleanup-Funktionen/api/admin/rate-limiter/stats- Rate-Limiter-Statistiken/api/admin/management-audit- Audit-Log
System-Endpoints:
/api/system/migration/migrate- Migration ausführen/api/system/migration/rollback- Migration zurückrollen
📝 Erforderliche Änderungen
1. ALLE API-Routen prüfen und /api hinzufügen
Schritt 1: Finde alle API-Aufrufe im Frontend:
# Alle fetch/axios Aufrufe finden
grep -r "fetch\(" frontend/src/
grep -r "axios\." frontend/src/
Schritt 2: Prüfe jede Route und füge /api Prefix hinzu (falls fehlend):
// ❌ FALSCH (alte Routen)
fetch('/groups/123')
fetch('/groups/123/approve')
fetch('/moderation/groups/123')
// ✅ RICHTIG (neue Routen)
fetch('/api/groups/123') // Public
fetch('/api/admin/groups/123/approve') // Admin (+ Bearer Token!)
fetch('/api/admin/groups/123') // Admin (+ Bearer Token!)
2. Admin-Session & CSRF einrichten
Die Admin-API verwendet jetzt serverseitige Sessions mit CSRF-Schutz. Statt Tokens in .env zu hinterlegen, erfolgt die Authentifizierung über Login-Endpunkte:
- Setup-Status abfragen –
GET /auth/setup/status→{ needsSetup, hasSession } - Ersten Admin anlegen –
POST /auth/setup/initial-admin(nur einmal nötig) - Login –
POST /auth/loginmit{ username, password } - CSRF Token holen –
GET /auth/csrf-token(liefertcsrfTokenund setzt HttpOnly Session-Cookie)
Alle nachfolgenden Admin-Requests senden automatisch das Session-Cookie (credentials: 'include') und den X-CSRF-Token Header.
3. API-Aufrufe für Admin-Endpoints anpassen
Vorher (ohne Session):
const response = await fetch('/api/admin/groups');
Nachher (mit Session + CSRF):
const response = await fetch('/api/admin/groups', {
method: 'GET',
credentials: 'include',
headers: {
'X-CSRF-Token': csrfToken, // nur bei mutierenden Requests zwingend nötig
}
});
3. Zentrale API-Helper-Funktion erstellen
Empfohlen: Nutze src/services/adminApi.js als einzige Stelle, die Session- und CSRF-Handling kapselt:
const SAFE_METHODS = new Set(['GET', 'HEAD', 'OPTIONS']);
let csrfToken = null;
const ensureCsrfToken = async () => {
if (!csrfToken) {
const response = await fetch('/auth/csrf-token', { credentials: 'include' });
const data = await response.json();
csrfToken = data.csrfToken;
}
return csrfToken;
};
export const adminFetch = async (url, options = {}) => {
const method = (options.method || 'GET').toUpperCase();
const headers = new Headers(options.headers || {});
if (!SAFE_METHODS.has(method)) {
headers.set('X-CSRF-Token', await ensureCsrfToken());
}
const response = await fetch(url, {
...options,
method,
credentials: 'include',
headers
});
if (!response.ok) {
throw await parseError(response);
}
return response;
};
4. Error Handling erweitern
try {
const response = await adminFetch('/api/admin/groups');
const data = await response.json();
// ...
} catch (error) {
if (error.status === 401) {
// Session abgelaufen
redirectToLogin();
} else if (error.status === 403 && error.reason === 'CSRF_INVALID') {
// CSRF neu anfordern
await adminSession.refreshStatus();
} else if (error.status === 429) {
notifyRateLimit();
} else {
console.error('Admin API error:', error);
}
}
🔍 Betroffene Dateien finden
Alle API-Calls prüfen (KRITISCH!)
cd frontend/src
# ALLE API-Calls finden (fetch + axios):
grep -rn "fetch(" --include="*.js" --include="*.jsx"
grep -rn "axios\." --include="*.js" --include="*.jsx"
# Spezifisch nach alten Routen OHNE /api suchen:
grep -rn "fetch('/groups" --include="*.js"
grep -rn "fetch('/moderation" --include="*.js"
# Admin-API-Calls finden:
grep -rn "/api/admin" --include="*.js" --include="*.jsx"
Bekannte betroffene Dateien:
Routen ohne /api Prefix (MÜSSEN GEFIXT WERDEN):
-
Components/Pages/ModerationGroupsPage.js- ❌
/groups/${groupId}/approve→ ✅/api/admin/groups/${groupId}/approve - ❌
/groups/${groupId}(DELETE) → ✅/api/admin/groups/${groupId} - ✅
/api/admin/social-media/platformsfür Moderationsfilter - ✅
/api/social-media/platformsfür öffentliche Formulare (keine Session nötig)
- ❌
-
Components/Pages/ModerationGroupImagesPage.js- ❌
/moderation/groups/${groupId}→ ✅/api/admin/groups/${groupId}
- ❌
-
Components/Pages/PublicGroupImagesPage.js- ❌
/groups/${groupId}→ ✅/api/groups/${groupId}
- ❌
Admin-Endpoints (Session + CSRF erforderlich):
Components/Pages/ModerationGroupsPage.js- Alle Moderations-CallsComponents/Pages/ModerationGroupImagesPage.js- Gruppe laden + Bilder löschenComponents/ComponentUtils/DeletionLogSection.js- Deletion LogComponents/ComponentUtils/ConsentManager.js- Consent-Export (Admin)services/reorderService.js- Admin-Reorder (falls im Einsatz)
Public/Management Endpoints (nur Pfad prüfen):
Utils/batchUpload.js- Bereits korrekt (/api/...)Components/Pages/ManagementPortalPage.js- Bereits korrekt (/api/manage/...)Utils/sendRequest.js- Bereits korrekt (axios)
✅ Checkliste
Phase 1: Route-Prefixes (ALLE Dateien)
- Alle
fetch()undaxiosCalls gefunden (grep) - Alle Routen ohne
/apiPrefix identifiziert /apiPrefix zu Public-Routen hinzugefügt (/api/groups,/api/upload)- Admin-Routen auf
/api/admin/*geändert - Management-Routen auf
/api/manage/*geprüft (sollten schon korrekt sein)
Phase 2: Admin Authentication (Session)
AdminSessionProviderwrappt die AppAdminSessionGateschützt alle ModerationsseitenadminApi.jsnutztcredentials: 'include'+X-CSRF-Token- Login- und Initial-Setup-Formulare eingebunden
- Fehlerbehandlung für
401/403 (SESSION_REQUIRED/CSRF_INVALID)ergänzt
Phase 3: Testing & Deployment
- Frontend lokal getestet (alle Routen)
- Admin-Funktionen getestet (Approve, Delete, etc.)
- Public-Routen getestet (Gruppe laden, Upload)
- Production
.envaktualisiert
🧪 Testing
Lokales Testing
- Backend starten (
npm run dev) – stellt Session- & Auth-Routen bereit. - Frontend starten (
npm start). /moderationöffnen:
- Falls kein Admin existiert → Setup-Formular ausfüllen.
- Danach mit frisch erstellten Credentials anmelden.
- Moderationsfunktionen (Approve/Delete/Reorder/Consent-Export) durchspielen.
Test-Fälle
- ✅ Moderation funktioniert mit aktiver Session
- ✅ Login/Logout ändert sofort den Zugriff auf Seiten
- ✅ CSRF-geschützte Aktionen schlagen fehl, wenn Token manipuliert wird
- ✅ Consent-Export & Reorder funktionieren weiterhin
- ✅ Öffentliche Routen bleiben ohne Login erreichbar
📚 Weitere Dokumentation
- Backend Auth-Doku:
AUTHENTICATION.md - API Route-Übersicht:
backend/src/routes/README.md - Route-Konfiguration:
backend/src/routes/routeMappings.js - OpenAPI Spec:
backend/docs/openapi.json - Swagger UI: http://localhost:5001/api/docs/ (dev only)
🆘 Troubleshooting
Problem: "Session Required" / 403 Fehler
Ursachen:
- Session abgelaufen (Inaktivität, Browser geschlossen)
- Cookies blockiert (Third-Party/SameSite Einstellungen)
Lösung:
- Seite neu laden → Login-Formular erscheint
- Browser-Einstellungen prüfen: Cookies für Host erlauben
Problem: "CSRF invalid"
Ursachen:
- CSRF-Token nicht gesetzt oder veraltet
Lösung:
AdminSessionGateneu laden → holt automatisch neues Token- Sicherstellen, dass
adminApibei mutierenden CallsX-CSRF-Tokensetzt
Problem: Setup-Formular erscheint nicht
Ursachen:
- Bereits ein Admin vorhanden
Lösung:
- Bestehende Admin-Credentials verwenden
- Falls vergessen: über Datenbank (Tabelle
admin_users) neuen Admin eintragen oder Passwort zurücksetzen
Problem: Login schlägt wiederholt fehl
Checks:
- Backend-Logs prüfen (Rate-Limits? falsches Passwort?)
- Prüfen, ob
ADMIN_SESSION_SECRETgesetzt ist (sonst keine stabilen Sessions) - Browser-Konsole → Network Request
POST /auth/loginanalysieren
🚀 Deployment
Production Checklist
- Sicheres
ADMIN_SESSION_SECRET(>= 32 random bytes) gesetzt - HTTPS aktiviert (Cookies:
Secure,SameSite=Strict) - Session-DB Pfad (
ADMIN_SESSION_DIR/ADMIN_SESSION_DB) persistent gemacht - Admin-Benutzer erstellt und dokumentiert (kein Secret im Frontend)
- Monitoring/Alerting für fehlgeschlagene Logins eingerichtet
Docker Deployment
# docker-compose.yml
services:
backend:
environment:
- ADMIN_SESSION_SECRET=${ADMIN_SESSION_SECRET}
- ADMIN_SESSION_DIR=/data/sessions
# optional weitere Backend-ENV Variablen
frontend:
environment:
- PUBLIC_URL=${PUBLIC_URL:-/}
# .env (nicht in Git!)
ADMIN_SESSION_SECRET=$(openssl rand -hex 32)
Fragen? Siehe AUTHENTICATION.md für detaillierte Backend-Dokumentation.
Status der Backend-Changes: ✅ Vollständig implementiert und getestet (45/45 Tests passing)