""" Eenvoudige wachtwoord-gate voor de dashboardpagina's. Streamlit heeft geen ingebouwde authenticatie. Omdat dashboard-URL's straks gedeeld worden met het diabetesteam, staat hier een lichte sessie-gebaseerde wachtwoordcontrole voor — geen volwaardig account-systeem, wel een drempel tegen toevallig meekijken. Het wachtwoord zelf staat nooit in plaintext in de configuratie: net als bij het Nightscout API secret in nightscout_client.py wordt hier een hash vergeleken, niet de ruwe waarde. """ from __future__ import annotations import hashlib import os import streamlit as st def require_auth() -> None: # pragma: no cover """Blokkeer de pagina totdat het juiste wachtwoord is ingevoerd. Slaat de status op in st.session_state zodat dit maar één keer per browsersessie hoeft. Moet als eerste statement van elke pagina aangeroepen worden (app.py en elk bestand in pages/), omdat Streamlit iedere pagina als los script uitvoert. Pure Streamlit-widget-orkestratie (st.text_input/st.session_state/ st.rerun) — buiten scope van de unit-testdekking net als pages/*.py, zie pyproject.toml se coverage-omit-lijst. De veiligheidsrelevante logica zelf (verify_password()) is wel volledig getest. """ if st.session_state.get("authenticated"): return st.title("Glucose dashboard") password = st.text_input("Wachtwoord", type="password") if not password: st.stop() if verify_password(password, os.environ.get("DASHBOARD_PASSWORD_HASH", "")): st.session_state["authenticated"] = True st.rerun() st.error("Onjuist wachtwoord") st.stop() def verify_password(password: str, expected_hash: str) -> bool: """Vergelijk een ingevoerd wachtwoord met de geconfigureerde sha256-hash.""" if not expected_hash: return False return hashlib.sha256(password.encode("utf-8")).hexdigest() == expected_hash