presseportale/dev/migration 2026/10-LEGACY-API-KUNDEN.md
Kevin Adametz 5b8bdf4182
Some checks are pending
linter / quality (push) Waiting to run
tests / ci (push) Waiting to run
12-05-2026 Frontend dev
2026-05-12 18:32:33 +02:00

174 lines
6.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 10 Legacy-API-Kunden & Zugriffsbereinigung
## Ausgangspunkt
Das Legacy-System speichert API-Zugriffe nicht applikationsseitig. In Produktion ist Symfony-Logging deaktiviert (`logging_enabled: false`, `sfNoLogger`). API-Nutzung ist daher nicht zuverlässig aus der Anwendung rekonstruierbar.
Stattdessen wird der API-Cutover aus den migrierten Daten abgeleitet:
- Legacy-API-User sind in `users.registration_type = apiuser` bzw. über die Rolle `api-only` erkennbar.
- Legacy-API-Keys wurden bewusst nicht übernommen.
- Legacy-API-Credentials wie `apiReadAccess` / `apiWriteAccess` wurden nicht 1:1 pro User persistiert, sondern in neue Sanctum-Abilities übersetzt.
- Zahlungs-/Freigabestatus kann nur über importierte `legacy_invoices` bzw. später über Grandfathering-Daten bewertet werden.
## Legacy-Regeln
Im alten Symfony-Frontend gilt:
- API-fähige Routen sind in `apps/frontend/config/routing.yml` mit `api_access: true` markiert.
- `ApiAccessFilter` weist `X-ApiKey` auf nicht-API-Routen mit HTTP 501 ab.
- `ApiKeyGuardAuthFilter` liest `X-ApiKey` und sucht `sfGuardUserProfile.api_key`.
- Wird ein Profil gefunden, wird dessen User für den Request eingeloggt.
- Wenn bereits eine gültige Web-Session existiert, kann die API technisch auch ohne gültigen API-Key laufen, sofern Credentials passen.
- `SecureApiAccessFilter` verlangt:
- `GET` / `HEAD``apiReadAccess`
- `POST` / `PUT` / `DELETE``apiWriteAccess`
- andere Methoden → HTTP 405
- Einzelne Actions verlangen zusätzlich Symfony-Credentials wie `editor`.
- `ApiKeyGuardAuthFilter` prüft nicht selbst `is_active`.
## Neue Bewertungsregel
Für den Cutover erhalten nur noch Kunden Zugriff, die im migrierten System fachlich freigabefähig sind:
1. Kandidat ist `registration_type = apiuser` oder hat Rolle `api-only`.
2. User ist aktiv (`is_active = true`).
3. Die letzte importierte Legacy-Rechnung des Users hat `status = paid`.
Alle anderen Kandidaten werden nicht automatisch freigeschaltet:
- `needs_review`: aktiver API-Kandidat ohne importierte Legacy-Rechnung.
- `blocked`: inaktiver API-Kandidat oder letzte Rechnung nicht bezahlt.
## Report-Command
```bash
php artisan api:legacy-customers-report
php artisan api:legacy-customers-report --classification=eligible
php artisan api:legacy-customers-report --portal=businessportal24
php artisan api:legacy-customers-report --no-report
```
Der Command schreibt standardmäßig:
```bash
storage/app/private/migration/legacy-api-customers-*.json
```
Der Report enthält:
- Kandidatenregel und bekannte Datenlücken
- Zusammenfassung nach `eligible`, `needs_review`, `blocked`
- User-ID, E-Mail, Portal, Legacy-ID
- Rollen und Registration-Type
- letzte Legacy-Rechnung inkl. Status, Datum, Betrag
- empfohlene Aktion:
- `invite_to_generate_sanctum_token`
- `manual_billing_review_required`
- `do_not_grant_api_access`
## Aktuelle Datenlage
In der migrierten Datenbank wurden bisher gefunden:
- 195 User mit `registration_type = apiuser`
- 1 API-User mit archivierter Legacy-Rechnung
- diese Rechnung ist bezahlt
Damit ist nach aktueller Datenlage nur ein API-User automatisch freigabefähig. Die übrigen API-User müssen entweder manuell geprüft werden oder benötigen zusätzliche Legacy-Billing-/Vertragsdaten.
## Noch fehlende Daten
Für eine harte finale Entscheidung fehlen ggf.:
- vollständige Legacy-Zuordnung von API-Usern zu zahlenden Vertrags-/Billing-Usern, falls API-User nicht selbst Rechnungsempfänger waren
- explizite Legacy-Credential-Zuordnung `apiReadAccess` / `apiWriteAccess` pro User, falls feiner als `apiuser`/`api-only` benötigt
- aktuelle fachliche Liste aktiver API-Kunden vom Auftraggeber, falls Rechnungsarchiv nicht ausreicht
Ohne diese Daten ist die sichere Standardeinstellung:
- nur `eligible` automatisch zur Token-Migration einladen
- `needs_review` nicht automatisch freischalten
- `blocked` nicht freischalten
## Token-Erstellung im neuen System
Die Customer-Seite für API-Tokens ist zusätzlich technisch abgesichert. Ein User kann nur dann einen Sanctum-Token erstellen, wenn:
1. `users.is_active = true`
2. mindestens eine der folgenden Bedingungen erfüllt ist:
- aktiver neuer Zahlungsstatus in `user_payment_options` (`status = active`, aktueller Zeitraum gültig)
- aktiver Bestandsschutz in `user_payment_options` (`status = grandfathered`, `grandfathered_until >= today`)
- Übergangsweise: letzte importierte Legacy-Rechnung ist `paid`
Damit bekommen reaktivierte oder neue Kunden künftig keinen API-Zugang über alte Rechnungen, sondern erst über die neue aktive Zahlungs-/Vertragslogik. Bereits erstellte Tokens inaktiver User werden zusätzlich bei API-Requests blockiert.
## API-Usage-Logging
Neue API-Requests werden persistent in `api_usage_logs` protokolliert:
- `user_id`
- `personal_access_token_id`
- HTTP-Methode
- Pfad
- Route-Name
- Statuscode
- IP-Adresse
- User-Agent
- Dauer in Millisekunden
- Zeitpunkt
Nicht gespeichert werden:
- Bearer-Token im Klartext
- Legacy-`api_key`
- Request-Payloads
Auch abgewiesene Legacy-Key-Requests (`410 Gone`) und Requests inaktiver User (`403`) werden geloggt.
## API-Rate-Limiting
Die `/api/v1`-Routen sind zusätzlich per Middleware `EnsureApiTokenRateLimit` limitiert:
- Limit: 60 Requests pro Minute
- bevorzugter Schlüssel: Sanctum-/Bearer-Token-ID
- Fallback: SHA-256-Fingerprint des Bearer-Tokens, danach User-ID/IP
- inaktive User werden vorher per `EnsureApiUserIsActive` blockiert
- überschrittene Limits liefern HTTP 429 mit `Retry-After`, `X-RateLimit-Limit` und `X-RateLimit-Remaining`
Damit wird ein einzelner stark nutzender Client begrenzt, ohne andere Tokens desselben Users sofort mitzusperren.
## API-Usage-Reporting
Die protokollierten API-Requests können per Artisan-Command ausgewertet werden:
```bash
php artisan api:usage-report
php artisan api:usage-report --from=2026-04-01 --to=2026-04-30
php artisan api:usage-report --user=123
php artisan api:usage-report --status=403
php artisan api:usage-report --no-report
```
Der Command schreibt standardmäßig:
```bash
storage/app/private/migration/api-usage-*.json
```
Der Report enthält:
- Gesamtzahl Requests
- eindeutige User und Sanctum-Tokens
- 2xx-/4xx-/5xx-Verteilung
- durchschnittliche Dauer
- Top-Pfade
- Statuscode-Verteilung
- Top-User und Top-Tokens
- letzte Requests im gefilterten Zeitraum
Damit ist die neue API-Nutzung ab Cutover nicht mehr von Webserver-Logs abhängig und kann regelmäßig exportiert oder später in eine Admin-UI übernommen werden.
## P7-Abgrenzung Newsletter
`newsletter/unsubscribe` wird bewusst nicht als Legacy-API-Endpoint umgesetzt. Es gibt dafür keinen relevanten Legacy-API-Client. Newsletter-Abmeldung und externer Newsletter-Dienst werden nach der Migration im neuen Frontend sauber neu implementiert.