Codex on Andrea Mac mini
Add password gate for Phase I dashboard
1d244c9
Raw
History Blame Contribute Delete
4.86 kB
#!/usr/bin/env python3
"""Password gate for the private Phase I AAI dashboard."""
from __future__ import annotations
import base64
import hmac
import os
import time
import urllib.error
import urllib.request
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
USERNAME = os.environ.get("DASHBOARD_USERNAME", "richard")
PASSWORD = os.environ.get("DASHBOARD_PASSWORD", "")
HF_READ_TOKEN = os.environ.get("HF_PRIVATE_READ_TOKEN", "")
PRIVATE_DASHBOARD_URL = os.environ.get(
"PRIVATE_DASHBOARD_URL",
"https://huggingface.co/spaces/andreaparker/phase1-aai-source-coverage-dashboard/raw/main/index.html",
)
CACHE_TTL_SECONDS = int(os.environ.get("CACHE_TTL_SECONDS", "300"))
_cached_html: bytes | None = None
_cached_at = 0.0
def require_env() -> None:
missing = [
name
for name, value in {
"DASHBOARD_PASSWORD": PASSWORD,
"HF_PRIVATE_READ_TOKEN": HF_READ_TOKEN,
}.items()
if not value
]
if missing:
raise RuntimeError(f"Missing required environment variable(s): {', '.join(missing)}")
def fetch_dashboard() -> bytes:
global _cached_html, _cached_at
now = time.time()
if _cached_html and now - _cached_at < CACHE_TTL_SECONDS:
return _cached_html
req = urllib.request.Request(
PRIVATE_DASHBOARD_URL,
headers={"Authorization": f"Bearer {HF_READ_TOKEN}"},
)
with urllib.request.urlopen(req, timeout=45) as response:
html = response.read()
_cached_html = html
_cached_at = now
return html
def parse_basic_auth(header: str) -> tuple[str, str] | None:
prefix = "Basic "
if not header.startswith(prefix):
return None
try:
decoded = base64.b64decode(header[len(prefix) :], validate=True).decode("utf-8")
except Exception:
return None
username, sep, password = decoded.partition(":")
if not sep:
return None
return username, password
class Handler(BaseHTTPRequestHandler):
server_version = "Phase1DashboardGate/1.0"
def log_message(self, fmt: str, *args: object) -> None:
print(f"{self.address_string()} - {fmt % args}")
def is_authorized(self) -> bool:
parsed = parse_basic_auth(self.headers.get("Authorization", ""))
if not parsed:
return False
username, password = parsed
return hmac.compare_digest(username, USERNAME) and hmac.compare_digest(password, PASSWORD)
def send_login(self) -> None:
body = b"Authentication required.\n"
self.send_response(401)
self.send_header("WWW-Authenticate", 'Basic realm="Phase I AAI Dashboard"')
self.send_header("Content-Type", "text/plain; charset=utf-8")
self.send_header("Content-Length", str(len(body)))
self.end_headers()
self.wfile.write(body)
def do_GET(self) -> None:
if self.path == "/healthz":
body = b"ok\n"
self.send_response(200)
self.send_header("Content-Type", "text/plain; charset=utf-8")
self.send_header("Content-Length", str(len(body)))
self.end_headers()
self.wfile.write(body)
return
if self.path not in {"/", "/index.html"}:
self.send_response(302)
self.send_header("Location", "/")
self.end_headers()
return
if not self.is_authorized():
self.send_login()
return
try:
html = fetch_dashboard()
except urllib.error.HTTPError as exc:
body = f"Could not fetch private dashboard: HTTP {exc.code}\n".encode("utf-8")
self.send_response(502)
self.send_header("Content-Type", "text/plain; charset=utf-8")
self.send_header("Content-Length", str(len(body)))
self.end_headers()
self.wfile.write(body)
return
except Exception as exc:
body = f"Could not fetch private dashboard: {type(exc).__name__}\n".encode("utf-8")
self.send_response(502)
self.send_header("Content-Type", "text/plain; charset=utf-8")
self.send_header("Content-Length", str(len(body)))
self.end_headers()
self.wfile.write(body)
return
self.send_response(200)
self.send_header("Content-Type", "text/html; charset=utf-8")
self.send_header("Cache-Control", "private, max-age=60")
self.send_header("Content-Length", str(len(html)))
self.end_headers()
self.wfile.write(html)
def main() -> None:
require_env()
port = int(os.environ.get("PORT", "7860"))
server = ThreadingHTTPServer(("0.0.0.0", port), Handler)
print(f"Serving password-gated dashboard on port {port}")
server.serve_forever()
if __name__ == "__main__":
main()