# Frontend Migration Guide - API Umstrukturierung **Datum:** 16. November 2025 **Betrifft:** ALLE API-Aufrufe im Frontend **Status:** ⚠️ Aktion erforderlich - ALLE Routen prüfen! --- ## � BREAKING CHANGE: Konsistente `/api` Prefixes **ALLE API-Routen haben sich geändert!** ### Vorher (inkonsistent): ```javascript // 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): ```javascript // 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 1. **Public API**: `/api/*` - Öffentlich zugänglich - `/api/upload`, `/api/groups`, `/api/download`, etc. 2. **Management API**: `/api/manage/*` - Token-basiert (UUID aus Upload-Response) - Für Gruppenbesitzer 3. **Admin API**: `/api/admin/*` ⚠️ **BEARER TOKEN ERFORDERLICH** - Moderation, Logs, Consents - `/api/admin/groups`, `/api/admin/deletion-log`, etc. 4. **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: ```bash # 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): ```javascript // ❌ 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: 1. **Setup-Status abfragen** – `GET /auth/setup/status` → `{ needsSetup, hasSession }` 2. **Ersten Admin anlegen** – `POST /auth/setup/initial-admin` (nur einmal nötig) 3. **Login** – `POST /auth/login` mit `{ username, password }` 4. **CSRF Token holen** – `GET /auth/csrf-token` (liefert `csrfToken` und 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): ```javascript const response = await fetch('/api/admin/groups'); ``` #### Nachher (mit Session + CSRF): ```javascript 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: ```javascript 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 ```javascript 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!) ```bash 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/platforms` für Moderationsfilter - ✅ `/api/social-media/platforms` fü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-Calls - `Components/Pages/ModerationGroupImagesPage.js` - Gruppe laden + Bilder löschen - `Components/ComponentUtils/DeletionLogSection.js` - Deletion Log - `Components/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()` und `axios` Calls gefunden (grep) - [ ] Alle Routen ohne `/api` Prefix identifiziert - [ ] `/api` Prefix 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) - [ ] `AdminSessionProvider` wrappt die App - [ ] `AdminSessionGate` schützt alle Moderationsseiten - [ ] `adminApi.js` nutzt `credentials: '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 `.env` aktualisiert --- ## 🧪 Testing ### Lokales Testing 1. Backend starten (`npm run dev`) – stellt Session- & Auth-Routen bereit. 2. Frontend starten (`npm start`). 3. `/moderation` öffnen: - **Falls kein Admin existiert** → Setup-Formular ausfüllen. - Danach mit frisch erstellten Credentials anmelden. 4. 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:** 1. Session abgelaufen (Inaktivität, Browser geschlossen) 2. 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:** - `AdminSessionGate` neu laden → holt automatisch neues Token - Sicherstellen, dass `adminApi` bei mutierenden Calls `X-CSRF-Token` setzt ### 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:** 1. Backend-Logs prüfen (Rate-Limits? falsches Passwort?) 2. Prüfen, ob `ADMIN_SESSION_SECRET` gesetzt ist (sonst keine stabilen Sessions) 3. Browser-Konsole → Network Request `POST /auth/login` analysieren --- ## 🚀 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 ```yaml # 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:-/} ``` ```bash # .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)