Админка: кнопки в шапке сайта, красный выход и путь, который нигде не утекает

Интерфейс:
- после входа на главной появляются «Админка» и «Выйти» — в шапке, перед
  переключателем темы и после него соответственно (порядок: Админка, тема,
  Выйти);
- «Выйти» теперь красная и заметно реагирует на наведение (темнеет,
  приподнимается, тень) — и на сайте, и в админке (одна кнопка в шапке,
  из карточки убрана);
- в админке убраны «осталось попыток», путь к файлу настроек и карточка
  «Данные расписания» (дублировала шапку); блокировка показывается отдельной
  плашкой только когда действительно активна.

Безопасность пути:
- путь к панели не отдаётся ни в HTML, ни в JSON (из /api/admin/state убран),
  ни в JS: на главной для вошедшего только флаг, а кнопка «Админка» ведёт на
  служебный /api/admin/goto, который отвечает 302 на секретный путь;
- без сессии /api/admin/goto и /api/admin/state отвечают 401, неизвестные пути
  дают 404 — перебором путь не находится;
- страница панели: noindex/nofollow/noarchive, Referrer-Policy: no-referrer,
  X-Frame-Options: DENY, Cache-Control: no-store;
- robots.txt без пути (только Disallow: /api/), внешние ссылки в панели —
  rel=noopener noreferrer.

Тесты: 161 (состояние без пути, /goto: 401 без входа и 302 с ним).
This commit is contained in:
2026-10-10 12:54:54 +03:00
parent 71f83a27dd
commit 34a46b6832
8 changed files with 159 additions and 34 deletions

View File

@@ -151,6 +151,47 @@ a:hover { color: var(--accent-red); }
}
.theme-toggle:hover { color: var(--accent); border-color: var(--accent); }
/* ---- кнопки в шапке: админка и выход ---- */
.topbar-actions { display: flex; align-items: center; gap: 10px; flex-shrink: 0; }
.topbar-admin {
display: inline-flex;
align-items: center;
height: 36px;
padding: 0 14px;
border: 1px solid var(--accent);
background: var(--accent);
color: var(--on-accent);
font-size: 13px;
font-weight: 600;
text-decoration: none;
transition: filter .15s ease, transform .15s ease;
}
.topbar-admin:hover { filter: brightness(1.1); transform: translateY(-1px); }
.topbar-admin:active { transform: none; }
/* красная кнопка выхода: при наведении темнеет, приподнимается и даёт тень */
.topbar-logout {
display: inline-flex;
align-items: center;
height: 36px;
padding: 0 14px;
border: 1px solid var(--accent-red-bright);
background: var(--accent-red-bright);
color: #fff;
font-size: 13px;
font-weight: 600;
cursor: pointer;
transition: background .15s ease, border-color .15s ease, box-shadow .15s ease, transform .15s ease;
}
.topbar-logout:hover {
background: var(--accent-red);
border-color: var(--accent-red);
box-shadow: 0 4px 12px color-mix(in srgb, var(--accent-red-bright) 35%, transparent);
transform: translateY(-1px);
}
.topbar-logout:active { transform: none; box-shadow: none; }
.theme-toggle .icon { width: 18px; height: 18px; }
.icon-sun { display: none; }