Files
glucose-dashboard/auth.py
willemjan 7f4377329a
willemjan/glucose-dashboard/pipeline/head This commit looks good
Add CI test-coverage gate at 80%, backfill remaining logic-module gaps
pytest-cov + pyproject.toml [tool.coverage.*] measure reporting.py,
nightscout_client.py, data_processing.py, pdf_export.py, profile_data.py,
ui_common.py, and auth.py; app.py and pages/*.py are omitted (thin
Streamlit UI scripts, not meaningfully unit-testable without a running
Streamlit session — the handful of similarly UI-coupled functions left
in ui_common.py/auth.py are marked "# pragma: no cover" with the same
rationale, since the logic they call into is already fully tested).

The Gitea Actions test job now runs with --cov and fails the build
below 80%; the coverage XML is uploaded as a build artifact and fed
into the SonarQube scan (closing the gap flagged in
homelab-cicd-werkinstructie.md). Backfilled a few missing branches
(get_colors() theme fallback, secondary-y-axis overlay traces) to reach
98% on the measured modules — comfortable headroom above the 80% gate.

Builds on #29/#30/#31.
2026-09-05 22:52:29 +02:00

55 lines
1.9 KiB
Python

"""
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