Files
kundenplattform/optionen_felder.py

88 lines
5.5 KiB
Python

# Gemeinsame Feld-Definitionen für Merkmal-Optionen (ADR-0010), verwendet
# von geraete.py (Geräte-Ebene), struktur.py (OE-Ebene) und gruppen.py
# (Gruppen-Ebene) - bisher lag das nur lokal+dupliziert in geraete.py und
# kannte nur Checkboxen (die frühere Brave-Option "standardbrowser",
# abgelöst am 13.10.2026 durch den Standardbrowser je Workspace). Seit den
# AD/OIDC/Fileserver-Merkmalen (10.09.2026) gibt es auch Text- und
# Passwort-Felder - "type" steuert den HTML-Input-Typ und die
# Parsing-Logik in parse_optionen_form().
#
# Seit 26.10.2026 (Kiosk) gibt es auch "textarea", "url" und "number", und
# alle Felder außer Passwörtern sind mit dem aktuellen Wert vorausgefüllt
# (templates/_merkmal_optionen.html), auch bei aktivem Merkmal änderbar.
#
# Passwort-Felder werden nie mit ihrem aktuellen Wert vorausgefüllt (siehe
# Templates) und nur übernommen, wenn tatsächlich etwas eingegeben wurde -
# ein leer gelassenes Passwort-Feld beim Bearbeiten überschreibt also
# nicht versehentlich ein bereits gesetztes Passwort mit nichts.
OPTIONEN_FELDER = {
"ad-anbindung": [
{"key": "ad_domain", "label": "AD-Domäne (z.B. schule.local)", "type": "text"},
{"key": "ad_join_user", "label": "Beitritts-Benutzer (z.B. Administrator)", "type": "text"},
{"key": "ad_join_passwort", "label": "Beitritts-Passwort", "type": "password"},
],
# 15.10.2026 umgebaut zur gemeinsamen Ablage (ansible-content Rolle
# fileserver, platform-docs roadmap/org-ressourcen-konzept.md): eine
# SMB-Freigabe für alle Benutzer des Geräts, standardmäßig nur lesbar.
# Persönliche Freigaben laufen über Organisation > Ressourcen.
"fileserver": [
{"key": "fileserver_adresse", "label": "SMB-Server (Name oder IP)", "type": "text"},
{"key": "fileserver_freigabe", "label": "Freigabename", "type": "text"},
{"key": "fileserver_anzeigename", "label": "Name im Dateimanager (leer = „Gemeinsame Ablage“)", "type": "text"},
{"key": "fileserver_schreibzugriff", "label": "Alle Benutzer dürfen schreiben und löschen (sonst nur lesen; beim erneuten Speichern wieder setzen)", "type": "checkbox"},
{"key": "fileserver_user", "label": "Konto für alle Geräte gemeinsam (leer = Kerberos/AD-Anmeldung)", "type": "text"},
{"key": "fileserver_passwort", "label": "Passwort dieses Kontos (leer = unverändert)", "type": "password"},
],
"update-proxy": [
{"key": "proxy_adresse", "label": "Proxy-Gerät (Host oder IP, Port 3142)", "type": "text"},
],
# 14.10.2026: systemweites WLAN für alle Benutzer (Rolle org-wlan).
# Leeres Passwort = offenes WLAN; ein einmal gesetztes Passwort lässt
# sich hier nicht wieder leeren (leer = "nicht ändern", siehe oben).
"org-wlan": [
{"key": "wlan_ssid", "label": "WLAN-Name (SSID)", "type": "text"},
{"key": "wlan_passwort", "label": "WLAN-Passwort (leer = offenes WLAN)", "type": "password"},
],
# 15.10.2026: Veyon-Bauplan (platform-docs roadmap/veyon-schluessel-
# verteilung-diskussion-2026-10-14.md). Entscheidung: Lehrergerät per
# Checkbox an der Gruppe. Der Server wertet das Häkchen jeder aktiven
# Gruppe aus (veyon_ist_lehrer() in provisioning-server).
"veyon": [
{"key": "veyon_lehrer", "label": "Lehrergerät (Veyon Master mit Schlüssel und Raumliste)", "type": "checkbox"},
],
# 26.10.2026: Kiosk (platform-docs roadmap/kiosk.md, Rolle kiosk).
"kiosk": [
{"key": "kiosk_startseite", "label": "Startseite", "type": "url", "placeholder": "https://…"},
{"key": "kiosk_whitelist", "label": "Whitelist: erlaubte Domains, eine je Zeile, optional mit Pfad. Subdomains sind eingeschlossen, die Domain der Startseite ist immer erlaubt.",
"type": "textarea", "placeholder": "opac.beispiel.de\nschule.de/vertretungsplan"},
{"key": "kiosk_frei_surfen", "label": "Frei surfen (Whitelist aus)", "type": "checkbox"},
{"key": "kiosk_anzeigename", "label": "Name am Anmeldebildschirm (leer = „Kiosk“)", "type": "text"},
{"key": "kiosk_leerlauf_minuten", "label": "Nach so vielen Minuten ohne Eingabe mit der Startseite neu beginnen (leer = 10, 0 = nie)", "type": "number"},
{"key": "kiosk_ohne_leiste", "label": "Bedienleiste (Zurück, Startseite, Abmelden) ausblenden, z. B. für Anzeigetafeln", "type": "checkbox"},
{"key": "kiosk_bildschirm_an", "label": "Bildschirm schaltet nie ab", "type": "checkbox"},
{"key": "kiosk_autostart", "label": "Autostart: Kiosk startet ohne Anmeldung, der Anmeldebildschirm erscheint nicht mehr", "type": "checkbox"},
],
}
def parse_optionen_form(form, merkmal_key: str) -> dict:
"""Liest die zu einem Merkmal gehörenden optionen-Felder aus einem
FastAPI-Formular gemäß OPTIONEN_FELDER - Checkboxen werden zu bool,
Passwort-Felder nur übernommen, wenn tatsächlich etwas eingegeben
wurde (leer = "nicht ändern", siehe Modul-Kommentar oben), Text-Felder
immer (sie sind vorausgefüllt)."""
ergebnis = {}
for feld in OPTIONEN_FELDER.get(merkmal_key, []):
roh = form.get(f"optionen.{feld['key']}")
if feld["type"] == "checkbox":
ergebnis[feld["key"]] = roh == "on"
elif feld["type"] == "password":
if roh:
ergebnis[feld["key"]] = roh
elif roh is not None:
# Seit 26.10.2026 vorausgefüllt (_merkmal_optionen.html): leer
# heißt hier "entfernen", nicht "beibehalten".
ergebnis[feld["key"]] = roh.strip()
return ergebnis