Commit Graph
5 Commits
Author SHA1 Message Date
clemens ef5d0e1822 Sicherheits-/Korrektheits-Fixes und neue Funktionen
Bugfixes aus dem Code-Review:
- XSS: unescaptes $_SERVER['PHP_SELF'] in csvupload.php und
  letzteneintraege.php durch feste Seitennamen ersetzt.
- Stripe-Webhook: Event-Deduplizierung (neue Tabelle stripe_webhook_events)
  gegen doppelte Verarbeitung/Dolibarr-Rechnungen bei Retry-Zustellung.
- Stripe-Webhook: Tarifwechsel aus dem Kundenportal wird lokal nachgezogen
  (plan_code aus dem Preis-lookup_key bei subscription.updated).
- Post-Redirect-Get fuer jahresauswertung, mailversenden und die
  Selbst-Stricheintragung - verhindert Doppelbuchung/Doppelversand per
  Browser-Refresh.
- Jahresbonus: Mails erst nach erfolgreichem Commit; Restcent-Ausgleich
  beim letzten Empfaenger, damit die Summe exakt stimmt.
- Verschachtelte HTML-Dokumente in csvupload/einzahlung/stricheintragen
  entfernt (Layout kommt aus header.php).
- Rate-Limit fuer den Versand von E-Mail-Verifizierungslinks.

Neue Funktionen:
- Mitglieder koennen ihren zuletzt selbst eingetragenen Strich wieder
  stornieren (nur eigene Web-Eintraege, Kassenwart-Eintraege bleiben).
- Monatsuebersicht des eigenen Verbrauchs im Mitglieder-Dashboard.
- Automatische Zahlungserinnerung: opt-in pro Mandant ab der
  Warnschwelle, mit Intervall; Cron-Skript scripts/send-payment-reminders.php.
- CSV-Import fuer Mitgliederlisten inkl. herunterladbarer Vorlage
  (mitglieder-vorlage.php), Semikolon-/Komma- und BOM-Erkennung.
- Logo als PDF-Wasserzeichen pro Mandant (Upload in den Mandant-
  Einstellungen, geschuetzt unter var/tenant_logos/, ersetzt den
  Text-Wasserzeichen im Ausdruck).

Robusterer Teilnehmer-Lookup im Dashboard ueber user_id (Fallback E-Mail).
2026-07-20 21:54:16 +02:00
clemensandClaude Sonnet 5 54217d2acb M8: Security-Headers, Rate-Limits und Audit-Log
Erste drei Bausteine der Haertung:

- Security-Headers (X-Content-Type-Options, X-Frame-Options, Referrer-
  Policy, Permissions-Policy, HSTS bei HTTPS) laufen automatisch ueber
  app_send_security_headers() am Ende von app/bootstrap.php fuer jede
  dynamische Seite; landing.php war als einzige Seite ganz ohne PHP und
  bekam einen minimalen Bootstrap-Aufruf. Bewusst kein CSP, da die
  bestehenden Templates durchgaengig auf Inline-style-Attribute setzen.
- DB-gestuetzte Rate-Limits (neue Tabelle rate_limit_attempts) fuer
  Login (10/15min je E-Mail, 20/15min je IP), Registrierung (5/h je IP)
  und Passwort-Reset-Anfrage (5/h je E-Mail, 10/h je IP); bei
  ausgereiztem Reset-Limit erscheint dieselbe generische Meldung wie im
  Erfolgsfall, um kein Konto-Enumeration-Signal zu geben.
- Zentrales Audit-Log (neue Tabelle audit_log) fuer Mitgliederverwaltung,
  Zugangsvergabe/-entzug, Storno, Mandant-Einstellungen, Hinweise,
  CSV-Import, Jahresbonus-Verteilung und Live-Mailversand; sichtbar fuer
  Owner/Admin auf mandant-einstellungen.php.

Live getestet: Rate-Limit greift nach 10 Fehlversuchen, Audit-Log-Eintrag
mit korrekten Metadaten und Nutzernamen ueber einen isolierten Test-
Mandanten geprueft. Alle Regressionstests weiterhin gruen (26/26 Smoke,
104 Golden-Master-Assertions).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-15 18:04:14 +02:00
clemensandClaude Sonnet 5 536ef2ead2 M6: Jahresabschluss als generisches Feature statt AOK-spezifischem Bonus-Skript
jahresauswertung.php verband sich bisher mit fest codierten (kaputten)
Zugangsdaten selbst zur Datenbank statt ueber config.php, hatte keine
Zugriffskontrolle und kein CSRF, und verteilte bei jedem Aufruf sofort
einen hart codierten Bonus-Topf (490 Striche a 0,20 Euro) per PHPMailer
(dessen Quelldateien im Repo fehlen) mit AOK-spezifischem Mailtext.

Nach Abstimmung mit dem Kunden als generisches, mandantenfaehiges Feature
neu gebaut statt nur deaktiviert oder rein lesend umgesetzt:

- Admin gibt einen frei waehlbaren Gesamtbetrag ein, das System verteilt
  ihn proportional zu den Jahresstrichen auf alle aktiven Mitglieder.
- Standardmaessig aktive Dry-Run-Checkbox zeigt die Verteilung, ohne zu
  buchen oder Mails zu verschicken.
- Bestaetigter Lauf bucht ueber dasselbe Zweig-Muster wie ueberall
  (Default-Mandant Dual-Write, andere Mandanten ledger_record_payment)
  und verschickt personalisierte Mails ueber saas_send_mail(), protokolliert
  im outbound_emails-Versandlog.
- Zugriffskontrolle ergaenzt (owner/admin/treasurer + Legacy-Fallback).
- http-smoke.php: jahresauswertung.php jetzt regulaerer Check statt
  uebersprungenem unsicherem Aufruf; damit sind keine Seiten mehr
  uebersprungen oder als bekannter offener Punkt markiert (26/26 gruen).

Live getestet: Dry-Run mit korrekter proportionaler Verteilung (Summe
ergibt exakt den Gesamtbetrag), Live-Lauf bucht und versendet korrekt,
Testdaten anschliessend vollstaendig entfernt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-15 17:21:34 +02:00
clemens 2e6d79e896 M0 Einrichtung 2026-07-11 22:24:22 +02:00
clemens 92d94f1c95 renew 2026-07-11 18:21:33 +02:00