2026-10-12 21:08:05 +02:00
2026-08-06 08:29:51 +02:00
2026-10-15 14:06:46 +02:00

kundenplattform

Kunden-Web-UI für den Tuxflotte-Auftragskatalog — von provisioning-server (anode) bewusst getrennter Dienst, siehe ADR-0011.

Architektur

  • FastAPI + Jinja2 (serverseitig gerendert, kein Frontend-Build).
  • Eigene Postgres-Datenbank (benutzer-Tabelle: E-Mail/Passwort-Hash pro Organisation) — getrennt von provisioning-servers Datenbank, keine Cross-Database-Referenzen.
  • Spricht mit anode ausschließlich über dessen HTTP-API, authentifiziert mit einem eigenen Service-Token (TUXFLOTTE_KUNDENPLATTFORM_TOKEN, getrennt vom Admin-Token). Organisationszugehörigkeits-Prüfung (darf dieser Login auf dieses Gerät zugreifen?) passiert hier in der Anwendung, vor jedem Aufruf gegen anode — siehe find_device_in_organization() in app.py.

Setup (lokal)

python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
KUNDENPLATTFORM_DATABASE_URL=postgresql://... .venv/bin/psql ... -f migrations/0001_initial_schema.sql

Env-Variablen:

  • TUXFLOTTE_ANODE_URL (Default http://127.0.0.1:8080)
  • TUXFLOTTE_KUNDENPLATTFORM_TOKEN — muss mit dem gleichnamigen Wert in provisioning-servers /etc/tuxflotte/provisioning-server.env übereinstimmen
  • KUNDENPLATTFORM_DATABASE_URL
  • KUNDENPLATTFORM_SESSION_SECRET — beliebiger zufälliger String zum Signieren der Session-Cookie (z.B. openssl rand -base64 32)

Start: .venv/bin/uvicorn app:app --port 8081

Mailversand

Siehe ADR-0041. Aufrufer tragen Mails mit mail.einreihen() in die Tabelle mail_ausgang ein (Migration 0009). Eine Versandschleife im Dienst liefert sie per SMTP mit Anmeldung beim Mailanbieter der Domain ein und wiederholt bei Fehlern (nach 1, 5 und 15 Minuten, dann „fehlgeschlagen“). Der Mailtext wird nach dem Endzustand geleert, Einträge werden nach 90 Tagen gelöscht.

Env-Variablen:

  • KUNDENPLATTFORM_MAIL_MODUS — trockenlauf (Default, schreibt die Mail ins Journal statt sie zu verschicken) oder smtp

  • KUNDENPLATTFORM_MAIL_HOST, KUNDENPLATTFORM_MAIL_PORT (Default 587, STARTTLS)

  • KUNDENPLATTFORM_MAIL_BENUTZER — Anmeldename des Postfachs

  • KUNDENPLATTFORM_MAIL_ABSENDER — z.B. Tuxflotte <konto@tuxflotte.de>

  • KUNDENPLATTFORM_MAIL_ANTWORT_AN — optional

  • KUNDENPLATTFORM_OEFFENTLICHE_URL — Basis der Links in Mails (Default https://flotten-management.tuxflotte.de), bewusst nicht aus dem Host-Header abgeleitet

Erster Aufrufer ist der Passwort-Reset („Passwort vergessen?“ auf der Login-Seite, Routen in auth.py). Plattform-Admins (is_superuser) sind davon ausgenommen, für sie bleibt scripts/reset_password.py.

Das Passwort steht nicht in der Umgebung, sondern kommt als systemd-Credential mail_passwort (siehe kundenplattform.service); für Aufrufe außerhalb des Dienstes KUNDENPLATTFORM_MAIL_PASSWORT_DATEI.

Testmail (prüft Konfiguration und Zugangsdaten):

KUNDENPLATTFORM_DATABASE_URL=... KUNDENPLATTFORM_MAIL_MODUS=smtp ... \
    .venv/bin/python scripts/testmail.py --an jemand@example.org

Tests (brauchen eine Wegwerfdatenbank mit „test“ im Namen und eingespielter Migration 0009; SMTP ist gemockt):

KUNDENPLATTFORM_DATABASE_URL=postgresql://.../kundenplattform_test \
    .venv/bin/python -m unittest discover -s tests -v

Konto anlegen

Kein Self-Service in v1 (siehe ADR-0011) — Konten werden manuell angelegt:

KUNDENPLATTFORM_DATABASE_URL=... .venv/bin/python scripts/create_user.py \
    --organization-id <organization-uuid> \
    --email admin@schule-beispiel.de

Deploy (anode)

Wie bei provisioning-server, git-basiert statt scp:

git pull --ff-only
systemctl restart kundenplattform

Läuft unter einem eigenen, unprivilegierten System-User kundenplattform (nicht root — seit ADR-0027 auch provisioning-server, siehe dort) — siehe kundenplattform.service. Port 8081 (provisioning-server belegt 8080).

Öffentliche Erreichbarkeit über Pangolin ist nicht Teil dieses Repos — das ist ein separater Ops/DNS/Reverse-Proxy-Schritt.

S
Description
No description provided
Readme
2.3 MiB
0 Stars 1 Watchers 0 Forks
Languages
Python 52%
HTML 41.3%
JavaScript 5.5%
PLpgSQL 1.2%