Files
ipam_control/docs/changes/035-user-last-login/SUMMARY.md
T
ayurishchevandClaude Opus 5.5 8384c2c311 Задачи 034-035: публикация через Caddy, последний вход пользователя
034 Публикация стенда как https://rxipam.rxmsk.ru через общий Caddy хоста (Caddyfile вне репозитория):
    UI и /api/v1 доступны из интернета, /docs, /redoc, /openapi.json — только из частных сетей
    (RFC 1918/4193, loopback). Caddy проксирует на опубликованный порт приложения — общая Docker-сеть
    отклонена из-за коллизии имён app/db с Nextcloud. TRUSTED_PROXIES=172.16.0.0/12: реальный IP
    клиента из X-Forwarded-For. Интеграционный тест журнала больше не проверяет подделку XFF с хоста
    (хост за Caddy доверенный), логику покрывает unit-тест.
035 Дата и IP последнего входа в разделе «Пользователи»: users.last_login_at / last_login_ip
    (миграция 0014 с заполнением из журнала), запись при успешном входе, UserOut, колонка в UI.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 15:45:30 +03:00

3.1 KiB
Raw Blame History

Итог: последний вход пользователя — дата и IP (изменение 035)

План: PLAN.md. В разделе «Пользователи» появилась колонка «Последний вход»: дата (UTC) и IP последнего успешного входа.

Что сделано

Файл Изменение
app/models.py User.last_login_at (timestamptz), User.last_login_ip (INET), nullable
alembic/versions/0014_users_last_login.py Колонки и перенос данных из журнала: последнее событие session.login на логин. Если журнал ротирован или очищен — NULL
app/api/v1/auth.py Успешный вход записывает last_login_at = now() и last_login_ip в той же транзакции, что и session.login. IP — тот же, что в журнале (реальный клиент за Caddy, изменение 034). Неудачные попытки поля не трогают
app/schemas.py UserOut.last_login_at, UserOut.last_login_ip. INET приводится к строке через field_validator с существующей ip_text(). Поля видны в /users (только superadmin) и в /auth/me (свои)
web/app.js Колонка «Последний вход» после «Статус»: дата и IP моноширинным шрифтом, «—», если входа не было
tests/test_users.py В test_users_management: после входа созданного пользователя поля заполнены в GET /users
README.md «Интерфейс», миграции 0001–0014, строка 035 в истории

Проверки

  • Стенд пересобран: alembic current — 0014, alembic check — чисто, откат до 0013 и повторный upgrade — без ошибок.
  • Перенос данных: у tstark дата и IP (192.168.5.253) совпадают с последним session.login в журнале; у sbas-sa входов не было — NULL.
  • Временный viewer (создан и удалён через SQL): вход через Caddy с LAN-адреса хоста дал last_login_ip = 192.168.5.9 и дату входа, в JSON — строки. Неудачная попытка поля не изменила.
  • node --check web/app.js, import app.main — чисто.
  • pytest -q — 15 passed. Перед прогоном учётная запись admin из .env (удалена через UI в 08:54, фикстура client без неё не работает) создана заново через SQL как superadmin с паролем из .env; попытки входа под удалённым admin (блокировка «логин + IP») очищены. Создание через SQL в журнал не попало.

Не проверено

  • Колонка в браузере — не просматривалась.