control-api: every route now carries a mandatory access level (admin / agent / open) in a route table. All /api/v1/admin/* require the admin token; the write calls of validator-agent and prober (self-check, events, results, complete) require a separate static agent token; register, heartbeat and fetching the assignment stay open. Tokens come from env vars, are compared in constant time and never logged. An empty token leaves that level open with a startup warning (backward compatible). validator-agent / prober: apiclient sends the agent token only to control-api. admin-dashboard: login/password (from env) with a stateless HMAC session cookie, Origin-based CSRF check, per-IP brute-force throttle, HX-Redirect for htmx polls, logout in the sidebar; the dashboard calls control-api with the admin token. Login page layout fixed after review. Also: env plumbing in docker-compose/rxprod-compose/systemd/config examples, e2e script with token assertions, tests, docs (API, SETUP, USAGE, DASHBOARD, README), plan and review under docs/changes/, bin/ rebuilt with new SHA256SUMS. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
30 lines
964 B
HTML
30 lines
964 B
HTML
{{define "login_page"}}
|
|
<!doctype html>
|
|
<html lang="ru">
|
|
<head>{{template "html_head" .}}</head>
|
|
<body>
|
|
<div class="bg-grid"></div>
|
|
<main class="login-shell">
|
|
<div class="login-card">
|
|
<form class="panel" method="post" action="/login" autocomplete="on">
|
|
<div class="panel-head"><h2>Cloud IP Validator — вход</h2></div>
|
|
<div class="panel-body">
|
|
{{if .Error}}<div class="alert alert-warning" role="alert">{{.Error}}</div>{{end}}
|
|
<input type="hidden" name="next" value="{{.Next}}">
|
|
<div class="field">
|
|
<label for="login-username">Логин</label>
|
|
<input type="text" id="login-username" name="username" autocomplete="username" autofocus required>
|
|
</div>
|
|
<div class="field">
|
|
<label for="login-password">Пароль</label>
|
|
<input type="password" id="login-password" name="password" autocomplete="current-password" required>
|
|
</div>
|
|
<button type="submit" class="btn btn-primary btn-block">Войти</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</main>
|
|
</body>
|
|
</html>
|
|
{{end}}
|