10 Commits
Author SHA1 Message Date
clemensandClaude Opus 5 a2dcc4df65 Zwei-Faktor-Anmeldung per TOTP
app/totp.php implementiert RFC 6238 selbst statt per Bibliothek: der
Algorithmus ist ein HMAC plus eine Truncation, und ein zweiter Faktor ist
die letzte Stelle fuer ungepruefte Abhaengigkeiten. Der QR-Code entsteht
aus dem ohnehin vorhandenen TCPDF, damit kein externer Dienst das
Geheimnis sieht.

Beim Login wird die Anmeldung bei aktivem zweitem Faktor nicht
abgeschlossen; der Zwischenzustand gewaehrt keinerlei Zugriff und ist
byte-identisch zu einem unangemeldeten Aufruf. users.totp_last_step
verhindert die Wiederverwendung eines abgefangenen Codes innerhalb seines
Gueltigkeitsfensters. Abschalten verlangt Passwort und Code.

APP_REQUIRE_2FA_FOR_ADMINS macht den Faktor fuer Platform-Admins
verbindlich, per Weiterleitung auf die Einrichtung statt als harte Sperre
- sonst koennte der Schalter den einzigen Admin aussperren. Standard aus.

check-konto-und-mandantenwechsel erwartete beim Login noch das entfernte
Kundenkuerzel-Feld und damit einen direkten Sprung aufs Dashboard; der
Check bildet jetzt den tatsaechlichen Weg ueber die Mandantenauswahl ab.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 23:51:45 +02:00
clemens a31a235422 Rechtstexte und B2C-Vertragsabläufe absichern 2026-08-22 14:31:56 +02:00
clemensandClaude Opus 5 d24ee9bf91 Betreiber-Zentralstelle, Mandanten-Design und schlankerer Einstieg
Funktions-Schalter je Mandant (app/features.php, tenant_features): der
Betreiber schaltet FAQ, Selbsteintrag, PDF, PayPal-Eingang, CSV-Import,
Mailversand, Jahresabschluss, Datenexport und eigenes Design pro Mandant
frei. Gesperrte Funktionen verschwinden aus Menue und Schaltflaechen, ihre
Seiten weisen Aufrufe und POSTs ab. Das Back-Office ist jetzt fuer
Platform-Admins im Menue verlinkt statt nur per URL erreichbar.

Eigenes Design je Mandant: Akzentfarbe und Logo in den Mandant-
Einstellungen, eingebettet ueber app/branding.php; das Logo liegt
geschuetzt in var/tenant_logos und wird nur ueber
tenant-logo-anzeigen.php an den eigenen Mandanten ausgeliefert.

Weniger Startinformationen: Startpaket neuer Mandanten auf zwei
Beispielfragen gekuerzt, Anleitung von ~1400 auf ~750 Woerter gestrafft
und um Abschnitte zu gesperrten Funktionen bereinigt.

Vorder-/Rueckseite erst bei mehr als 50 Personen (vorher schon ab 50).
Die Schwelle liegt jetzt gemeinsam in app/ledger.php und gilt auch fuer
die Vorder-/Rueckseiten-Auswahl beim Erfassen, wo sie bisher unabhaengig
von der Teamgroesse angeboten wurde.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 22:52:55 +02:00
clemensandClaude Opus 5 39f662d541 Kontofunktionen vor dem Go-Live und Landingpage-Kuerzung
Vier Luecken geschlossen, die im Alltag sofort aufgefallen waeren:

- Passwort aendern war im eingeloggten Zustand gar nicht moeglich; es gab
  nur den Reset per Mail-Link. saas_change_password() prueft das aktuelle
  Passwort, verlangt ein tatsaechlich anderes und erneuert danach die
  Session-ID. Formular in konto.php.
- mandant-auswahl.php war nur direkt nach dem Login erreichbar. Wer bei
  mehreren Mandanten Mitglied ist, musste sich zum Wechseln abmelden. Die
  Seite bedient jetzt beide Wege, die Mandantenpruefung bleibt unveraendert
  ueber saas_identity_for_user_tenant(). Menuepunkt ab zwei Mitgliedschaften.
- email_verified_at wurde nirgends geprueft, nur angezeigt - bei offener
  Selbstregistrierung konnte sich jemand mit fremder Adresse anmelden und
  alles nutzen. Erzwungen wird jetzt gezielt dort, wo eine Aktion nach
  aussen wirkt: Einladung, Info-Mail, Jahresabschluss. Der Login selbst
  bleibt bewusst frei, sonst waeren alle migrierten Bestandsnutzer mit
  NULL-Verifikation ausgesperrt. Zusaetzlich setzt der Passwort-Reset die
  Verifikation mit, weil der Mail-Link den Postfachzugriff nachweist -
  sonst blieben eingeladene Mitglieder dauerhaft unbestaetigt.
- Login landete auf konto.php statt auf dem Dashboard.

Landingpage: die gruene Vertrauenszeile auf "DSGVO-konform" gekuerzt, die
Eintraege zu Paragraf 19 UStG und "Bestehende Ablaeufe bleiben" entfernt.

Geprueft: neues scripts/check-konto-und-mandantenwechsel.php mit 18
Assertions gruen, Passwortformular zusaetzlich manuell inkl. CSRF (419).
Bestehende Suiten unveraendert gruen: HTTP-Smoke 34 Seiten, Rollenmatrix
55, Mandanten-Isolation 12, M3-Auth 9, M3-Settings 15.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-06 17:03:50 +02:00
clemensandClaude Sonnet 5 f60c0bb85e M8: Loesch-/Anonymisierungsprozess fuer Teilnehmer und Mandanten
Zwei getrennte Flows:

- Teilnehmer anonymisieren statt loeschen (ledger_anonymize_participant):
  Name/E-Mail/PayPal-Name werden durch einen Platzhalter ersetzt, das
  Mitglied deaktiviert und vom Login-Konto getrennt. Buchungshistorie
  bleibt fuer die Kassenfuehrung erhalten, konsistent mit dem
  Storno-statt-Delete-Prinzip. Default-Mandant spiegelt die
  Anonymisierung in kl_Mitarbeiter (Email dort NOT NULL UNIQUE, bekommt
  Platzhalter statt NULL). Inhaber kann nicht anonymisiert werden.
- Mandant vollstaendig loeschen (mandant-loeschen.php, nur Inhaber):
  erfordert exakte Eingabe des Kundenkuerzels, loescht die tenants-Zeile;
  alle tenant-scoped Tabellen kaskadieren per Fremdschluessel. users
  bleiben bestehen (koennen zu mehreren Mandanten gehoeren). Der
  migrierte Default-Mandant ist ausgenommen, da seine kl_Mitarbeiter-
  Historie sonst verwaisen wuerde.

Live getestet: Mitglied mit Buchungshistorie anonymisiert (Historie
blieb erhalten), Mandantenloeschung mit falscher/richtiger Bestaetigung
geprueft, vollstaendiger Cascade-Delete ueber alle tenant-scoped Tabellen
verifiziert, globale users-Zeile bleibt korrekt erhalten.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-15 20:17:57 +02:00
clemensandClaude Sonnet 5 f3045dbab9 M8: Datenexport pro Mandant
Neue Seite datenexport.php (Owner/Admin) laedt einen vollstaendigen
JSON-Export des eigenen Mandanten herunter: Stammdaten, Einstellungen,
Teilnehmer, Mitglieder mit Rolle, alle Ledger-Buchungen, Hinweise,
CSV-Importe, Mail-Versandlog und Admin-Protokoll. Passwort- und
Token-Hashes werden bewusst nicht exportiert; der Export selbst wird im
Audit-Log protokolliert. Link von konto.php aus.

Live getestet: eigens angelegter Test-Mandant, Export heruntergeladen,
Header und JSON-Struktur geprueft, keine Passwoerter im Export gefunden.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-15 20:10:30 +02:00
clemens 539117b409 Deutsche Umlaute in UI und Dokumentation korrigieren 2026-07-14 22:11:33 +02:00
clemens 8ab4a8a9bb M3 Passwort-Reset und E-Mail-Verifikation ergänzen
- Auth-Token-Tabelle mit gehashten Single-Use-Tokens einführen
- Passwort-Reset und E-Mail-Verifikation als Dev-Flow bauen
- Token-Flow-Test, Smoke-Abdeckung und M3-Dokumentation aktualisieren
2026-07-13 19:26:58 +02:00
clemens 19ff11c21a M3 Mandant-Einstellungen und Rollencheck ergänzen
- zentrale Owner/Admin-Rollenpruefung in SaaS-Auth ergaenzen
- Mandant-Einstellungen fuer Preise, PayPal und Basisdaten bauen
- Settings-Flow-Test, Navigation und M3-Dokumentation aktualisieren
2026-07-12 22:32:51 +02:00
clemens 5baf6542ce M3 Registrierung und Login-Grundlage ergänzen
- SaaS-Auth-Helper und PDO-Datenbankzugriff einführen
- Registrierung, Login, Logout und Kontoansicht ergänzen
- Auth-Migration, Flow-Check und Smoke-Abdeckung aktualisieren
2026-07-12 20:17:42 +02:00