From 795dcf7eebc88413db2650e2cdf3ac3aaf311890 Mon Sep 17 00:00:00 2001 From: Jeuner <62662523+Jeuners@users.noreply.github.com> Date: Fri, 28 Aug 2026 18:10:31 +0200 Subject: [PATCH] feat: mehrere Leitstand-Zugaenge gleichzeitig (LEITSTAND_ZUGAENGE) Bisher gab es genau ein Nutzer/Passwort-Paar (LEITSTAND_USER/LEITSTAND_PASS). Fuer einen zweiten Einsatzzweck/ein zweites Team am selben Leitstand (z.B. Notdienst neben Praxis) reicht das nicht. LEITSTAND_ZUGAENGE in der .env nimmt jetzt zusaetzliche "nutzer:passwort"-Paare (kommagetrennt) an - das bestehende LEITSTAND_USER/LEITSTAND_PASS bleibt als erstes Konto gueltig, config.leitstand_konten() buendelt alle. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01EbdWYnDtyMgxsq4eN1WnrQ --- .env.example | 3 +++ pipe/config.py | 16 ++++++++++++++++ pipe/server.py | 7 ++++--- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/.env.example b/.env.example index 60d7470..9e78dda 100644 --- a/.env.example +++ b/.env.example @@ -99,6 +99,9 @@ LEITSTAND_HOST=127.0.0.1 LEITSTAND_PORT=8088 LEITSTAND_USER=praxis LEITSTAND_PASS= +# Weitere Konten zusaetzlich zum obigen - kommagetrennt "nutzer:passwort", +# z.B. fuer ein zweites Team/einen zweiten Einsatzzweck neben "praxis". +LEITSTAND_ZUGAENGE= # Optional: geteiltes Geheimnis fuer signierte, 1h gueltige Testzugangslinks # (z.B. per Chatbot-Kommando ausgegeben). Leer = Feature aus. diff --git a/pipe/config.py b/pipe/config.py index 7c04eb1..4a26b3a 100644 --- a/pipe/config.py +++ b/pipe/config.py @@ -117,6 +117,22 @@ LEITSTAND_PORT = int(os.environ.get("LEITSTAND_PORT", "8088")) # auf den Seiten stehen Transkripte und Aufnahmen von Patienten. LEITSTAND_USER = os.environ.get("LEITSTAND_USER", "praxis") LEITSTAND_PASS = os.environ.get("LEITSTAND_PASS", "") +# Weitere Konten zusaetzlich zum obigen (z.B. ein eigenes Konto fuer den +# Notdienst neben dem Praxis-Konto) - kommagetrennt "nutzer:passwort", +# z.B. "notdienst:Berg,spaeter:nochwas". +LEITSTAND_ZUGAENGE = os.environ.get("LEITSTAND_ZUGAENGE", "") + + +def leitstand_konten() -> dict[str, str]: + """Alle gueltigen Leitstand-Logins als {nutzername: passwort}.""" + konten = {} + if LEITSTAND_PASS: + konten[LEITSTAND_USER] = LEITSTAND_PASS + for eintrag in LEITSTAND_ZUGAENGE.split(","): + nutzer, _, passwort = eintrag.strip().partition(":") + if nutzer and passwort: + konten[nutzer] = passwort + return konten # Geteiltes Geheimnis mit dilles-agent.php ("agent-one test"-Kommando auf # dillenberg.net) fuer signierte, 1h gueltige Testzugangslinks - siehe diff --git a/pipe/server.py b/pipe/server.py index bd90e15..5f4cb59 100644 --- a/pipe/server.py +++ b/pipe/server.py @@ -186,7 +186,8 @@ class Handler(BaseHTTPRequestHandler): """ self._zusatz_header: list[tuple[str, str]] = [] self._via_token = False # True nur bei Zugang per Testzugangs-Token, nicht Passwort - if not config.LEITSTAND_PASS: + konten = config.leitstand_konten() + if not konten: return True token = parse_qs(urlparse(self.path).query).get("zugang", [None])[0] @@ -209,8 +210,8 @@ class Handler(BaseHTTPRequestHandler): except Exception: return False # compare_digest: Vergleichsdauer verrät nichts über das Passwort. - return (hmac.compare_digest(nutzer, config.LEITSTAND_USER) - and hmac.compare_digest(wort, config.LEITSTAND_PASS)) + erwartet = konten.get(nutzer) + return erwartet is not None and hmac.compare_digest(wort, erwartet) def _anmeldung_verlangen(self) -> None: self.send_response(401)