25 lines
3.1 KiB
Markdown
25 lines
3.1 KiB
Markdown
# Итог: последний вход пользователя — дата и 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 в журнал не попало.
|
|||
|
|
|
|||
|
|
## Не проверено
|
|||
|
|
- Колонка в браузере — не просматривалась.
|