6c048a9c30
backend/portal_auth.py: stdlib HMAC-signed session cookie carrying the access-
token id (re-validated against the DB each request, so revoke kills live
sessions), hash_token, resolve_token, and the get_current_client dependency
(raises PortalAuthError). SECRET_KEY env (insecure dev default + warning).
routers/portal.py: /portal/enter/{token} mints the cookie -> /portal; /logout;
/access; /portal home stub. main.py registers the router + a PortalAuthError
handler (HTML access page for pages, 401 JSON for /portal/api/*).
Portal shell templates (base, access_required, overview stub), branded dark.
Verified: cookie round-trip + tamper/garbage rejection, token resolution
(valid/bad), get_current_client (valid/no-cookie/revoked) — 8/8 against a temp DB.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
45 lines
1.8 KiB
HTML
45 lines
1.8 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en" class="h-full dark">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>{% block title %}Monitoring{% endblock %} · TMI</title>
|
|
|
|
<script src="https://cdn.tailwindcss.com"></script>
|
|
<script>
|
|
tailwind.config = {
|
|
darkMode: 'class',
|
|
theme: { extend: { colors: { seismo: {
|
|
orange: '#f48b1c', navy: '#142a66', burgundy: '#7d234d'
|
|
} } } }
|
|
}
|
|
</script>
|
|
<link rel="icon" type="image/png" sizes="32x32" href="/static/icons/favicon-32.png">
|
|
<meta name="theme-color" content="#142a66">
|
|
{% block head %}{% endblock %}
|
|
</head>
|
|
<body class="h-full bg-slate-900 text-gray-100 antialiased">
|
|
<header class="border-b border-slate-700/70 bg-slate-800/60 backdrop-blur">
|
|
<div class="max-w-5xl mx-auto px-4 py-3 flex items-center justify-between">
|
|
<a href="/portal" class="flex items-center gap-2 font-semibold">
|
|
<span class="inline-block w-2.5 h-2.5 rounded-full bg-seismo-orange"></span>
|
|
TMI Monitoring{% if client %} <span class="text-gray-500 font-normal">·</span>
|
|
<span class="text-seismo-orange">{{ client.name }}</span>{% endif %}
|
|
</a>
|
|
{% if client %}
|
|
<a href="/portal/logout" class="text-sm text-gray-400 hover:text-gray-200">Sign out</a>
|
|
{% endif %}
|
|
</div>
|
|
</header>
|
|
|
|
<main class="max-w-5xl mx-auto px-4 py-6">
|
|
{% block content %}{% endblock %}
|
|
</main>
|
|
|
|
<footer class="max-w-5xl mx-auto px-4 py-8 text-xs text-gray-600">
|
|
Read-only monitoring view. Data is provided as-is for informational purposes.
|
|
</footer>
|
|
{% block scripts %}{% endblock %}
|
|
</body>
|
|
</html>
|