Files
alembic/app/templates/base.html
T
andrew 2c86d7973f P2 minor set: password off argv, configurable share gate, POST logout, log path check
- Navidrome password is now passed to curl via stdin (--data-urlencode "p@-")
  in navidrome-scan.sh and pipeline-status.sh, so it no longer appears in
  ps/proc. Verified the query sent is identical and a live scan still triggers.
- MIN_ARTIST_DIRS (the share-health gate) is now a setting, threaded through to
  the pipeline env, so a user with a small library can lower it instead of the
  scan/sync being permanently blocked by the hardcoded 500.
- /auth/logout is now POST-only (with a nav form + aria-label), so a drive-by
  GET can't log the user out; enforced allowed_email already landed separately.
- view_log now confirms the run's log_path resolves under the logs dir before
  serving it (defense in depth).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-10 15:50:06 -06:00

67 lines
3.2 KiB
HTML

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{% block title %}alembic{% endblock %}</title>
<link rel="icon" type="image/svg+xml" href="/static/icon.svg">
<link rel="icon" type="image/png" sizes="16x16" href="/static/favicon-16.png">
<link rel="icon" type="image/png" sizes="32x32" href="/static/favicon-32.png">
<link rel="icon" type="image/png" sizes="48x48" href="/static/favicon-48.png">
<link rel="apple-touch-icon" href="/static/apple-touch-icon.png">
<link rel="manifest" href="/static/site.webmanifest">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@500;600;700&family=Manrope:wght@400;500;600;700;800&display=swap" rel="stylesheet">
<link rel="stylesheet" href="/static/style.css">
<script src="/static/htmx.min.js"></script>
<script src="/static/alpine.min.js" defer></script>
</head>
<body>
<div class="ambient-blob one"></div>
<div class="ambient-blob two"></div>
<div class="ambient-blob three"></div>
<header class="topbar">
<div class="topbar-inner">
<a class="brand" href="/">
<svg width="22" height="22" viewBox="0 0 24 24">
<defs>
<linearGradient id="brandGrad" x1="0" y1="0" x2="24" y2="24">
<stop offset="0%" stop-color="#7dd3fc"/>
<stop offset="50%" stop-color="#a78bfa"/>
<stop offset="100%" stop-color="#f9a8d4"/>
</linearGradient>
</defs>
<path fill="url(#brandGrad)" d="M9 2.5h6v5.2l4.3 8.6a2.6 2.6 0 0 1-2.33 3.76H7.03A2.6 2.6 0 0 1 4.7 16.3L9 7.7V2.5z"/>
<path d="M9 2.5h6M8.2 8.6h7.6" stroke="#08090d" stroke-width="0.9" stroke-linecap="round" opacity="0.35"/>
</svg>
<span class="chrome-text">Alembic</span>
</a>
<nav class="nav-pills">
<a href="/" class="{{ 'active' if request.url.path == '/' else '' }}">Dashboard</a>
<a href="/playlists" class="{{ 'active' if request.url.path.startswith('/playlists') else '' }}">Playlists</a>
<a href="/library" class="{{ 'active' if request.url.path.startswith('/library') else '' }}">Library</a>
<a href="/dedup" class="{{ 'active' if request.url.path.startswith('/dedup') else '' }}">Dedup</a>
<a href="/genres" class="{{ 'active' if request.url.path.startswith('/genres') else '' }}">Genres</a>
<a href="/import" class="{{ 'active' if request.url.path.startswith('/import') else '' }}">Import</a>
<a href="/settings/credentials" class="{{ 'active' if request.url.path.startswith('/settings') else '' }}">Settings</a>
</nav>
{% if user %}
<div class="user-chip">
<span class="user-dot"></span>
<span>{{ user.email or user.name }}</span>
<form method="post" action="/auth/logout" style="display:inline; margin:0;">
<button type="submit" class="logout" title="Log out" aria-label="Log out">&#9211;</button>
</form>
</div>
{% endif %}
</div>
</header>
<main>
{% block content %}{% endblock %}
</main>
</body>
</html>