alientimandClaude Sonnet 5 2d920f581f Eigenstaendige Lizenzen-Seite, entschachtelte Ticket-Ansicht, zeitlich begrenzter Kundenportal-Zugang (v1.2.2)
Reaktion auf Feedback: 'Tickets und Lizenzen je Kunden war sehr sehr
unintuitiv dargestellt... Kunde -> Ticket -> Lizenz aber alles auf extra
Seiten, im Menü einzeln anwählbar ohne diese riesen Verschachtelung.'

## Lizenzen als eigene, gleichberechtigte Ebene (neu: /licenses)

Bisher war eine Lizenz nur ueber Kunde -> gefilterte Tickets -> Ticket-
Detail -> eingebettete Historie-Tabelle erreichbar. Jetzt: Kunden,
Tickets UND Lizenzen sind drei eigene, direkt in der Navigation
erreichbare Seiten (Reihenfolge im Menü spiegelt bewusst die fachliche
Hierarchie). Kunden- und Ticket-Seite verlinken mit Filter (?customer_id=/
?ticket_id=) dorthin, statt Lizenzdaten selbst einzubetten.

Ticket-Detailseite dadurch massiv entschlackt: statt einer vollen
Lizenz-Historie-Tabelle nur noch eine kompakte 'Aktuelle Lizenz'-Zeile
mit Link auf die (ggf. gefilterte) Lizenzen-Seite fuer die volle Historie.

## Kundenportal: kein dauerhafter Link mehr, sondern zeitlich begrenzter Zugang

Vorheriger Ansatz (v1.2.0): ein dauerhafter, unbefristeter Token pro
Kunde, von Admins verteilt. Auf Nachfrage ('wie bekommt der Kunde seinen
Magic-Link, wenn er ihn verloren hat?') kam eine oeffentliche
'Zugang anfordern'-Seite dazu (E-Mail eingeben -> Link zugeschickt) --
und direkt im Anschluss die berechtigte Sicherheitsfrage, ob so ein
oeffentlich auf blossen Zuruf ausloesbarer Link nicht zeitlich begrenzt
sein sollte. Ergebnis: der dauerhafte Link wurde komplett entfernt.

Neuer, einziger Weg ins Kundenportal:
1. /portal/request -- Kunde gibt seine E-Mail ein (oeffentlich, keine
   Anmeldung noetig). Immer dieselbe generische Erfolgsmeldung,
   unabhaengig davon ob die Adresse bekannt ist (keine Enumeration).
2. Bei bekannter Adresse: ein frischer, einmalig nutzbarer Zugangs-Token
   (portal_access_tokens-Tabelle) wird per E-Mail verschickt, gueltig nur
   PORTAL_ACCESS_LINK_MINUTES (30) ab Anforderung.
3. /portal/access/<token> prueft Gueltigkeit + Einmalnutzung, markiert
   den Token als benutzt und setzt eine Session, die ihrerseits nach
   PORTAL_SESSION_MINUTES (60) automatisch ablaeuft.
4. /portal/me zeigt das eigentliche Portal (alle Tickets/Lizenzen,
   Kontaktdaten pflegen) -- ausschliesslich session-basiert erreichbar.

license_customers.portal_token bleibt in der DB bestehen (keine riskante
Schema-Ruecknahme), wird fuer die Zugriffsentscheidung aber nicht mehr
herangezogen -- alle Stellen, die vorher den dauerhaften Portal-Link
eingebettet haben (Ticket-Seite, Lizenz-per-E-Mail, Self-Service-Seite),
verweisen jetzt stattdessen auf /portal/request.

Verifiziert: bestehende Funktionstests erneut komplett durchlaufen (neue
Lizenzen-Seite, entschachtelte Ticket-Seite, entfernter dauerhafter
Zugang liefert 404), plus 11 neue Tests fuer den kompletten Magic-Link-
Fluss (Token-Erzeugung, Einmalnutzung, Ablehnen bei Wiederverwendung/
unbekanntem/abgelaufenem Token, Session bleibt nach Erstnutzung gueltig,
/portal/me ohne Session leitet zur Anfrage-Seite um) -- alle bestanden.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-23 17:03:55 +02:00

TESM-Lizenzserver

Master-Lizenzserver für TESM (TimEShepManager) — verwaltet Kunden und deren Lizenzen, statt Netzwerkgeräte. Ursprünglich als Teil des TESM-Hauptrepos gebaut (gleiche Codebasis: Login/Benutzer/Gruppen, LDAP/AD, NGINX- und Systemeinstellungen, Live-Log/Verlauf/Auditlog, Im-/Export-Grundgerüst, das komplette Rechtesystem) und in dieses eigene Repo ausgelagert.

Das Projekt ist ausschließlich für Linux ausgelegt (Zielsystem: eine Linux-VM, identisches Deployment-Muster wie TESM selbst).

Kernfunktionen

  • Kunden-/Lizenzübersicht als Dashboard (Typ, Module, Ablaufdatum, Aktivierungsstatus, letzter Heartbeat)
  • Lizenz-Ausstellung: Trial/Standard/Custom/Enterprise, frei wählbare Gültigkeitsdauer, bei Custom einzeln wählbare Module
  • Ed25519-signierte Lizenzdateien (siehe srv/tesm-license/licensing.py) — dieselbe Datei existiert byte-identisch im TESM-Repo, da Client (TESM) und Master (dieses Repo) exakt dasselbe Signier-/ Verifikationsprotokoll sprechen müssen
  • Online-Aktivierung/-Deaktivierung/-Heartbeat über eine schlanke JSON-API (/api/activate, /api/deactivate, /api/heartbeat, unauthentifiziert per Design — die Signatur der Anfrage selbst ist der Berechtigungsnachweis)
  • Offline-Fallback: dieselbe Aktivierungs-/Deaktivierungs-/Heartbeat- Logik auch als manuell kopierbarer Code für Kunden ohne Netzwerkzugriff auf den Lizenzserver
  • E-Mail-Versand ausgestellter Lizenzen per Microsoft Graph (Client-Credentials-Flow, keine zusätzliche Abhängigkeit) inkl. Einrichtungsanleitung und Verbindungstest in der GUI
  • Eigene Bootstrap-Lizenz des Masters selbst (create_master_license.py, rein lokal, kein externer Super-Master nötig)

Installation

sudo ./install.sh

Richtet System-Pakete, die Flask-App (systemd: tesm-license.service) sowie nginx als Reverse-Proxy unter /srv/tesm-license ein. Erkennt selbstständig, ob dort bereits eine Installation existiert, und aktualisiert sie entsprechend (In-Place bei unverändertem Datenbank-Schema, sonst mit automatischem Backup + Health-Check + Rückroll bei Fehlschlag — siehe Kommentarkopf in install.sh).

Nach der Erstinstallation:

sudo /srv/tesm-license/venv/bin/python3 /srv/tesm-license/create_admin.py
sudo /srv/tesm-license/venv/bin/python3 /srv/tesm-license/create_master_license.py

Update (von einem bereits installierten System aus)

sudo ./update.sh
# oder für eine bestimmte Version statt "latest":
TESM_RELEASE_TAG=v1.0.0 sudo -E ./update.sh

Lädt das aktuelle Gitea-Release herunter und übergibt an install.sh.

Zusammenspiel mit TESM

Eine TESM-Instanz aktiviert sich gegen genau einen Lizenzserver (master_endpoint, in der Lizenzdatei hinterlegt). Ein Protokoll, zwei Transportwege: online automatisch per HTTPS/JSON, offline als manuell auszutauschender Code — beide Seiten nutzen dieselben Funktionen aus licensing.py. Details zum kryptografischen Format und Ablauf siehe die Docstrings in srv/tesm-license/licensing.py bzw. dem identischen Modul im TESM-Repo.

S
Description
TESM-Lizenzserver -- Master-Lizenzserver fuer TESM (Kunden-/Lizenzverwaltung, Aktivierungs-/Heartbeat-API)
Readme
3.7 MiB
2026-09-03 16:18:55 +02:00
Languages
Python 62.4%
HTML 21.3%
Shell 7.7%
CSS 5.5%
JavaScript 3.1%