"""Browser session helpers shared by the new workbench and the legacy control UI. An empty ``ASR_WEB_PASSWORD`` closes the UI. Set ``ASR_WEB_ALLOW_ANON=1`` only for a local process that is not reachable from the network. """ from __future__ import annotations import hashlib import hmac import os from http import cookies from .config import get_setting def allow_anon() -> bool: return os.getenv("ASR_WEB_ALLOW_ANON", "").strip().lower() in { "1", "true", "yes", "on", } def password() -> str: env_pw = os.getenv("ASR_WEB_PASSWORD") if env_pw not in (None, ""): return env_pw return get_setting("web_password", "") def _secret() -> bytes: return (password() or os.getenv("ASR_AGENT_TOKEN", "") or "asr-web-unset").encode("utf-8") def session_token() -> str: return hmac.new(_secret(), b"asr-web-session-v1", hashlib.sha256).hexdigest() def csrf_token() -> str: return hmac.new(_secret(), b"asr-web-csrf-v1", hashlib.sha256).hexdigest() def cookie_matches(header: str) -> bool: if not password(): return False jar = cookies.SimpleCookie() try: jar.load(header or "") except Exception: return False morsel = jar.get("asr_session") return bool(morsel and hmac.compare_digest(morsel.value, session_token())) def csrf_matches(supplied: str) -> bool: if not supplied: return False return hmac.compare_digest(supplied, csrf_token())