mail/app/templates/admin/index.html
deeily 5024bf9a8d init: full mail stack — phases 0..8 (web client, admin, IMAP/SMTP,
sieve, search, sessions, dramatiq, deploy/install, ELK, monitoring)
2026-04-29 16:30:43 +03:00

125 lines
7.9 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{% extends 'layout/base.html' %}
{% block title %}Админка сервера{% endblock %}
{% block body %}
<div class="content">
{% include 'admin/_flash.html' %}
<div class="metrics">
<div class="metric"><div class="metric-label">Домены</div><div class="metric-val">{{ n_domains }}</div><div class="metric-sub">настроено</div></div>
<div class="metric"><div class="metric-label">Ящики</div><div class="metric-val">{{ n_mailboxes }}</div><div class="metric-sub">активные</div></div>
<div class="metric"><div class="metric-label">Алиасы</div><div class="metric-val">{{ n_aliases }}</div><div class="metric-sub">переадресации</div></div>
<div class="metric"><div class="metric-label">DMS</div><div class="metric-val">v14</div><div class="metric-sub">docker-mailserver</div></div>
</div>
<div class="card">
<div class="card-head"><div class="card-title">Быстрые действия</div></div>
<div class="card-body" style="display:flex;gap:8px;flex-wrap:wrap;align-items:center">
<a class="btn" href="{{ url_for('admin.mailboxes') }}">Ящики</a>
<a class="btn" href="{{ url_for('admin.aliases') }}">Алиасы</a>
<a class="btn" href="{{ url_for('admin.domains') }}">Домены / DNS / DKIM</a>
<span style="flex:1"></span>
<form method="post" action="{{ url_for('admin.trash_cleanup_now') }}" style="display:inline">
<button type="submit" class="btn" title="Очистить корзину старше {{ settings.trash_retention_days }} дней у всех активных юзеров">Очистить Корзину</button>
</form>
<form method="post" action="{{ url_for('admin.reindex') }}" style="display:inline">
<button type="submit" class="btn" title="Перечитать письма из IMAP и положить в Meilisearch">Реиндексировать поиск</button>
</form>
</div>
</div>
<div class="card" style="margin-top:14px">
<div class="card-head"><div class="card-title">Администраторы ({{ admins|length }})</div></div>
<div class="card-body">
<p style="color:var(--color-text-secondary);font-size:12px;margin-bottom:12px">
Администраторы видят раздел «Сервер» и пункты «Ящики», «Группы», «Общие ящики» в настройках, могут заходить на /admin/*.
</p>
<div style="display:flex;flex-direction:column;gap:6px;margin-bottom:14px">
{% for a in admins %}
<div style="display:flex;align-items:center;gap:10px;padding:6px 0;border-bottom:0.5px solid var(--color-border-tertiary)">
<span style="flex:1">{{ a }}</span>
<form method="post" action="{{ url_for('admin.admins_change') }}" onsubmit="return confirm('Снять {{ a }} с администратора?')">
<input type="hidden" name="action" value="remove">
<input type="hidden" name="email" value="{{ a }}">
<button class="btn" type="submit" style="font-size:12px;color:var(--color-text-danger)">Убрать</button>
</form>
</div>
{% endfor %}
</div>
<form method="post" action="{{ url_for('admin.admins_change') }}" style="display:flex;gap:8px;align-items:center">
<input type="hidden" name="action" value="add">
<input class="compose-input" name="email" placeholder="email@domain" required type="email"
style="flex:1;border:0.5px solid var(--color-border-tertiary);border-radius:6px;padding:6px 10px">
<button class="btn btn-primary" type="submit">+ Назначить администратором</button>
</form>
</div>
</div>
<div class="card" style="margin-top:14px">
<div class="card-head"><div class="card-title">ELK · отправка логов</div></div>
<div class="card-body">
<p style="color:var(--color-text-secondary);font-size:12px;margin-bottom:10px">
Логи Flask, Dramatiq, Postfix/Dovecot и cron-бэкапов отправляются на удалённый syslog-приёмник
(Logstash / rsyslog-collector). Настрой и нажми «Применить» — конфиг
<code>/etc/rsyslog.d/49-mail-stack.conf</code> перегенерируется и rsyslog перезагрузится.
Пустой ELK_HOST выключает отправку.
</p>
<table class="tbl" style="margin-bottom:14px">
<tr><td style="width:40%;color:var(--color-text-secondary)">Текущий target</td>
<td><code>{{ settings.elk_host or '— не настроен —' }}{% if settings.elk_host %}:{{ settings.elk_port }} ({{ settings.elk_proto }}){% endif %}</code></td></tr>
</table>
<form method="post" action="{{ url_for('admin.elk_apply') }}">
<button class="btn btn-primary" type="submit">Применить настройки rsyslog</button>
</form>
</div>
</div>
<div class="card" style="margin-top:14px">
<div class="card-head"><div class="card-title">Настройки приложения</div></div>
<div class="card-body">
<p style="color:var(--color-text-secondary);margin-bottom:14px;font-size:12px">
Значения сохраняются в <code>.env</code>. IMAP/SMTP-параметры применятся после авто-перезагрузки Flask
(debug-mode сам подхватит правки .env), остальное — мгновенно.
</p>
<form method="post" action="{{ url_for('admin.settings_update') }}" class="settings-form">
{% for form_name, env_name, kind, label in editable_settings %}
<div class="settings-row">
<label for="set-{{ form_name }}">
<span class="settings-label">{{ label }}</span>
<span class="settings-key">{{ env_name }}</span>
</label>
<input id="set-{{ form_name }}" name="{{ form_name }}"
type="{{ 'number' if kind == 'int' else 'text' }}"
value="{{ settings.get(form_name) if settings.get(form_name) is not none else '' }}">
</div>
{% endfor %}
<div class="settings-readonly">
<strong>Только для чтения:</strong>
use_mock_mail = {{ settings.use_mock_mail }}
</div>
<div style="display:flex;gap:8px;margin-top:14px">
<button class="btn btn-primary" type="submit">Сохранить</button>
</div>
</form>
</div>
</div>
<style>
.settings-form{display:flex;flex-direction:column;gap:10px}
.settings-row{display:grid;grid-template-columns:minmax(280px,2fr) minmax(160px,1fr);gap:14px;align-items:center}
.settings-row label{display:flex;flex-direction:column;gap:2px}
.settings-label{font-size:13px;color:var(--color-text-primary)}
.settings-key{font-size:11px;color:var(--color-text-tertiary);font-family:monospace}
.settings-row input{width:100%;padding:6px 10px;font-size:13px;font-family:inherit;color:var(--color-text-primary);background:var(--color-background-primary);border:0.5px solid var(--color-border-tertiary);border-radius:6px}
.settings-row input:focus{outline:none;border-color:var(--color-text-primary)}
.settings-readonly{margin-top:6px;padding:8px 12px;background:var(--color-background-secondary);border-radius:6px;font-size:12px;color:var(--color-text-secondary);font-family:monospace}
</style>
<div class="card" style="margin-top:14px">
<div class="card-head"><div class="card-title">Отложенная отправка</div></div>
<div class="card-body" style="color:var(--color-text-secondary)">
Все исходящие письма уходят через <strong>{{ settings.send_defer_seconds }} сек</strong>
после нажатия «Отправить». В это окно вы можете отменить отправку.
</div>
</div>
</div>
{% endblock %}