Gegenstück zur bestehenden Verwaltung von der Gruppen-Seite aus
(/gruppen/{id}) - jetzt auch umgekehrt vom Gerät aus möglich, ohne
anode-Änderung (fetch_gruppen() aus routers/gruppen.py wiederverwendet,
Diff-Berechnung gegen bestehende add/remove-Endpunkte).
geraete_liste(): neue Spalte 'Gruppen' (aktuelle Mitgliedschaft),
Aktionen-Dropdown bekommt eine Checkbox-Liste aller Organisations-
Gruppen; POST /geraete/{id}/gruppen berechnet die Differenz zur
gewünschten Auswahl und ruft die bestehenden Endpunkte entsprechend auf.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Bugfix: auftragskatalog.html hatte Select/Deselect-Formular-Ziele fest
auf /geraete/... verdrahtet statt zurueck_url zu nutzen - Admin-Ansicht
eines fremden-Org-Geraets scheiterte dadurch mit 404. Jetzt dynamisch.
- Herkunfts-Anzeige ('via OE'/'via Gruppe') ist jetzt anklickbar, sofern
ein Sprungziel existiert (neue anreichere_mit_quelle_url()-Hilfsfunktion
in routers/geraete.py, von geraete.py und admin_geraete.py genutzt).
- Admin-Geräteliste (/admin/geraete) bekommt OE-Spalte + 'In OE
verschieben', analog zur Kundenportal-Liste.
- Neue, bewusst schlanke Admin-OE-Ansicht
(/admin/kunden/{org}/organisationseinheiten/{oe}/merkmale) - nur der
Merkmale-Editor als Sprungziel, kein OE-CRUD (bleibt laut ADR-0012
Kunden-Self-Service unter /struktur).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Kund:innen können jetzt eigene Gruppen selbst verwalten (/gruppen) statt
nur intern über /admin/kunden - reiner Kundenplattform-Zusatz, keine
Backend-Änderung nötig (anode-API war bereits organisationsgebunden und
generisch aufgebaut, siehe ADR-0012). Admin-Zugang bleibt zusätzlich
bestehen (Support/Onboarding), beide teilen sich dieselbe anode-API.
Neuer Router routers/gruppen.py (eng an struktur.py angelehnt, gleiches
Besitz-Validierungsmuster), Templates gruppen_liste/gruppe_detail
(Merkmale-Tristate-Editor + Geräte-Mitgliedschaft, wie
admin/gruppe_detail.html)/gruppe_umbenennen/gruppe_loeschen.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Kundenportal:
- Neue Seite /struktur - OE-Baum (rekursives Jinja-Makro), Anlegen/
Umbenennen/Löschen (Standard-OE 'Neue Geräte' geschützt), Merkmale-
Editor pro OE mit Tristate aktiv/inaktiv/nicht festgelegt.
- geraete_liste.html: neue Spalte 'OE', Aktionen-Dropdown um 'In OE
verschieben' erweitert.
- auftragskatalog.html: zeigt jetzt die Herkunft einer Einstellung an
(OE/Gruppe/manuell), sofern sie nicht vom Workspace-Default kommt.
Admin (/admin/kunden/{id}):
- Neue Sektion 'Gruppen' - Anlegen/Löschen, verlinkt auf neue
Detailseite (admin/gruppe_detail.html) mit Merkmale-Editor (wie OE)
und Geräte-Mitgliedschaft-Checkliste. Bewusst nur intern verwaltbar
in v1 (siehe Konfigurationsgruppen-Diskussion).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Hardware-Informationen, Installations-/Aktions-Log, De-/Reprovisionieren,
Gerät löschen (Soft Delete, mit Bestätigungsseite) - via Pico-Dropdown,
kein zusätzliches JS. Spricht die neuen anode-Endpunkte aus
provisioning-server an.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Neue Sektion auf der /admin/kunden/{id}-Detailseite: Liste bestehender
Bereitstellungsvorlagen der Organisation + Formular zum Anlegen einer
neuen (Workspace, Backend, Root-Dateisystem, Default/Diskverschluesselung/
Secure-Boot), ruft den neuen provisioning-server-Endpoint auf. Schliesst
die in Phase 5 dokumentierte Luecke: bisher hatte eine frische
Kundenorganisation keine Moeglichkeit, ueberhaupt eine Vorlage zu
bekommen, und damit eine leere Auswahl auf der
Installationsmedium-Selfservice-Seite.
Lokal end-to-end verifiziert (siehe provisioning-server-Commit).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Zwei neue Menuepunkte fuer eingeloggte Kunden (nicht der
organisationsuebergreifende /admin/-Bereich):
- "Organisation": Name bearbeiten (ruft Phase-3-PATCH auf
provisioning-server auf).
- "Installationsmedium": WLAN-SSID/-Passwort, Vorlagenwahl, Kontingent
und Gueltigkeitsdauer speichern, personalisierte Kunden-ISO per
Klick erstellen (Phase-4-Endpoints), Fortschritt/Status-Anzeige
(Meta-Refresh waehrend pending/running), Download + dd/Rufus-
Anleitung. Getrennte "aufladen"-Aktion erhoeht Kontingent/
Gueltigkeit der bestehenden Enrollment Session (neuer PATCH-
Endpoint), ohne eine neue ISO zu erzeugen - die bereits ausgeteilte
bleibt gueltig.
Neue Tabelle installationsmedium_konfiguration (Migration 0004, eigene
DB, kein Foreign Key auf provisioning-server-Ressourcen, siehe
ADR-0011) haelt SSID/verschluesselten PSK/Vorlage/Kontingent-Defaults
sowie die IDs der aktuell gueltigen Enrollment Session und des
zugehoerigen ISO-Baus.
WLAN-PSK wird Fernet-verschluesselt gespeichert (encryption.py, neuer
KUNDENPLATTFORM_ENCRYPTION_KEY) - echte Zugangsdaten, kein
Passwort-Hash-Fall. Download laeuft ueber einen Streaming-Proxy
(anode_stream() in anode_client.py) statt eines direkten Links, weil
der Browser kein KUNDENPLATTFORM_TOKEN besitzt.
Lokal end-to-end verifiziert (Wegwerf-Postgres fuer beide Services,
echter build_customer_iso.sh-Lauf ueber die Kundenplattform-UI):
Formular -> Enrollment Session + ISO-Bau -> Status-Polling ->
Download-Proxy liefert byte-identische, korrekt personalisierte Datei
(SSID/PSK/Aktivierungscode per xorriso-Extraktion gegengeprueft) ->
Aufladen erhoeht Kontingent/Gueltigkeit der bestehenden Session ohne
neuen Bau -> "neues Installationsmedium erstellen" erzeugt neue
Session + ISO, alte Session bleibt unangetastet nutzbar (alter
ISO-Bau wird laut Phase-4-Cleanup automatisch entfernt), leeres
PSK-Feld uebernimmt das zuvor gespeicherte PSK korrekt.
Organisation-Name-Aenderung ueber PATCH verifiziert. Unauthentifizierter
Zugriff auf beide neuen Routen leitet korrekt zu /login um.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Ersetzt die handgestrickte bcrypt+Session-Auth durch fastapi-users
(CookieTransport+JWTStrategy statt Starlette-Session, custom
psycopg3-async-Adapter statt SQLAlchemy). Bestehende bcrypt-Hashes
bleiben gültig und werden beim nächsten Login automatisch auf Argon2
angehoben (pwdlib-Default-PasswordHelper). ist_admin wird zu
is_superuser, damit fastapi-users' eingebaute Semantik direkt nutzbar
ist - require_admin/get_current_user bleiben als Wrapper unter
gleichem Namen, alle Router-Dateien bis auf geraete.py (dict- zu
attribut-Zugriff auf user.organization_id) unverändert.
Lokal end-to-end gegen eine Wegwerf-Postgres-Instanz (podman) verifiziert:
Migration, Bestandskonto-Login mit altem Passwort samt Argon2-Upgrade,
Admin-Kontoanlage über beide Aufrufstellen (create_user.py und
admin_kunden.py), 403 für Nicht-Admins, Logout.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
routers/admin_flows.py: pro Organisation unbestätigte Geräte anzeigen
und bestätigen (Bereitstellungsvorlage zuweisen), Enrollment Sessions
anlegen/widerrufen. Confirm-Aktion ruft direkt anodes bestehenden
resolve-Endpoint auf.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
routers/admin_technik.py: Merkmale (anlegen/bearbeiten inkl. Kategorie
und Katalogfähigkeit), Kategorien (anlegen), Workspaces (anlegen +
Zusammensetzung aus Merkmalen - Grundbaustein des Workspace-Creators),
Backends/Blueprints nur zur Anzeige.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
routers/admin_geraete.py mit echter Funktionalität: alle Geräte aller
Organisationen auflisten, pro Gerät der Auftragskatalog (Wiederverwendung
von auftragskatalog.html und der Logik aus routers/geraete.py, nur ohne
Org-Besitz-Check - Admins dürfen jedes Gerät direkt per ID öffnen).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
routers/admin_kunden.py mit echter Funktionalität: Organisationen
auflisten/anlegen, pro Organisation Aktivierungscodes erzeugen und
Kundenkonten anlegen (direkt in der Kundenplattform-eigenen
benutzer-Tabelle, kein anode-Aufruf nötig). Löst das bisherige manuelle
create_user.py-Skript für den Alltagsgebrauch ab.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
app.py auf APIRouter-Module umgestellt (db.py, templating.py,
anode_client.py, auth.py, routers/geraete.py + vier Admin-Router als
Platzhalter). benutzer.ist_admin (Migration 0002) + require_admin-
Dependency (403 ohne Admin-Flag). Admin-Nav-Link im Header nur für
Admin-Konten sichtbar. create_user.py um --admin-Flag erweitert.
Die vier Admin-Bereiche (Technik/Datenbank, Geräte, Flows, Kunden) sind
als Platzhalterseiten unter /admin/... verdrahtet und bekommen in den
nächsten Schritten echte Funktionalität.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>