Files
WebAPP/CLAUDE.md
Rhino ad60e7a9f9 Spielerpositionen, Statistiken, Fahrgemeinschaften, Spielfeld-Visualisierung
- PlayerPosition Enum (7 Handball-Positionen) mit Label/ShortLabel
- Spielerstatistik pro Spiel (Tore, Würfe, TW-Paraden, Bemerkung)
- Position-Dropdown in Spieler-Editor und Event-Stats-Formular
- Statistik-Seite: TW zuerst, Trennlinie, Feldspieler, Position-Badges
- Spielfeld-SVG mit Ampel-Performance (grün/gelb/rot)
- Anklickbare Spieler im Spielfeld öffnen Detail-Modal
- Fahrgemeinschaften (Anbieten, Zuordnen, Zurückziehen)
- Übersetzungen in allen 6 Sprachen (de, en, pl, ru, ar, tr)
- .gitignore für Laravel hinzugefügt
- Demo-Daten mit Positionen und Statistiken

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 11:47:34 +01:00

8.1 KiB

WebApp_Install — Handball Team Manager

Projekt-Typ

Laravel 12 WebApp zur Verwaltung von Handball-Teams, Spielern, Eltern, Terminen und Dateien. PHP 8.2+, SQLite/MySQL, Blade + Alpine.js + Tailwind CSS, Quill.js WYSIWYG-Editor. Deployment: Shared Hosting (all-inkl.com, FTP only, kein SSH).

Architektur

Verzeichnisstruktur

  • app/Models/ — Eloquent Models (User, Player, Team, Event, Setting, etc.)
  • app/Http/Controllers/Admin/ — Admin-Bereich (UserController, SettingsController, etc.)
  • app/Http/Controllers/Auth/ — Login, Register, ForgotPassword, ResetPassword
  • app/Http/Middleware/ — InstallerMiddleware, SetLocaleMiddleware, SecurityHeadersMiddleware, ActiveUserMiddleware, DsgvoConsentMiddleware, StaffMiddleware, AdminOnlyMiddleware
  • app/Services/ — HtmlSanitizerService (HTMLPurifier), GeocodingService, SupportApiService
  • app/Enums/ — UserRole, EventType, EventStatus, ParticipantStatus, CateringStatus
  • app/Notifications/ — ResetPasswordNotification (Custom, mit Setting-Template)
  • resources/views/ — Blade-Templates (layouts: admin, guest, app, installer)
  • lang/{de,en,pl,ru,ar,tr}/ — 6 Sprachen: Deutsch, Englisch, Polnisch, Russisch, Arabisch, Tuerkisch
  • database/migrations/ — Nummeriert mit Prefix 0001-0035
  • database/seeders/ — AdminSeeder, DemoSeeder, FaqSeeder

Wichtige Patterns

  • Settings: Key-Value Store in settings Tabelle. Setting::get($key) mit 1-Stunden-Cache, Setting::set($key, $value) mit Cache-Invalidierung
  • Locale-Settings: Rechtliche Texte und E-Mail-Templates sind locale-suffixed: impressum_html_de, datenschutz_html_en, password_reset_email_pl etc.
  • Passwort-Hashing: User-Model nutzt Laravel Cast 'password' => 'hashed' — KEIN manuelles Hash::make beim Setzen via $user->password = $pw noetig
  • HTML-Output: Alle {!! !!}-Ausgaben von User-Content muessen durch HtmlSanitizerService::sanitize() gehen
  • Rollen: Admin, Coach, ParentRep, User (Enum UserRole)
  • Soft-Deletes: User und Player (7 Tage Wiederherstellung)
  • Activity-Log: ActivityLog::log() / ActivityLog::logWithChanges() fuer Audit-Trail
  • User-Model: Nutzt Notifiable Trait (erforderlich fuer Passwort-Reset-Notifications)
  • .env-Manipulation: updateEnvValues() Helper in InstallerController und SettingsController

Multi-Language

  • 6 Sprachen: de, en, pl, ru, ar, tr
  • Translation-Dateien: lang/{locale}/admin.php, auth_ui.php, passwords.php, ui.php, events.php, profile.php, validation.php
  • Locale wird per SetLocaleMiddleware aus $user->locale oder Session gesetzt
  • RTL-Support fuer Arabisch (ar)
  • Alle Uebersetzungsschluessel muessen in ALLEN 6 Sprachen hinzugefuegt werden

Installer (5-Step Wizard)

  1. Systemcheck (PHP-Version, Extensions, Berechtigungen)
  2. Datenbank (SQLite/MySQL Konfiguration)
  3. Einstellungen (App-Name, Admin-Account)
  4. E-Mail (SMTP-Konfiguration mit Verbindungstest, oder Log-Modus zum Ueberspringen)
  5. Abschluss (Finalize, Demo-Daten, Lizenz)
  • InstallerMiddleware prueft storage/installed Datei
  • Setup-Token-Schutz: Token in storage/setup-token, SHA256 im Laravel-Log
  • SMTP-Test nutzt Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport
  • PW-Reset-Standardtexte fuer 6 Sprachen in getDefaultPasswordResetTexts()
  • Session-basierte Datenpersistenz zwischen Schritten

Password Reset Flow

  1. User klickt "Passwort vergessen?" auf Login-Seite
  2. ForgotPasswordController sendet Reset-Link via Laravel Password Broker
  3. ResetPasswordNotification laedt Custom-Template aus Setting::get('password_reset_email_{locale}')
  4. Platzhalter: {name}, {link}, {app_name}
  5. Fallback auf Standard-Laravel-Template mit Translation-Keys (passwords.reset_*)

Admin Settings Tabs

  • Allgemein: App-Name, Slogan, Favicon, Saison
  • E-Mail: SMTP-Konfiguration mit Verbindungstest (schreibt in .env, Artisan::call('config:clear'))
  • Rechtliches: Impressum + Datenschutz + PW-Reset-E-Mail pro Sprache (Quill-Editor mit Flaggen-Selector)
  • Event-Standards: Min-Werte fuer Spieler, Catering, Zeitnehmer pro Event-Typ
  • Dateikategorien: CRUD fuer File-Categories
  • Sichtbarkeit: Feature-Toggles
  • Lizenz: License-Key-Validierung via SupportApiService
  • Wartung: Demo-Daten loeschen, Factory-Reset

Lazy Quill-Initialisierung (Rechtliches-Tab)

  • Quill-Editoren werden erst bei Klick auf die Sprach-Flagge erstellt (initLocaleEditors(locale))
  • Verhindert Datenverlust: Nicht-initialisierte Locales behalten ihre Server-Werte in Hidden-Inputs
  • $watch('legalLocale') + $nextTick() fuer verzoegerte Erstellung
  • syncEditors() synchronisiert nur tatsaechlich initialisierte Editoren

Route-Struktur (Middleware)

  • Installer: throttle:10,1, ohne SetLocaleMiddleware/ActiveUserMiddleware
  • Oeffentlich: Login, Register, Legal-Pages, Locale-Switch
  • User-Bereich: auth Middleware
  • Admin-Bereich: auth + admin + prefix('admin')
    • Staff-Routes (Admin + Coach): staff Middleware
    • Admin-Only-Routes: admin-only Middleware (Settings, Locations, Support)

Security

Middleware-Stack

  • CSP und Permissions-Policy via SecurityHeadersMiddleware (inkl. COOP-Header)
  • StaffMiddleware — prueft Admin oder Coach Rolle
  • AdminOnlyMiddleware — prueft explizit Admin-Rolle (Route-Level-Schutz)
  • Rate-Limiting auf Auth-Routes, User-Actions, Geocoding, Installer

Schutzmassnahmen

  • Honeypot-Feld auf Login/Register-Formularen
  • DSGVO-Consent-System mit Datei-Upload und Admin-Bestaetigung
  • Factory Reset benoetigt Passwort + Bestaetigung "RESET-BESTAETIGT"
  • File-Autorisierung: authorizeFileAccess() in FileController prueft Team-Zugehoerigkeit
  • Settings-Whitelist: SettingsController akzeptiert nur bekannte Keys + validierte Locale-Suffixe
  • SSRF-Schutz: GeocodingService mit Host-Whitelist, HTTPS-only, DNS-Rebinding-Check, Timeout 5s
  • Installer-Sicherheit: Admin-Passwort sofort gehasht, Setup-Token nur als SHA256 geloggt
  • Path-Traversal-Schutz: DSGVO-Datei-Downloads pruefen str_starts_with('dsgvo/')
  • HTML-Sanitisierung: Alle User-Content-Ausgaben durch HtmlSanitizerService geschuetzt
  • Invitation-Tokens: SHA-256 gehasht in DB gespeichert
  • E-Mail-Normalisierung: Lowercase-Vergleich bei Login und Password-Reset
  • Team-Scoping: Coach/ParentRep sehen nur ihre zugewiesenen Teams

Security-Audit-Historie (Maerz 2026)

6 Audits durchgefuehrt, Score: 6.5 → 9.5/10

  • 95 Findings insgesamt, 88 behoben, 3 akzeptierte Risiken, 4 verbleibende Niedrig/Info
  • Akzeptierte Risiken: MIME-Spoofing (F05), Enum-Reuse (F20), CSP unsafe-inline (W04, CDN-Abhaengigkeit)

Conventions

  • Controller-Methoden: resourceful (index, create, store, show, edit, update, destroy)
  • Blade-Components: <x-layouts.admin>, <x-layouts.guest>, <x-layouts.app>, <x-layouts.installer>
  • Alpine.js fuer interaktive UI-Elemente
  • Quill.js v1.3.7 fuer WYSIWYG-Editoren (via CDN mit SRI-Hashes)
  • Keine Tests vorhanden — bei Aenderungen manuell testen
  • Commit-Sprache: Deutsch oder Englisch
  • Alle Uebersetzungsschluessel muessen in ALLEN 6 Sprachen hinzugefuegt werden

Haeufige Aufgaben

Neuen Translation-Key hinzufuegen

Immer in allen 6 Dateien: lang/de/, lang/en/, lang/pl/, lang/ru/, lang/ar/, lang/tr/

Neues Setting hinzufuegen

  1. Migration erstellen: Setting::firstOrCreate(['key' => '...'], [...])
  2. In SettingsController edit() laden
  3. In View rendern
  4. In update() speichern (mit Sanitization fuer HTML)

Neues locale-spezifisches Setting

  1. Keys: {setting_name}_{locale} (z.B. impressum_html_de)
  2. Migration fuer alle 6 Locales
  3. In SettingsController $localeSettings Array aufnehmen
  4. In View mit Sprach-Flaggen-Selector anzeigen
  5. In update() mit Whitelist und updateOrCreate() behandeln
  6. Wichtig: Neuen Key zur Whitelist in SettingsController::update() hinzufuegen ($allowedLocaleKeys)

Neue Admin-Route hinzufuegen

  1. Route in routes/web.php im passenden Middleware-Block:
    • Alle Admin-Panel-Nutzer: direkt unter admin Prefix
    • Staff (Admin + Coach): unter staff Middleware
    • Nur Admin: unter admin-only Middleware
  2. Controller-Methode mit Autorisierungs-Pruefung
  3. View erstellen
  4. Translation-Keys fuer alle 6 Sprachen