1. Überblick
Eigenständige Webanwendung ohne externe Abhängigkeiten: PHP-Backend (api.php + lib/), Single-Page-Oberfläche (index.html), SQLite-Datenbank. Läuft auf Synology-NAS mit PHP 8.1+.
| Eigenschaft | Wert |
|---|---|
| PHP | ≥ 8.1 |
| Datenbank | SQLite (data/mgv.sqlite, WAL) |
| Externe Bibliotheken | keine |
| Version | 1.8.0 |
2. Architektur
api.php (JSON); diese nutzt die Module in lib/ und die SQLite-Datenbank.3. Dateien & Module
| Datei | Aufgabe |
|---|---|
api.php | Zentraler JSON-Endpunkt. |
index.html | Oberfläche. |
lib/core.php | DB, Schema, Migration, APP_VERSION. |
lib/auth.php | Anmeldung, Token, Rollen/Rechte. |
lib/docgen*.php | Dokumentations-Generator (Vorlagen, Archiv, Backup). |
selbsttest.php | Diagnose-Werkzeug. |
4. Installation (Synology)
pdo_sqlite, mbstring, zip).data/, backups/, uploads/, docs/.index.html aufrufen → Ersteinrichtung.5. Datenmodell
Wichtige Tabellen: mitglieder, garden, funktionen, orden, users, roles, user_roles, tokens, export_vorlagen, settings, audit.
6. Migrationen
Schema wird bei jedem DB-Zugriff über migrate() automatisch aktualisiert; fehlende Spalten idempotent ergänzt.
7. Anmeldung, Rollen & Token
Benutzername LOWER(username)=LOWER(?) (Schreibweise egal), Passwort exakt (bcrypt/argon2). API-Token mit Präfix mgvapi_, nur als SHA-256-Hash gespeichert, läuft nicht ab.
8. Schnittstelle zur Trainingsplanung
GET api.php?action=members.export&include_unconfirmed=0
Header: X-Api-Key: mgvapi_…
Liefert je Mitglied u.a. ref, Name, Garde, ist_schnupperer, betreuungsrelevant.
9. Selbstverwaltung & Portal-Anbindung
Seit 1.8.0 können Mitglieder ausgewählte eigene Daten über einen kontrollierten Schreibweg selbst pflegen. Architektur: Das FGM-Portal ist die Anlaufstelle für Mitglieder, die Mitgliederverwaltung bleibt Datenhalter (speichert, prüft, gibt frei).
| Bestandteil | Datei |
|---|---|
| Selbstverwaltungs-Logik | lib/selfservice.php |
| Selbstbedienungsseite | meine-daten.html (öffentlich, ohne Login) |
| Portal-Modul (separates Paket) | modules/meine-daten/portal.php |
Zugang & Signatur
Zwei Wege zur Auflösung eines Zugangs (selfservice_resolve_zugang()):
- HMAC-signierte Portal-Anfrage – identisch zur Portal-Spezifikation 1.3.1:
Signaturbasis
Time.Ref.Role.Want.Path, HMAC-SHA256, 120-Sekunden-Fenster, HeaderX-Portal-Time/Ref/Role/Want/Sig.Refhat die Formmgv:<mitglied_id>und bindet die Anfrage an genau ein Mitglied. - Slug + Code – Tabelle
self_access: merkbarer Slug (aus dem Namen abgeleitet) plus kurzer Zufallscode (nur als SHA-256-Hash gespeichert), mit Ablauf und optionaler Geburtsdatum-Prüfung.
selfservice_secret gesetzt ist (Einstellungen → Persönliche Zugänge → „Automatisch erzeugen"). Dieser Wert muss identisch im Portal-Modul (PORTAL_SECRET) und bei dessen Registrierung hinterlegt sein.Datenmodell (additiv)
| Tabelle | Zweck |
|---|---|
change_requests | Offene Änderungswünsche (Typ „aenderung"/„loeschung"), Freigabe-Workflow. |
change_log | Protokoll automatisch übernommener Änderungen. |
self_access | Zugang (Slug/Code) ↔ Mitglied. |
ss_mail_templates | Mail-Vorlagen der Benachrichtigung. |
Feldregeln
selfservice_feldregeln() liefert je Feld live (sofort in
mitglieder + change_log) oder freigabe (als
change_requests-Eintrag). Foto-Änderungen werden immer als Wartedatei
(pending_…) im Portrait-Verzeichnis abgelegt und erst bei Genehmigung
(selfservice_approve()) auf die endgültige Datei umgesetzt.
Wichtige Endpunkte
self.getData / self.saveData / self.requestDelete # Mitglied (Zugang per HMAC oder Slug+Code)
self.listChanges / self.approve / self.reject # Freigabe (eingeloggt, rechtegeschützt)
self.linkCreate / self.linkList / self.linkRevoke # Persönliche Zugänge verwalten
self.settings / self.saveSettings # Konfiguration (Secret, Feldregeln, Empfängerkreis)
self.saveTemplate / self.testMail / self.runDaily # Mail-Vorlagen & Versand
Benachrichtigung
Empfängerkreis als Vereinigung aus Rollen (alle zugehörigen Benutzer) und einzeln
gewählten Personen (selfservice_notify_recipients()), nur aktive Konten mit
E-Mail-Adresse. Versand sofort (bei Freigabe-relevanter Änderung), täglich gebündelt
(self.runDaily, für Cron geeignet) oder beides. Mail-Versand ist überall
konsequent mit try/catch abgesichert – ein SMTP-Fehler darf niemals einen Serverfehler
(HTTP 500) auslösen, sondern liefert eine sprechende Meldung.
Rechte
| Recht | Wirkung |
|---|---|
selfservice.verwalten | Zugänge, Feldregeln, Mail-Vorlagen, Sicherheitsschlüssel. |
selfservice.freigeben | Änderungen (Name/Foto) genehmigen/ablehnen. |
selfservice.loeschen.freigeben | Löschanträge genehmigen/ablehnen (separat von obigem Recht). |
selfservice.protokoll | Protokoll automatischer Änderungen einsehen. |
10. Sicherheit
- Passwörter/Token gehasht.
- Rechteprüfung je Endpunkt.
- Token mit
random_bytes. - HTTPS empfohlen;
data/,backups/,docs/nicht öffentlich.
11. Doku-Generator
Hilfe und Dokus werden von lib/docgen*.php aus Vorlagen erzeugt und übernehmen Theme-Farben, Vereinsname, Logo und Version aus den Einstellungen. Beim Update werden sie automatisch neu erzeugt. Jede Generierung schreibt zusätzlich einen Archivstand nach docs/archiv/<zeitstempel>_v<version>/. Rechte je Dokument: docs.<key>.generate/backup/delete.
12. Diagnose
selbsttest.php # Oberfläche mit Kacheln
selbsttest.php?format=json # JSON für den Tab
php e2e.php # CLI-Test
13. Fehlersuche
| Symptom | Lösung |
|---|---|
| HTTP 500 beim ersten Aufruf | Migration; Seite neu laden, Schreibrechte data/ prüfen. |
| Bild beim Update abgelehnt | Logo per FileStation in assets/ bzw. uploads/ legen. |
| Doku nicht generierbar | Schreibrechte für docs/ und den Anwendungsordner prüfen. |
| Selbstverwaltung: Portal-Zugriff abgelehnt | selfservice_secret in MV und Portal-Modul prüfen (muss identisch sein); Zeitabweichung der Server < 120s. |
| Testmail schlägt fehl | SMTP-Zugangsdaten unter „System & Updates" prüfen; Fehlermeldung nennt die genaue SMTP-Stufe. |