Passwort vergessen: Konto aus dem QR-Code (ADR-0041, 25.10.2026)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
adminandClaude Opus 5.5 committed 2026-10-25 10:36:06 +01:00
1 parent da44fd1c6a
commit 2a734497ed
1 file changed
+15 -9
+15 -9
View File
@@ -6273,7 +6273,8 @@ def personalisierung_modus(device_id: str) -> str:
return "passwort" if konto_aktiv else "aus"
# Der Kiosk "Passwort vergessen?" weist sich mit Gerät und diesem Token aus.
# Der Kiosk "Passwort vergessen?" und seit 25.10.2026 der QR-Code am
# Anmeldebildschirm weisen sich mit Gerät und diesem Token aus.
# Abgeleitet statt gespeichert; lesen kann es jedes lokale Konto des Geräts,
# es erlaubt aber nur, dem Besitzer einen Link an seine eigene Adresse zu
# schicken (begrenzt, siehe VERGESSEN_*).
@@ -6296,7 +6297,7 @@ def email_maskieren(email: str | None) -> str:
return f"{lokal[:1]}•••@{domain}"
def _vergessen_konto(cur, device_id: str, token: str):
def _vergessen_konto(cur, device_id: str, token: str, anmeldename: str | None = None):
"""Das aktive persönliche Konto des Geräts, wenn das Kiosk-Token passt."""
erwartet = personalisierung_kiosk_token(device_id)
@@ -6309,25 +6310,26 @@ def _vergessen_konto(cur, device_id: str, token: str):
JOIN devices d ON d.id = p.device_id
JOIN organizations o ON o.id = p.organization_id
WHERE p.device_id::text = %s AND p.status = 'angelegt' AND NOT p.entfernen AND NOT p.gesperrt
AND (%s::text IS NULL OR p.anmeldename = %s)
ORDER BY p.angelegt_am DESC
LIMIT 1
""",
(str(device_id),),
(str(device_id), anmeldename or None, anmeldename or None),
)
return cur.fetchone()
def vergessen_pruefen(device_id: str, token: str) -> dict | None:
def vergessen_pruefen(device_id: str, token: str, anmeldename: str | None = None) -> dict | None:
with get_database_connection() as conn:
with conn.cursor() as cur:
row = _vergessen_konto(cur, device_id, token)
row = _vergessen_konto(cur, device_id, token, anmeldename)
if row is None:
return None
_pid, anmeldename, email, _mails, hostname, org_name = row
return {"anmeldename": anmeldename, "email_maskiert": email_maskieren(email), "hostname": hostname, "organisation": org_name}
def vergessen_anfordern(device_id: str, token: str):
def vergessen_anfordern(device_id: str, token: str, anmeldename: str | None = None):
"""
Erzeugt den Link für "Passwort vergessen?". Gibt (Ergebnis, Fehler)
zurück; das Ergebnis enthält die volle Adresse und das Token für die
@@ -6336,7 +6338,7 @@ def vergessen_anfordern(device_id: str, token: str):
with get_database_connection() as conn:
with conn.cursor() as cur:
row = _vergessen_konto(cur, device_id, token)
row = _vergessen_konto(cur, device_id, token, anmeldename)
if row is None:
return None, "Auf diesem Gerät ist kein persönliches Konto eingerichtet."
return _vergessen_link(cur, row)
@@ -6944,6 +6946,10 @@ class StandRequest(BaseModel):
class VergessenRequest(BaseModel):
device_id: str
token: str
# Seit dem QR-Code am Anmeldebildschirm (Ergänzung 25.10.2026) nennt der
# Link das Konto, dessen Anmeldung fehlschlug; ohne Angabe das zuletzt
# eingerichtete wie beim alten Kiosk.
anmeldename: str | None = None
class NeuesPasswortRequest(BaseModel):
@@ -7092,7 +7098,7 @@ def post_vergessen_pruefen(payload: VergessenRequest, authorization: str | None
if not require_service_token(authorization):
return {"success": False, "error": "unauthorized", "message": "Fehlendes oder ungültiges Service-Token."}
ergebnis = vergessen_pruefen(payload.device_id, payload.token)
ergebnis = vergessen_pruefen(payload.device_id, payload.token, payload.anmeldename)
if ergebnis is None:
return {"success": False, "error": "kein_konto", "message": "Auf diesem Gerät ist kein persönliches Konto eingerichtet."}
return {"success": True, **ergebnis}
@@ -7103,7 +7109,7 @@ def post_vergessen_anfordern(payload: VergessenRequest, authorization: str | Non
if not require_service_token(authorization):
return {"success": False, "error": "unauthorized", "message": "Fehlendes oder ungültiges Service-Token."}
ergebnis, fehler = vergessen_anfordern(payload.device_id, payload.token)
ergebnis, fehler = vergessen_anfordern(payload.device_id, payload.token, payload.anmeldename)
if ergebnis is None:
return {"success": False, "error": "abgelehnt", "message": fehler}
return {"success": True, **ergebnis}