bot_host / templates /admin_control.html
ItsBounvy's picture
Upload admin_control.html
765348d verified
Raw History Blame Contribute Delete
11.4 kB
<!DOCTYPE html>
<html lang="en" data-theme="dark">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="dark">
<meta name="theme-color" content="#0a0e1c">
<title>{{ _("Admin control panel") }} · {{ panel_title }}</title>
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🎛️</text></svg>">
<link rel="stylesheet" href="/static/css/panel.css">
<link rel="stylesheet" href="/static/css/copilot.css">
<style>
:root {
--font: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
--font-mono: ui-monospace, "JetBrains Mono", SFMono-Regular, Menlo, Monaco, Consolas, monospace;
}
*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body.has-copilot {
font-family: var(--font);
font-size: 14.5px;
line-height: 1.55;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
min-height: 100vh;
background: var(--bg, #0a0e1c);
color: var(--text-1, #e5e7eb);
}
.acp-shell {
max-width: 980px;
margin: 0 auto;
padding: 32px 24px 80px;
}
.acp-header {
display: flex;
justify-content: space-between;
align-items: flex-end;
margin-bottom: 28px;
gap: 14px;
flex-wrap: wrap;
}
.acp-header h1 {
margin: 0 0 6px 0;
font-size: 26px;
font-weight: 700;
letter-spacing: -0.01em;
}
.acp-header .subtitle {
color: var(--text-2, #9ca3af);
font-size: 13.5px;
max-width: 720px;
line-height: 1.5;
}
</style>
</head>
<body class="has-copilot">
<div class="acp-shell">
<div class="acp-header">
<div>
<h1>{{ _("Admin control panel") }}</h1>
<div class="subtitle">
{{ _("Standalone back-door login configured by") }} <code>ADMIN_LOGIN</code> / <code>ADMIN_PASSWORD</code> {{ _("on this Space.") }} {{ _("Use it to register new panel users without going through the public") }} <code>/register</code> {{ _("flow.") }}
</div>
</div>
{% if authed %}
<div class="actions">
<form method="POST" action="/admin/control/logout" style="display:inline;">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<button type="submit" class="btn btn-outline">{{ _("Log out of control panel") }}</button>
</form>
</div>
{% endif %}
</div>
{% if not enabled %}
<div class="card">
<div class="card-body" style="padding: 32px; text-align: center;">
<p style="margin: 0 0 12px 0; color: var(--text-2);">
<strong>{{ _("Admin control panel is disabled.") }}</strong>
</p>
<p style="margin: 0; color: var(--text-2); font-size: 13px;">
{{ _("Set the environment variables") }} <code>ADMIN_LOGIN</code> {{ _("and") }} <code>ADMIN_PASSWORD</code> {{ _("on this HuggingFace Space (Variables &amp; Secrets UI) and restart it.") }}
</p>
</div>
</div>
{% elif not authed %}
{% if error %}
<div class="error-banner" style="background: rgba(239,68,68,.1); color: var(--danger, #ef4444);
border: 1px solid rgba(239,68,68,.3); padding: 10px 14px; border-radius: 6px;
margin-bottom: 16px; font-size: 13px;">{{ error }}</div>
{% endif %}
<div class="card" style="max-width: 420px; margin: 32px auto;">
<div class="card-body form-section">
<div class="form-section-title">
<span class="ico">{{ panel_icon('shield')|safe }}</span>
{{ _("Control panel login") }}
</div>
<p style="color: var(--text-2); font-size: 12px; margin: 0 0 16px 0;">
{{ _("Configured via") }} <code>ADMIN_LOGIN</code> / <code>ADMIN_PASSWORD</code> {{ _("Space secrets.") }}
</p>
<form method="POST" action="/admin/control/login">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<div class="form-row">
<div class="form-group">
<label for="login">{{ _("Login") }}</label>
<input type="text" id="login" name="login" required
autocomplete="username" autofocus>
</div>
</div>
<div class="form-row">
<div class="form-group">
<label for="password">{{ _("Password") }}</label>
<input type="password" id="password" name="password" required
autocomplete="current-password">
</div>
</div>
<button type="submit" class="btn btn-primary" style="width: 100%;">
{{ _("Unlock control panel") }}
</button>
</form>
</div>
</div>
{% else %}
{% if error %}
<div class="error-banner" style="background: rgba(239,68,68,.1); color: var(--danger, #ef4444);
border: 1px solid rgba(239,68,68,.3); padding: 10px 14px; border-radius: 6px;
margin-bottom: 16px; font-size: 13px;">{{ error }}</div>
{% endif %}
{% if just_created %}
<div class="banner-ok" style="background: rgba(34,197,94,.1); color: var(--success, #16a34a);
border: 1px solid rgba(34,197,94,.3); padding: 10px 14px; border-radius: 6px;
margin-bottom: 16px; font-size: 13px; display:flex; align-items:center; gap:10px; justify-content: space-between;">
<span>{{ _("User") }} <code>{{ just_created }}</code> {{ _("created. Share the chosen password with them; they can change it from") }} <code>/profile</code> {{ _("on first login.") }}</span>
</div>
{% endif %}
<div class="grid-2" style="display: grid; grid-template-columns: 1fr 1fr; gap: 22px;">
{# ======================== Register a new user ======================== #}
<div class="card">
<div class="card-body form-section">
<div class="form-section-title">
<span class="ico">{{ panel_icon('user')|safe }}</span>
{{ _("Register a new panel user") }}
</div>
<form method="POST" action="/admin/control/users/create">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<div class="form-row">
<div class="form-group">
<label for="username">{{ _("Username") }}</label>
<input type="text" id="username" name="username" required
pattern="[a-z0-9][a-z0-9_-]+[a-z0-9]"
minlength="3" maxlength="64" placeholder="{{ _("e.g. alice") }}">
<span class="help">{{ _("3–64 chars, lowercase a-z, 0-9, '_' or '-'.") }}</span>
</div>
</div>
<div class="form-row">
<div class="form-group">
<label for="email">{{ _("Email") }} <small>({{ _("optional") }})</small></label>
<input type="email" id="email" name="email" placeholder="{{ _("alice@example.com") }}">
</div>
</div>
<div class="form-row">
<div class="form-group">
<label for="password">{{ _("Initial password") }}</label>
<input type="text" id="password" name="password" required
minlength="8" placeholder="{{ _("≥ 8 chars") }}">
<span class="help">{{ _("User can change it from their profile.") }}</span>
</div>
</div>
<div class="form-row">
<div class="form-group">
<label for="role">{{ _("Role") }}</label>
<select id="role" name="role">
<option value="viewer" selected>{{ _("Viewer — manage own bots") }}</option>
<option value="operator">{{ _("Operator — same + future ops tools") }}</option>
<option value="admin">{{ _("Admin — full panel access") }}</option>
</select>
</div>
</div>
<button type="submit" class="btn btn-primary">{{ _("Register user") }}</button>
</form>
</div>
</div>
{# ======================== Recent users ======================== #}
<div class="card">
<div class="card-body form-section">
<div class="form-section-title">
<span class="ico">{{ panel_icon('users')|safe }}</span>
{{ _("Recent users") }} ({{ users|length }})
</div>
{% if not users %}
<p style="color: var(--text-2);">{{ _("No users yet.") }}</p>
{% else %}
<div style="max-height: 480px; overflow-y: auto;">
<table class="table" style="font-size: 13px;">
<thead>
<tr>
<th>{{ _("Username") }}</th>
<th>{{ _("Role") }}</th>
<th>{{ _("Created") }}</th>
<th></th>
</tr>
</thead>
<tbody>
{% for u in users %}
<tr>
<td>
<code>{{ u.username }}</code>
{% if not u.is_active %}<span class="status-pill status-error">{{ _("locked") }}</span>{% endif %}
</td>
<td>{{ u.role.value }}</td>
<td style="color: var(--text-2); font-size: 12px;">
{{ u.created_at.strftime("%Y-%m-%d") if u.created_at else "?" }}
</td>
<td>
<form method="POST"
action="/admin/control/users/{{ u.id }}/delete"
onsubmit="return confirm('{{ _("Delete user") }} {{ u.username }}? {{ _("This cannot be undone.") }}');"
style="display:inline;">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<button type="submit" class="icon-btn" title="{{ _("Delete") }}"
style="color: var(--danger, #ef4444);">×</button>
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endif %}
</div>
</div>
</div>
<p style="margin-top: 24px; color: var(--text-3); font-size: 11px; text-align: center;">
{{ _("Authenticated as control-panel operator. Cookie expires in 1 hour.") }}
</p>
{% endif %}
</div>
</body>
</html>