feat: DB backend and API implemementation
This commit is contained in:
1 parent
39b891cd63
commit
a78e84515a
14 files changed
+955
-652
No files matched your search
@@ -60,6 +60,83 @@ Die genaue Contao-, PHP- und Template-Version der öffentlichen Seite ist nicht
|
||||
|
||||
Die Terminlogik liegt in `public/booking/booking.js` als browsernatives ES-Modul. Für die statische Perspektivwerk-Vorschau liegen identische Kopien unter `public/perspektivwerk/js/`.
|
||||
|
||||
## Datenbankgestützte Buchungsdemo
|
||||
|
||||
Die Buchungsdemo lädt ihre Termine aus MariaDB und speichert eine Anmeldung
|
||||
über `public/booking/api.php`. Die API wird unabhängig von Contao direkt durch
|
||||
Apache ausgeliefert, verwendet aber dieselbe `DATABASE_URL` wie Contao. Dadurch
|
||||
funktioniert sie aus der Vorschau `/perspektivwerk/` und aus dem Contao-
|
||||
HTML-Element gleichermaßen.
|
||||
|
||||
Vor dem ersten Aufruf müssen die externen Migrationen eingespielt werden:
|
||||
|
||||
```powershell
|
||||
.\scripts\Invoke-BookingMigrations.ps1
|
||||
```
|
||||
|
||||
`database/migrations/001_booking_schema.sql` ist produktionsgeeignet
|
||||
versioniert und idempotent. Sie enthält Tabellen für Termine und Anmeldungen
|
||||
sowie klar erkennbare Demo-Termine. Die API prüft Kapazitäten innerhalb einer
|
||||
Transaktion und sperrt den Termin dabei mit `SELECT … FOR UPDATE`; parallele
|
||||
Anmeldungen können dadurch die Kapazität nicht überschreiten.
|
||||
|
||||
Die Demo speichert eine gültige Anmeldung direkt als `confirmed`. Sie hat
|
||||
bewusst noch **keinen** Mailversand, kein Double-Opt-in, keine Erinnerungen,
|
||||
keinen ICS-Feed und keine Verwaltungsoberfläche. Die Anzeige benennt diesen
|
||||
Umstand ausdrücklich. Ein Produktiveinsatz erfordert außerdem die in den
|
||||
SOLL-Dokumenten genannten Entscheidungen zu Art. 13 DSGVO, Löschfristen,
|
||||
Mailbetrieb, Rollen/Berechtigungen und Missbrauchsschutz.
|
||||
|
||||
Der Browser erhält ein CSRF-Token per gleicher Sitzung; die API validiert alle
|
||||
Pflichtdaten serverseitig und begrenzt Anmeldungen pro Sitzung. Dies ist eine
|
||||
Demonstration der Schutzrichtung, ersetzt aber keine gesonderte
|
||||
Sicherheitsanalyse für den Produktivbetrieb.
|
||||
|
||||
### API verwenden
|
||||
|
||||
Die API ist unter `/booking/api.php` erreichbar und akzeptiert ausschließlich
|
||||
gleichartige Same-Origin-Anfragen. Sie liefert JSON und verwendet keine
|
||||
Zugangsdaten im Browser.
|
||||
|
||||
Termine eines Monats laden (`to` ist der erste Tag des Folgemonats):
|
||||
|
||||
```text
|
||||
GET /booking/api.php?project=perspektivwerk&from=2026-09-01&to=2026-10-01
|
||||
```
|
||||
|
||||
`project` ist entweder `perspektivwerk` oder `produktionsschule`. Der Zeitraum
|
||||
darf höchstens 93 Tage umfassen. Die Antwort enthält ein `csrfToken` und eine
|
||||
Liste `events`. Ein Event enthält unter anderem `id`, `title`, `startsAt`,
|
||||
`endsAt`, `capacity`, `availableCapacity`, `status` (`available` oder `full`),
|
||||
`format` (`vor_ort` oder `telefonisch`) und `introductionRequired`.
|
||||
|
||||
Eine Anmeldung wird per `POST` angelegt. Dazu muss dieselbe Browser-Sitzung wie
|
||||
beim `GET` verwendet und das erhaltene Token im Header
|
||||
`X-SUFW-Booking-CSRF` übertragen werden:
|
||||
|
||||
```http
|
||||
POST /booking/api.php
|
||||
Content-Type: application/json
|
||||
X-SUFW-Booking-CSRF: <csrfToken-aus-dem-GET>
|
||||
|
||||
{
|
||||
"project": "perspektivwerk",
|
||||
"eventId": "6c7f216b-2704-4c81-b17a-000000000001",
|
||||
"name": "Max Mustermann",
|
||||
"email": "max@example.org",
|
||||
"phone": "+49 351 123456",
|
||||
"privacyAccepted": true,
|
||||
"introductionAttended": false,
|
||||
"introductionDate": ""
|
||||
}
|
||||
```
|
||||
|
||||
Für ein PS-`Probearbeiten` mit `introductionRequired: true` müssen
|
||||
`introductionAttended` den Wert `true` und `introductionDate` ein gültiges
|
||||
Datum im Format `YYYY-MM-DD` enthalten. Bei Erfolg antwortet die Demo mit
|
||||
`201 Created`; bei einem inzwischen ausgebuchten oder doppelt gebuchten Termin
|
||||
mit `409 Conflict`; fehlerhafte Pflichtangaben erhalten `422`.
|
||||
|
||||
## Zwei Einbindungswege
|
||||
|
||||
Die Terminbuchungskomponente hat eine Vorschau auf einem Webseiten-Nachbau der Orginalseite:
|
||||
@@ -71,7 +148,10 @@ Die Terminbuchungskomponente hat eine Vorschau auf einem Webseiten-Nachbau der O
|
||||
|
||||
## Statische Buchungsvorschau in Contao einbinden
|
||||
|
||||
Die erste Komponente ist absichtlich datenbankfrei. Sie zeigt Test-Slots, rendert einen Monatskalender und unterscheidet freie von belegten Terminen. Ein Klick auf einen freien Slot öffnet eine modale Eingabemaske für Name, E-Mail, Telefon, Alter, Nachricht, Ansprechperson bei AfA/Jobcenter sowie die DSGVO-Einwilligung. Die Eingaben werden derzeit ausschließlich im Browser validiert und weder gespeichert noch versendet.
|
||||
Die Komponente lädt Termin- und Kapazitätsdaten über die beschriebene API. Ein
|
||||
Klick auf einen freien Termin öffnet eine modale Eingabemaske für Name,
|
||||
E-Mail-Adresse, Telefonnummer und die DSGVO-Kenntnisnahme; für Probearbeiten
|
||||
kommen Einführungsveranstaltung und Datum hinzu.
|
||||
|
||||
Die Komponente benötigt keinen TypeScript-Compiler und keinen Build-Schritt. Regressionstests ausführen:
|
||||
|
||||
@@ -93,7 +173,22 @@ Contao maskiert nicht freigegebene HTML-Tags auch im Inhaltselement **HTML**. Vo
|
||||
|
||||
Danach den Contao-Cache über **Systemwartung** leeren und das Inhaltselement erneut speichern. Keine globale Freigabe mit `*` verwenden. Wer ein HTML-Inhaltselement bearbeiten darf, kann mit dem freigegebenen `script`-Tag JavaScript auf der Website ausführen; diese Bearbeitungsrechte müssen daher auf vertrauenswürdige Backend-Nutzer beschränkt bleiben.
|
||||
|
||||
Die Beispieltermine stehen in `public/booking/booking.js`; `public/perspektivwerk/js/booking.js` ist die für den statischen Upload bestimmte Kopie. Ein Test stellt sicher, dass beide Dateien gleich bleiben. Der spätere serverseitige Endpunkt muss sie ersetzen; Datenbankzugänge oder SQL gehören niemals in das HTML oder das Browser-JavaScript.
|
||||
Die Termin- und Kapazitätsdaten kommen aus `/booking/api.php`; Datenbankzugänge
|
||||
oder SQL gehören niemals in das HTML oder das Browser-JavaScript.
|
||||
`public/perspektivwerk/js/booking.js` und die zugehörige CSS-Datei sind die für
|
||||
den statischen Upload bestimmte Kopie. Ein Test stellt sicher, dass beide
|
||||
Asset-Paare gleich bleiben. Nach Änderungen können sie lokal synchronisiert
|
||||
werden mit:
|
||||
|
||||
```powershell
|
||||
Copy-Item public\booking\booking.js public\perspektivwerk\js\booking.js -Force
|
||||
Copy-Item public\booking\booking.css public\perspektivwerk\js\booking.css -Force
|
||||
```
|
||||
|
||||
Der vorhandene SCP-Upload überträgt weiterhin nur die statische
|
||||
Perspektivwerk-Seite. Für einen externen Einsatz der Buchungsdemo müssen
|
||||
zusätzlich `/booking/api.php`, die Migrationen und die sichere
|
||||
`DATABASE_URL`-Konfiguration auf dem Zielserver bereitgestellt werden.
|
||||
|
||||
## Statische Perspektivwerk-Seite übertragen
|
||||
|
||||
|
||||
Reference in new issue
Block a user