Technische Dokumentation

Setup-Anleitung, Architektur und API-Referenz fuer die eforms.cloud-Plattform

Inhaltsverzeichnis

  1. Architektur & Tech-Stack
  2. Voraussetzungen
  3. Entwicklungsumgebung starten
  4. Backend-Zugang & Admin-User
  5. API-Referenz
  6. Authentifizierung (Sanctum)
  7. Zwei-Faktor-Authentifizierung (2FA)
  8. CAPTCHA-System
  9. Rollensystem & Berechtigungen
  10. Dynamisches Formularsystem
  11. Anonymisierung
  12. Mehrsprachigkeit (i18n)
  13. Wartungsmodus
  14. Datenbank
  15. Projektstruktur
  16. Frontend-Seiten & Komponenten
  17. Code-Qualitaet & Checks
  18. CI/CD-Pipeline
  19. Screenshot-Automatisierung
  20. Deployment (Produktion)
  21. Kalender-Integration (Google & Microsoft)

1. Architektur & Tech-Stack

Frontend Nuxt 3 (Vue 3)
TypeScript, Tailwind CSS
Backend (API) Laravel 13 (PHP 8.4)
Laravel Sanctum
Datenbank PostgreSQL 15
Docker Volume

Die Anwendung folgt einer klassischen Client-Server-Architektur. Das Nuxt-3-Frontend kommuniziert per REST-API mit dem Laravel-Backend. In Produktion sitzt ein Nginx-Reverse-Proxy davor, der SSL-Terminierung und Routing übernimmt.

2. Voraussetzungen

3. Entwicklungsumgebung starten

Repository klonen und starten

git clone https://github.com/calhelp/eforms-cloud.git
cd eforms-cloud
docker compose -f docker compose.dev.yml up --build

Das startet drei Container:

ServiceURL / PortBeschreibung
apihttp://localhost:8000Laravel Backend (API)
frontendhttp://localhost:3000Nuxt 3 Frontend
dblocalhost:5432PostgreSQL Datenbank

Datenbank-Migrationen ausführen

docker compose -f docker compose.dev.yml exec api php artisan migrate

Container stoppen

docker compose -f docker compose.dev.yml down

Zum vollständigen Zurücksetzen inkl. Datenbank-Volume:

docker compose -f docker compose.dev.yml down -v

4. Backend-Zugang & Admin-User

Admin-User per Seeder anlegen

Der AdminSeeder erstellt automatisch einen Standard-Admin-Account:

docker compose -f docker compose.dev.yml exec api php artisan db:seed --class=AdminSeeder
FeldWert
E-Mailadmin@eforms.cloud
Passwortpassword

Admin-Login im Frontend

Öffne http://localhost:3000/admin/login und melde dich mit den obigen Zugangsdaten an.

Eigenen Admin-User per Tinker anlegen

docker compose -f docker compose.dev.yml exec api php artisan tinker

# In Tinker:
User::create([
    'name' => 'Dein Name',
    'email' => 'deine@email.de',
    'password' => Hash::make('deinSicheresPasswort')
]);

Direkt in den Backend-Container

docker compose -f docker compose.dev.yml exec api bash

# Nützliche Artisan-Befehle:
php artisan migrate         # Migrationen ausführen
php artisan migrate:fresh   # DB zurücksetzen & neu migrieren
php artisan tinker           # Laravel REPL
php artisan route:list       # Alle API-Routen anzeigen

5. API-Referenz

Basis-URL (Entwicklung): http://localhost:8000/api

Öffentliche Endpunkte (kein Token nötig)

MethodeEndpunktBeschreibung
POST /api/meldungen Anonyme Meldung abgeben (mit CAPTCHA/Honeypot-Validierung)
POST /api/auth/login Admin-Login (gibt Bearer-Token zurück, optional CAPTCHA)
POST /api/auth/two-factor-challenge 2FA-Code oder Recovery-Code verifizieren
GET /api/maintenance/status Wartungsstatus abfragen
GET /api/captcha CAPTCHA-Challenge generieren (Rate-Limited)
GET /api/captcha/settings CAPTCHA-Einstellungen (aktiviert/deaktiviert)
GET /api/layout/settings Header-/Footer-/Seiten-Layout-Konfiguration
GET /api/geo/bundeslaender Liste aller Bundeslaender (OpenPLZ API, 24h Cache)
GET /api/geo/landkreise/{bundesland} Landkreise eines Bundeslandes
GET /api/app-name Anwendungsname abrufen (fuer Layout und Login-Seite)
GET /api/form-templates/{slug} Formular-Template mit aufgeloesten Bloecken (fuer Rendering)

Geschützte Endpunkte (Bearer-Token erforderlich)

MethodeEndpunktBeschreibung
POST /api/auth/logout Logout & Token widerrufen
GET /api/auth/me Aktuellen User abrufen (inkl. 2FA-Status)
PUT /api/auth/profile Name, E-Mail und Passwort aktualisieren
GET /api/meldungen Alle Meldungen auflisten (paginiert, Template-Filter)
GET /api/meldungen/{id} Einzelne Meldung anzeigen
GET /api/dashboard/stats Dashboard-Statistiken
GET /api/dashboard/templates Verfuegbare Templates fuer Dashboard-Auswahl
GET /api/dashboard/stats/{templateSlug} Dashboard-Statistiken fuer ein bestimmtes Template

Zwei-Faktor-Authentifizierung (Bearer-Token erforderlich)

MethodeEndpunktBeschreibung
POST /api/auth/two-factor/enable 2FA aktivieren (Secret + QR-Code + Recovery Codes)
POST /api/auth/two-factor/confirm 2FA-Einrichtung mit TOTP-Code bestaetigen
DELETE /api/auth/two-factor 2FA deaktivieren (Passwort erforderlich)
POST /api/auth/two-factor/recovery-codes Neue Recovery Codes generieren (8 Stueck, XXXX-XXXX)

Admin-Endpunkte (Admin-Rolle erforderlich)

MethodeEndpunktBeschreibung
GET /api/admin/users Alle Benutzer auflisten
POST /api/admin/users Neuen Benutzer erstellen (Name, E-Mail, Passwort, Rolle)
PUT /api/admin/users/{user} Benutzer aktualisieren (Rollen-Hierarchie beachten)
DELETE /api/admin/users/{user} Benutzer loeschen (Selbstloeschung verhindert)
POST /api/admin/maintenance Wartungsmodus umschalten
POST /api/admin/layout Layout-Einstellungen speichern (Header, Footer, Seiten)
POST /api/admin/layout/upload-logo Logo-Bild hochladen
GET /api/admin/captcha CAPTCHA-Einstellungen abrufen
POST /api/admin/captcha CAPTCHA-Einstellungen speichern (Schwierigkeit, Kontext, Rate Limit)
GET /api/admin/testdata/status Anzahl geseedeter Testdaten abfragen
POST /api/admin/testdata/prompt LLM-Prompt fuer realistische Testdaten generieren
POST /api/admin/testdata/import Testdaten aus JSON importieren
POST /api/admin/testdata/clear Alle Testmeldungen loeschen
GET /api/admin/meldungen/count Gesamtanzahl aller Meldungen
POST /api/admin/meldungen/clear-all Alle Meldungen unwiderruflich loeschen
POST /api/admin/meldungen/clear-by-template Meldungen eines bestimmten Templates loeschen
POST /api/admin/app-name Anwendungsname speichern
GET /api/admin/translations Alle Uebersetzungen abrufen
PUT /api/admin/translations Uebersetzung erstellen oder aktualisieren
DELETE /api/admin/translations/{id} Uebersetzung loeschen
GET /api/admin/translations/export Alle Uebersetzungen als JSON exportieren
POST /api/admin/translations/import Uebersetzungen aus JSON importieren
GET /api/admin/tokens Alle API-Tokens des Benutzers auflisten
POST /api/admin/tokens Neuen API-Token erstellen (optionales Ablaufdatum)
DELETE /api/admin/tokens/{id} API-Token widerrufen
GET /api/admin/bi/felder BI-Feld-Metadaten (fuer Endpunkt-Anzeige in Token-Verwaltung)

Developer-Endpunkte (Developer-Rolle erforderlich)

MethodeEndpunktBeschreibung
GET /api/admin/form-blocks Formular-Bloecke auflisten (Suche, Feldtyp-Filter, paginiert)
POST /api/admin/form-blocks Neuen Formular-Block erstellen
GET /api/admin/form-blocks/{id} Einzelnen Block abrufen
PUT /api/admin/form-blocks/{id} Block aktualisieren
DELETE /api/admin/form-blocks/{id} Block loeschen (Verwendung wird geprueft)
GET /api/admin/form-templates Alle Formular-Templates auflisten
POST /api/admin/form-templates Neues Template erstellen
GET /api/admin/form-templates/{id} Template mit Bloecken abrufen
PUT /api/admin/form-templates/{id} Template aktualisieren
DELETE /api/admin/form-templates/{id} Template loeschen
POST /api/admin/form-templates/{id}/duplicate Template duplizieren (inaktive Kopie)
GET /api/admin/form-templates/{id}/export Template als JSON-Bundle exportieren
POST /api/admin/form-templates/import Template aus JSON-Bundle importieren

BI-API Endpunkte (Bearer-Token mit bi:read Berechtigung)

MethodeEndpunktBeschreibung
GET /api/bi/felder Metadaten: verfuegbare Templates, abfragbare Felder, Filter
GET /api/bi/daten Alle Meldungen (paginiert, dynamisch filterbar)
GET /api/bi/stats/uebersicht Gesamtstatistiken mit Top-Werten
GET /api/bi/stats/zeitverlauf Monatliche Zeitreihe (konfigurierbarer Zeitraum)
GET /api/bi/stats/feld/{feldSlug} Statistik pro Feld (dynamisch, GROUP BY auf jedes abfragbare Feld)

Detaillierte Dokumentation: BI-API Dokumentation

6. Authentifizierung (Sanctum)

Die API nutzt Laravel Sanctum mit Token-basierter Authentifizierung.

Login (Token erhalten)

curl -X POST http://localhost:8000/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email": "admin@eforms.cloud", "password": "password"}'

Antwort:

{
  "token": "1|abc123...",
  "user": { "id": 1, "name": "Admin", "email": "admin@eforms.cloud" }
}

Geschützte Route aufrufen

curl http://localhost:8000/api/meldungen \
  -H "Authorization: Bearer 1|abc123..."

Logout

curl -X POST http://localhost:8000/api/auth/logout \
  -H "Authorization: Bearer 1|abc123..."

7. Zwei-Faktor-Authentifizierung (2FA)

Das System unterstuetzt TOTP-basierte Zwei-Faktor-Authentifizierung fuer alle Admin-Benutzer. Die Implementierung nutzt pragmarx/google2fa und bacon/bacon-qr-code.

Ablauf

  1. Aktivierung: POST /api/auth/two-factor/enable – Generiert Secret, QR-Code (SVG) und 8 Recovery Codes (Format: XXXX-XXXX)
  2. Bestaetigung: POST /api/auth/two-factor/confirm – Verifiziert TOTP-Code aus Authenticator-App
  3. Login mit 2FA: Login gibt two_factor: true zurueck → Client sendet Code an POST /api/auth/two-factor-challenge
  4. Recovery: Falls kein Zugriff auf Authenticator, kann ein Recovery Code statt TOTP-Code verwendet werden

Beispiel: 2FA aktivieren

curl -X POST http://localhost:8000/api/auth/two-factor/enable \
  -H "Authorization: Bearer 1|abc123..." \
  -H "Content-Type: application/json" \
  -d '{"password": "mein-passwort"}'

Antwort:

{
  "secret": "JBSWY3DPEHPK3PXP",
  "qr_code_svg": "<svg ...>",
  "recovery_codes": ["ABCD-EFGH", "IJKL-MNOP", ...]
}

Deaktivierung

curl -X DELETE http://localhost:8000/api/auth/two-factor \
  -H "Authorization: Bearer 1|abc123..." \
  -H "Content-Type: application/json" \
  -d '{"password": "mein-passwort"}'

8. CAPTCHA-System

Das System bietet einen mathematischen CAPTCHA-Schutz mit SVG-Rendering und visueller Rausch-Ueberlagerung.

Schwierigkeitsstufen

StufeBereichOperationenBeispiel
easy1–10Addition3 + 7 = ?
medium10–50Addition, Subtraktion34 - 12 = ?
hard2–99Addition, Subtraktion, Multiplikation8 * 7 = ?

Kontext-Steuerung

CAPTCHA kann separat fuer verschiedene Kontexte aktiviert werden:

Zusaetzlicher Schutz

Beispiel: CAPTCHA generieren

curl http://localhost:8000/api/captcha

Antwort:

{
  "token": "abc123...",
  "image_svg": "<svg ...>",
  "accessible_text": "Was ergibt 3 plus 7?"
}

9. Rollensystem & Berechtigungen

Das System verwendet vier Rollen mit hierarchischen Berechtigungen:

RolleZugriff
userDashboard, Meldungen ansehen, eigenes Profil
editorAlles von user + eingeschraenkter Admin-Zugang zu Templates
adminAlles von editor + Benutzerverwaltung, Einstellungen, Wartungsmodus, Tokens, Testdaten, Uebersetzungen
developerAlles von admin + Formular-Template-Editor, Block-Editor, Import/Export

Hierarchie-Regel: Admins koennen keine Developer bearbeiten oder loeschen. Benutzer koennen sich nicht selbst loeschen.

10. Dynamisches Formularsystem

Formulare werden ueber ein Template-Block-System definiert, das ohne Code-Aenderungen neue Formular-Layouts ermoeglicht.

Architektur

Unterstuetzte Feldtypen (18)

KategorieTypen
Auswahl (Einzel)select, radio-group
Auswahl (Mehrfach)multi-select, checkbox-group
Texttext, email, tel, url, textarea
Numerischnumber, range
Temporaldate, time
Sonstigetoggle, file-upload, hidden
Anzeigeheading, paragraph

Feld-Eigenschaften

Import / Export

Templates koennen als JSON-Bundle exportiert und importiert werden. Beim Import werden bestehende Bloecke wiederverwendet oder automatisch erstellt. So lassen sich Formulare zwischen verschiedenen eforms.cloud-Instanzen portieren.

11. Anonymisierung

Der AnonymisierungsService entfernt automatisch personenbezogene Daten aus Freitextfeldern bei der Einreichung einer Meldung. Welche Felder anonymisiert werden, wird dynamisch aus den FormBlock-Definitionen ermittelt.

Dynamische Felderkennung

Der Service liest zur Laufzeit alle Felder, die in den zugehoerigen FormBlocks mit anonymize: true markiert sind. Zusaetzlich werden alle otherDbField-Eintraege (Sonstiges-Freitextfelder) automatisch einbezogen. Neue Felder koennen im Block-Editor (/admin/blockeditor) per Checkbox "Anonymisieren" aktiviert werden — ohne Code-Aenderung.

Erkannte Muster

MusterErsetzung
Namen (Herr/Frau/Dr./Prof. + Name)[NAME ANONYMISIERT]
E-Mail-Adressen[E-MAIL ANONYMISIERT]
Telefonnummern (deutsche Formate)[TELEFON ANONYMISIERT]
Raum-/Stationsangaben (Zimmer/Station/Raum + Nr.)[RAUM ANONYMISIERT]
Datumsangaben (TT.MM.JJJJ)[DATUM ANONYMISIERT]

Zusätzlich werden technische Metadaten (ip, user_agent, session_id, debug_info) aus der Anfrage entfernt.

12. Mehrsprachigkeit (i18n)

eforms.cloud unterstuetzt vollstaendige Zweisprachigkeit (Deutsch und Englisch) auf allen Ebenen:

Frontend

Backend

API-Endpunkte (Admin-Rolle erforderlich)

MethodeEndpunktBeschreibung
GET /api/admin/translations Alle Uebersetzungen abrufen
PUT /api/admin/translations Uebersetzung erstellen oder aktualisieren
DELETE /api/admin/translations/{id} Uebersetzung loeschen
GET /api/admin/translations/export Alle Uebersetzungen als JSON exportieren
POST /api/admin/translations/import Uebersetzungen aus JSON importieren

13. Wartungsmodus

Das System verfügt über einen konfigurierbaren Wartungsmodus, der über die app_settings-Tabelle gesteuert wird.

Status abfragen (öffentlich)

curl http://localhost:8000/api/maintenance/status

Antwort:

{
  "enabled": true,
  "message": "Dieses Projekt dient als Demonstrationsversion...",
  "contact": ""
}

Wartungsmodus umschalten (Admin)

curl -X POST http://localhost:8000/api/admin/maintenance \
  -H "Authorization: Bearer 1|abc123..." \
  -H "Content-Type: application/json" \
  -d '{"enabled": true, "message": "Wartungsarbeiten bis 18 Uhr", "contact": "admin@example.de"}'

14. Datenbank

Entwicklungs-Zugangsdaten

ParameterWert
Hostlocalhost
Port5432
Datenbankeforms_db
Benutzereopel
Passwortdevpassword123

Direkte Verbindung per psql

docker compose -f docker compose.dev.yml exec db psql -U eopel eforms_db

Wichtige Tabellen

15. Projektstruktur

eforms.cloud/
├── backend/                        # Laravel 13 API
│   ├── app/
│   │   ├── Http/Controllers/Api/   # Auth, Meldung, Dashboard, Settings, User,
│   │   │                           # FormTemplate, FormBlock, BiStats, TwoFactor,
│   │   │                           # Captcha, ApiToken, Geo, AuditLog,
│   │   │                           # EmailNotification, Health, StripeWebhook,
│   │   │                           # Organization, OrganizationInvitation, Plan,
│   │   │                           # ScheduledReport, SsoAuth, SsoProvider,
│   │   │                           # Translation, UpdateController
│   │   ├── Http/Middleware/         # Admin, Developer, ValidateCaptcha, CheckPlanFeature,
│   │   │                           # DemoMode, EnsureTenant, SetLocale
│   │   ├── Models/                 # User, Submission, FormTemplate, FormBlock,
│   │   │                           # FormTemplateBlock, AppSetting, AuditLog,
│   │   │                           # EmailNotification, InstancePlan, Organization,
│   │   │                           # OrganizationInvitation, ScheduledReport,
│   │   │                           # ScheduledReportRun, SsoProvider, Translation, UpdateLog
│   │   └── Services/               # AnonymisierungsService, CaptchaService,
│   │                               # BiFieldRegistry, GeoService, TestDataSeederService,
│   │                               # AuditService, StripeService, PlanService,
│   │                               # SsoService, TenantContext, UpdateService
│   ├── database/
│   │   ├── migrations/             # Datenbank-Schema
│   │   └── seeders/                # AdminSeeder, FormBlockSeeder, FormTemplateSeeder,
│   │                               # EnglishTranslationSeeder, DatabaseSeeder
│   ├── tests/                      # PHPUnit-Tests
│   ├── routes/api.php              # API-Routen
│   ├── Dockerfile                  # Produktion
│   └── Dockerfile.dev              # Entwicklung
├── frontend/                       # Nuxt 3 Frontend
│   ├── pages/                      # 19 Seiten (Meldung, Admin, Login, …)
│   ├── components/                 # 19 Vue-Komponenten
│   ├── composables/                # 15 Composables (useApi, useAuth, useCaptcha, …)
│   ├── tests/                      # Vitest-Tests
│   ├── Dockerfile                  # Produktion
│   └── Dockerfile.dev              # Entwicklung
├── nginx/                          # Reverse-Proxy-Konfiguration
├── docs/                           # GitHub Pages Dokumentation
├── .github/workflows/
│   ├── deploy.yml                  # Build, Test & Deploy
│   ├── pages.yml                   # GitHub Pages Deploy
│   └── version-bump.yml            # Semantische Versionierung
├── docker-compose.yml              # Produktion
└── docker-compose.dev.yml          # Entwicklung

16. Frontend-Seiten & Komponenten

Seiten (19)

PfadBeschreibung
/Startseite
/meldung/:slugDynamische Formularseite per Template-Slug (z.B. /meldung/schnell, /meldung/ausfuehrlich)
/schnellRedirect auf /meldung/schnell
/ausfuehrlichRedirect auf /meldung/ausfuehrlich
/dankeBestätigungsseite nach Absenden
/maintenanceWartungsmodus-Anzeige
/admin/loginAdmin-Anmeldung (mit 2FA-Unterstuetzung)
/adminAdmin-Dashboard mit Statistiken
/admin/meldungenListe aller Meldungen
/admin/meldungen/:idDetailansicht einer Meldung
/admin/profilBenutzerprofil, Passwort & 2FA-Verwaltung
/admin/benutzerBenutzerverwaltung (Erstellen, Bearbeiten, Loeschen)
/admin/templatesFormular-Templates verwalten (CRUD, Import/Export, Duplizieren)
/admin/blockeditorFormular-Bloecke und Felder bearbeiten (Developer)
/admin/einstellungenAnwendungseinstellungen (Wartung, CAPTCHA, Layout, Testdaten)
/admin/seitenOeffentliche Seiten verwalten
/admin/tokensAPI-Token-Verwaltung
/admin/email-notificationsE-Mail-Benachrichtigungen verwalten
/admin/organizationOrganisationsverwaltung
/admin/ssoSSO-Konfiguration
/admin/updatesUpdate-Verwaltung

Wichtige Komponenten

Composables (15)

17. Code-Qualitaet & Checks

Die Code-Qualitaet wird durch ein mehrstufiges System aus lokalen Git-Hooks, Makefile-Befehlen und CI-Pipeline sichergestellt. Jede Aenderung durchlaeuft automatisch mehrere Pruefungen, bevor sie auf main gelangt.

Uebersicht der Checks

CheckToolPre-CommitPre-PushCI
PHP Code-StyleLaravel Pint
PHP Syntaxphp -l
PHP Statische AnalysePHPStan + Larastan
PHP Unit-TestsPHPUnit✓ (min. 40%)
JS/TS LintESLint
JS/TS FormatierungPrettier
TypeScript Typechecknuxi typecheck
JS Unit-TestsVitest

Git-Hooks

Die Git-Hooks werden mit bash scripts/setup-hooks.sh (bzw. make setup) aktiviert. Sie liegen unter .githooks/ und werden automatisch bei jedem Commit bzw. Push ausgefuehrt.

Pre-Commit Hook

Schnelle Checks, die bei jedem git commit laufen (unter 5 Sekunden):

Pre-Push Hook

Umfassendere Checks, die vor jedem git push laufen (30–120 Sekunden):

Falls ein Check fehlschlaegt, wird der Push abgelehnt. In Ausnahmefaellen: git push --no-verify (nicht empfohlen).

PHPStan (Statische Analyse)

PHPStan analysiert den PHP-Code statisch auf Typfehler, undefinierte Variablen und falsche Methodenaufrufe. Die Konfiguration:

# PHPStan ausfuehren
cd backend && vendor/bin/phpstan analyse

# Baseline aktualisieren (nach dem Fixen von Fehlern)
cd backend && vendor/bin/phpstan analyse --generate-baseline

Makefile-Befehle

Alle Checks koennen auch manuell ueber das Makefile ausgefuehrt werden:

BefehlBeschreibung
make testBackend- und Frontend-Tests ausfuehren
make test-backendPHPUnit-Tests
make test-frontendVitest-Tests
make lintLaravel Pint (PHP Code-Style pruefen)
make lint-frontendESLint + Prettier (Frontend pruefen)
make formatLaravel Pint (PHP automatisch formatieren)
make phpstanPHPStan statische Analyse
make typecheckTypeScript Typecheck (nuxi typecheck)
make check-allAlle Checks auf einmal ausfuehren

Claude-Integration

Bei der Entwicklung mit Claude Code (.claude/settings.json) werden Pint, ESLint und Prettier automatisch vor jedem Commit ausgefuehrt und Aenderungen gestaged.

18. CI/CD-Pipeline

Die CI/CD-Pipeline ist in drei GitHub Actions Workflows aufgeteilt:

Build, Test & Deploy (deploy.yml)

Wird bei jedem Push und Pull Request auf main ausgeführt:

SchrittToolBeschreibung
PHP Code-StyleLaravel PintCode-Formatierung prüfen
PHP Statische AnalysePHPStan + LarastanTypfehler und Bugs erkennen (Level 5)
PHP Syntaxphp -lSyntax-Check aller PHP-Dateien
Config-CheckArtisanLaravel-Konfiguration und Routen validieren
MigrationenArtisanDatenbank-Schema gegen PostgreSQL 15 testen
Backend-TestsPHPUnitTests mit min. 40% Code-Coverage
Frontend-Buildnpm run buildTypeScript-Kompilierung prüfen
Frontend-LintESLintCode-Qualität prüfen
Frontend-FormatierungPrettierCode-Formatierung prüfen
TypeScript Typechecknuxi typecheckTypeScript-Typen prüfen
Frontend-TestsVitestUnit-Tests ausführen

Bei erfolgreichem Merge auf main wird automatisch auf den Produktionsserver deployed.

GitHub Pages (pages.yml)

Automatisches Deployment der docs/-Inhalte bei Änderungen auf main.

Versionierung (version-bump.yml)

Automatische semantische Versionierung nach PR-Merge basierend auf Labels:

19. Screenshot-Automatisierung

Automatisierte Screenshots der Anwendung werden mit Playwright erstellt und in docs/assets/screenshots/ abgelegt, wo sie direkt in der Dokumentation referenziert werden können.

Funktionsweise

Das System liegt im Verzeichnis screenshots/ und ist als eigenständiges Node.js-Projekt aufgebaut. Playwright steuert einen Chromium-Browser, meldet sich an der Anwendung an, navigiert zu den relevanten Seiten und erstellt PNG-Screenshots.

Verzeichnisstruktur

screenshots/
  playwright.config.ts          # Projekte, Viewports, Auth
  package.json                  # Playwright als Dependency
  .env.example                  # Credential-Template (nur für lokale Nutzung)
  lib/helpers.ts                # Shared Utilities
  scripts/
    eforms/
      login.setup.ts            # Auth-Flow
      dashboard.spec.ts         # Screenshot-Scripts
      formulare.spec.ts
      admin.spec.ts
    calserver/                  # Placeholder
    edocs/                      # Placeholder
    quizrace/                   # Placeholder
docs/assets/screenshots/        # Zielordner (wird committet)
  eforms/
  calserver/
  edocs/
  quizrace/

GitHub Actions Workflow

Der Workflow .github/workflows/screenshots.yml wird automatisch jeden Montag um 6:00 UTC ausgeführt oder kann manuell gestartet werden.

ParameterOptionenStandard
Toolall, eforms, calserver, edocs, quizraceall
Viewportdesktop (1280×800), full-hd (1920×1080), tablet (768×1024)desktop

Geänderte Screenshots werden automatisch committet und gepusht.

Erforderliche GitHub Secrets

Die Credentials müssen im Repository unter Settings → Secrets and variables → Actions konfiguriert werden:

SecretBeschreibungBeispiel
EFORMS_URLURL der eforms-Instanzhttps://demo.eforms.cloud
EFORMS_USERE-Mail des Admin-Accountsadmin@example.de
EFORMS_PASSPasswort des Admin-Accounts
CALSERVER_URLURL der calServer-Instanzhttps://demo.calserver.com
CALSERVER_USERBenutzername calServer
CALSERVER_PASSPasswort calServer
EDOCS_URLURL der eDocs-Instanzhttps://calhelp.edocs.cloud
EDOCS_USERE-Mail eDocs
EDOCS_PASSPasswort eDocs
QUIZRACE_URLURL der QuizRace-Instanzhttps://demo.quizrace.app
QUIZRACE_USERE-Mail QuizRace
QUIZRACE_PASSPasswort QuizRace

Hinweis: Nur die Secrets der Tools konfigurieren, die tatsächlich verwendet werden. Fehlende Credentials führen dazu, dass das jeweilige Login-Setup mit einer Fehlermeldung abbricht — andere Tools sind davon nicht betroffen.

Screenshots in der Dokumentation verwenden

Die erzeugten Bilder liegen unter docs/assets/screenshots/<tool>/ und können direkt referenziert werden:

<img src="assets/screenshots/eforms/dashboard-uebersicht.png" alt="Dashboard">

Neues Screenshot-Script hinzufügen

Eine neue .spec.ts-Datei im passenden Tool-Ordner anlegen. Jeder test()-Block erzeugt einen Screenshot:

import { test } from '@playwright/test';
import { prepareCleanState, hideVolatileElements, waitForIdle } from '../../lib/helpers';

test('neue-seite', async ({ page }) => {
  await page.goto('/admin/neue-seite');
  await prepareCleanState(page);
  await hideVolatileElements(page);
  await waitForIdle(page);

  await page.screenshot({
    path: 'docs/assets/screenshots/eforms/neue-seite.png',
  });
});

20. Deployment (Produktion)

Das Produktions-Deployment nutzt docker compose.yml mit Nginx, SSL via Let's Encrypt und automatischer Zertifikatserneuerung.

Schritte

  1. .env-Datei im Root erstellen (basierend auf .env.example)
  2. Sichere Werte für APP_KEY, DB_PASSWORD und Domain setzen
  3. docker compose up -d --build ausführen
  4. Der docker-entrypoint.sh führt automatisch Migrationen aus

Wichtige Umgebungsvariablen (.env)

VariableBeschreibung
APP_KEYLaravel-Verschlüsselungsschlüssel
DB_PASSWORDPostgreSQL-Passwort
SANCTUM_STATEFUL_DOMAINSFrontend-Domain(s)
APP_URLÖffentliche Backend-URL

21. Kalender-Integration (Google & Microsoft)

eforms.cloud unterstuetzt die Synchronisation von Terminen mit externen Kalendern (Google Calendar, Microsoft 365/Outlook und CalDAV). Die Integration erfolgt ueber OAuth 2.0 — Admins verbinden ihren Kalender mit einem Klick, ohne selbst OAuth-Credentials konfigurieren zu muessen.

Voraussetzungen fuer den Systembetreiber

Der Betreiber der eforms.cloud-Instanz muss einmalig eine OAuth-App bei Google und/oder Microsoft registrieren und die Credentials in der .env-Datei hinterlegen. Danach funktioniert die Kalender-Verbindung fuer alle Admins und Mandanten automatisch.

VariableBeschreibung
GOOGLE_CALENDAR_CLIENT_IDOAuth Client-ID aus der Google Cloud Console
GOOGLE_CALENDAR_CLIENT_SECRETOAuth Client-Secret aus der Google Cloud Console
MICROSOFT_CALENDAR_CLIENT_IDApplication (Client) ID aus dem Azure Portal
MICROSOFT_CALENDAR_CLIENT_SECRETClient Secret aus dem Azure Portal
MICROSOFT_CALENDAR_TENANT_IDTenant-ID (Standard: common fuer Multi-Tenant)

Hinweis: Die Redirect-URI wird automatisch aus APP_URL abgeleitet (z.B. https://ihre-instanz.eforms.cloud/admin/calendars/google-callback). Eine manuelle Konfiguration ist nicht noetig.

Google Calendar OAuth-App einrichten

  1. Oeffnen Sie die Google Cloud Console (console.cloud.google.com)
  2. Erstellen Sie ein neues Projekt oder waehlen Sie ein bestehendes aus
  3. Navigieren Sie zu APIs & Dienste > Bibliothek und aktivieren Sie die Google Calendar API
  4. Navigieren Sie zu APIs & Dienste > Anmeldedaten und erstellen Sie eine OAuth 2.0-Client-ID (Typ: Webanwendung)
  5. Fuegen Sie als Autorisierte Weiterleitungs-URI hinzu: https://[IHRE-DOMAIN]/admin/calendars/google-callback
  6. Kopieren Sie Client-ID und Client-Secret in die .env-Datei
  7. Konfigurieren Sie den OAuth-Zustimmungsbildschirm unter APIs & Dienste > OAuth-Zustimmungsbildschirm:
    • App-Name und Support-E-Mail angeben
    • Unter Testnutzer die E-Mail-Adressen hinzufuegen, die sich verbinden sollen (im Testmodus)
  8. Fuer den produktiven Einsatz: Klicken Sie auf App veroeffentlichen, damit alle Nutzer sich verbinden koennen. Im Testmodus koennen nur die eingetragenen Testnutzer zugreifen.

Microsoft 365 / Outlook OAuth-App einrichten

  1. Oeffnen Sie das Azure Portal (portal.azure.com) und navigieren Sie zu App-Registrierungen
  2. Erstellen Sie eine neue App-Registrierung (Name frei waehlbar, z.B. "eforms.cloud Kalender")
  3. Waehlen Sie unter Unterstuetzte Kontotypen die Option Konten in einem beliebigen Organisationsverzeichnis und persoenliche Microsoft-Konten
  4. Fuegen Sie unter Authentifizierung > Plattformkonfigurationen > Web die Redirect-URI hinzu: https://[IHRE-DOMAIN]/admin/calendars/microsoft-callback
  5. Erstellen Sie unter Zertifikate & Geheimnisse ein neues Client Secret
  6. Kopieren Sie folgende Werte in die .env-Datei:
    • Anwendungs-ID (Client-ID) — von der Uebersichtsseite
    • Client Secret — soeben erstellt
    • Verzeichnis-ID (Tenant-ID) — oder common fuer mandantenuebergreifenden Zugriff

Kalender-Verbindung herstellen (Admin)

Sobald der Systembetreiber die OAuth-Credentials konfiguriert hat, koennen Admins ihre Kalender verbinden:

  1. Navigieren Sie zu Admin > Kalender-Verbindungen (/admin/calendars)
  2. Klicken Sie auf Verbindung hinzufuegen
  3. Vergeben Sie einen Namen (z.B. "Praxis-Kalender")
  4. Waehlen Sie den Anbieter (Google Calendar, Microsoft 365 oder CalDAV)
  5. Klicken Sie auf Verbinden — Sie werden zur Autorisierungsseite des Anbieters weitergeleitet
  6. Nach erfolgreicher Autorisierung werden Sie zurueckgeleitet und koennen einen Kalender auswaehlen

DSGVO-Konformitaet

Die Kalender-Synchronisation ist DSGVO-konform: Es werden keine personenbezogenen Daten in den externen Kalender geschrieben. Stattdessen wird lediglich ein neutraler Eintrag "Terminbuchung" als Platzhalter eingetragen. Fuer die Verfuegbarkeitspruefung wird die FreeBusy-API verwendet, die keine Eventdetails preisgibt.