Files
fotospiel-app/docs/process/changes/2025-10-02-registration-role-fixes.md
2025-11-20 10:44:29 +01:00

3.9 KiB

Registrierungs-Fixes: Redirect, Error-Clearing und Role-Handling (2025-10-02)

Problem-Beschreibung

  • Redirect-Fehler: Bei erfolgreicher Registrierung (free oder paid Package) wurde onSuccess in Register.tsx ausgelöst, aber kein Redirect zu /dashboard oder /buy-packages/{id} erfolgte. Ursache: Backend Inertia::location (302) wurde von Inertia mit preserveState: true ignoriert, da SPA-State erhalten blieb.
  • Persistente Errors: Server-Errors (z.B. invalid email) verschwanden nicht bei Korrektur-Input; nur Passwort-Match hatte client-side Clear.
  • Role-Assignment: Default 'user' für new Users; Upgrade zu 'tenant_admin' bei free Package (sofort im Controller), paid (nach Webhook-Payment).
  • Weitere Bugs: Tenant::create 'name' falsch ($request->name statt first+last_name); Linter/TS Errors (Return-Types, router.visit unknown).

Fixes

Backend (MarketingRegisterController.php)

  • JSON-Response für Redirect: Ersetzt Inertia::location durch response()->json(['success' => true, 'redirect' => $url]) für free (Zeile 141) und paid (Zeile 133). Kompatibel mit Inertia onSuccess (page.props.success/redirect prüfen).
  • Tenant Name Fix: 'name' => $request->first_name . ' ' . $request->last_name (Zeile 71); slug entsprechend angepasst.
  • Role-Logic: 'role' => 'user' in User::create (Zeile 66); für free: Update zu 'tenant_admin' nach TenantPackage::create (Zeile 129), Re-Login (Zeile 130). Für paid: Kein Upgrade bis Webhook (Paddle).
  • Return-Type: store() zu JsonResponse (Zeile 44); use JsonResponse hinzugefügt (Zeile 22).

Frontend (Register.tsx)

  • onSuccess-Handling: Prüfe page.props.success && router.visit(page.props.redirect as string) (Zeile 66-68); Fallback zu data.package_id ? `/buy-packages/\${data.package_id}` : '/dashboard' (Zeile 71-75); console.log für Debug (Zeile 67, 74).
  • Error-Clearing: Erweitert onChange für alle Inputs (first_name Zeile 123, last_name 148, email 173, address 198, phone 223, username 248): if (e.target.value.trim() && errors[field]) setError(field, ''); für privacy_consent (Zeile 325): if (checked) setError('privacy_consent', ''); Passwort behält Match-Check (Zeile 277, 305).
  • General Errors Key: nutze <div key={"general-errors-" + Object.keys(errors).join('-')}> (Zeile 347) für Re-Render bei Error-Änderungen.

Tests (RegistrationTest.php)

  • JSON-Asserts: assertJsonStructure(['success', 'redirect']) und assertJson(['success' => true]) in test_registration_creates_user_and_tenant (Zeile 37-39) und test_registration_without_package (Zeile 78-80).
  • Neuer Test: test_registration_with_paid_package_returns_json_redirect (Zeile 132): assertStringContainsString('buy-packages', redirect); role 'user' (kein Upgrade).
  • Validation/Email: Unverändert, assertSessionHasErrors (Zeile 107).

Verification

  • Backend: php artisan test --filter RegistrationTest; prüfe JSON-Response in Browser-Network-Tab (POST /register -> 200 JSON).
  • Frontend: Registrierung mit free: Redirect zu /verification.notice; paid: zu /buy-packages/10; Errors clear bei Input (z.B. invalid email -> input valid -> error gone).
  • Role: DB-Check: free -> 'tenant_admin', paid -> 'user' (Upgrade via Webhook).
  • Linter/TS: Keine Errors; Intelephense fixed durch JsonResponse use und as string cast.

PRP-Update (docs/prp/13-backend-authentication.md)

  • Hinzugefügt: Section "Role Flow in Registration": Default 'user'; Upgrade 'tenant_admin' bei free Package (Controller); paid via Webhook (Stripe invoice.paid, Paddle IPN); JSON-Success für Inertia-Forms (preserveState + onSuccess visit).

Best Practices

  • Inertia-Forms: Bei preserveState JSON-Response für custom Redirects verwenden, statt location() (vermeidet State-Ignorieren).
  • Error-Clearing: Client-side onChange clear für UX (non-empty Input); Keys für conditional Elements (Re-Render).
  • GDPR: Privacy-Consent required; no PII in Logs.

Date: 2025-10-02