"""Multi-user basic-auth list for the HF Space deployment. Four fixed login strings. Each password comes from a Space secret. The 'students' login keeps using the long-standing ME_CHAT_PASSWORD secret so the password already shared with the class continues to work. Used by deploy/hf-space/app.py. Importable from anywhere in scripts/lib so unit tests can exercise it without loading the Space's hyphen-pathed app.py. """ from __future__ import annotations import os from typing import List, Tuple # Fixed login order. The order is the order Gradio displays internally # but is otherwise irrelevant to behavior. _LOGIN_TO_ENV: List[Tuple[str, str]] = [ ("robert", "ME_CHAT_PASSWORD_ROBERT"), ("pino", "ME_CHAT_PASSWORD_PINO"), ("udayan", "ME_CHAT_PASSWORD_UDAYAN"), ("students", "ME_CHAT_PASSWORD"), ] class MissingPasswordError(RuntimeError): """Raised when a required ME_CHAT_PASSWORD_* secret is unset.""" def build_auth() -> List[Tuple[str, str]]: """Return the four (login, password) tuples for Gradio's auth=. Raises MissingPasswordError naming the first unset env var.""" pairs: List[Tuple[str, str]] = [] for login, env_var in _LOGIN_TO_ENV: password = os.environ.get(env_var) # Treat both unset and empty-string as missing — HF Space UI can # silently save a blank value, and Gradio basic auth with an empty # password is worse than a clear startup error. if not password: raise MissingPasswordError( f"required env var {env_var} (for login '{login}') is unset" ) pairs.append((login, password)) return pairs