5.1 KiB
EK-DOS-WEB
Büroanwendung der Elektro Krüger GmbH. Tickets, Angebote, Rechnungen, Kundenstamm, interne Aufgaben, Stundennachweise und Online-Käufe -- die Fachdaten liegen in n8n, die Benutzer in einer eigenen Datenbank.
Browser
│ HTTPS, Sitzungscookie (undurchsichtig)
▼
nginx ────────────────┬──────────────────────────────┐
│ statisch │ /api/ über Unix-Socket │
▼ ▼ │
React-Bündel php8.5-fpm ──► PostgreSQL (Benutzer, Rollen, Protokoll)
(nur Dateien) Slim 4 ──► Redis (Sitzungen, n8n-Cache)
──► n8n (alle Fachdaten)
Auf dem Server läuft kein Node. Die Oberfläche wird im Gitea-Lauf zu statischen Dateien kompiliert; ausgeliefert wird sie von nginx.
Verzeichnisse
| Ordner | Inhalt |
|---|---|
backend/ |
PHP 8.5, Slim 4. BFF-Sitzung, Benutzerverwaltung, n8n-Weiterleitung |
frontend/ |
React 19 + Vite. Baut nach frontend/dist/ |
deploy/nginx/ |
nginx-Site |
deploy/php-fpm/ |
php-fpm-Pool |
.gitea/workflows/ |
Bau- und Ausrollstrecke |
docs/ |
Betrieb und n8n-Schnittstelle |
legacy-nextjs/ |
Die abgelöste Next.js-Fassung. Kann nach dem Umstieg weg |
Wie es zusammenhängt
Die Anmeldung ist ein Backend-For-Frontend: der Browser hält nur eine zufällige Kennung im Cookie, alles Weitere -- Benutzer, Rolle, Rechte -- liegt in Redis. Das Cookie wächst dadurch nicht mit den Rechten mit, und eine Rechteänderung wirkt sofort, weil das Backend die Sitzung wegwerfen kann.
Die Rechte ersetzen die früheren Namensabfragen. Statt user === "Sascha"
gibt es Permission::OffersDelete, und Rollen bündeln diese Rechte:
| Rolle | darf zusätzlich |
|---|---|
admin |
alles, einschließlich Benutzerverwaltung |
inhaber |
Angebote/Kunden/Aufgaben löschen, Online-Käufe eintragen und löschen |
buero |
Online-Käufe abschließen, Rechnungen bearbeiten und versenden |
inhaber entspricht dem, was Sascha vorher durfte, buero dem von Svenja.
Die n8n-Daten kommen weiter live aus den Webhooks, aber durch einen kurzen Redis-Cache. Drei Dinge passieren dort: eine frische Antwort wird für 15--300 Sekunden wiederverwendet; läuft sie ab, während mehrere Ansichten gleichzeitig fragen, holt genau eine die Daten (Single-Flight); und ist n8n nicht erreichbar, wird die letzte bekannte Antwort ausgeliefert statt einer Fehlerseite. Jeder schreibende Aufruf verwirft seine Gruppe sofort.
Erste Einrichtung
cd backend
cp .env.example .env # DB, Redis, n8n-Geheimnisse eintragen
composer install --no-dev --optimize-autoloader
php bin/ekdos migrate
php bin/ekdos user:create # der erste Administrator
php bin/ekdos check # Postgres, Redis und n8n prüfen
Details zu nginx, php-fpm und dem Ausrollen: docs/DEPLOYMENT.md.
Lokal entwickeln
Zwei Fenster:
php -S 127.0.0.1:8080 -t backend/public
cd frontend && pnpm install && pnpm dev
Der Vite-Entwicklungsserver läuft auf http://127.0.0.1:5173 und reicht /api
an den PHP-Server weiter. Ein anderes Backend lässt sich über EKDOS_BACKEND
angeben. Postgres und Redis müssen erreichbar sein; n8n nur, wenn die
Fachansichten Daten zeigen sollen -- Anmeldung und Benutzerverwaltung laufen ohne.
Wartungs-CLI
php backend/bin/ekdos migrate # Schema fortschreiben
php backend/bin/ekdos user:create # Benutzer anlegen
php backend/bin/ekdos user:list # Benutzer auflisten
php backend/bin/ekdos user:password <name> # Passwort zurücksetzen
php backend/bin/ekdos cache:flush # n8n-Cache leeren
php backend/bin/ekdos check # Verbindungen prüfen
Was noch offen ist
frontend/src/views/Dashboard.tsx ist unverändert die eine große Komponente aus
der Next.js-Fassung (rund 4.700 Zeilen, 22 Ansichten in einer Zustandsmaschine).
Sie wurde bewusst kopiert statt neu geschrieben, damit an der Darstellung
nichts unbemerkt verrutscht. Herausgelöst sind bisher Anmeldung, Sitzung und die
neue Benutzeransicht.
Die Aufteilung in eine Ansicht pro Datei ist der nächste sinnvolle Schritt.
Der Weg dorthin ohne Umschreiben der Markup-Blöcke: den Zustand in einen
AppState-Kontext heben, und jede Ansichtsdatei oben genau die Namen
destrukturieren, die ihr JSX schon verwendet -- dann bleibt das Markup wörtlich
unverändert.