14 lines
2.9 KiB
Markdown
14 lines
2.9 KiB
Markdown
# Итог: мелкие улучшения безопасности и журнала (изменение 023)
|
||||
|
|
|
|||
|
|
## Что сделано
|
|||
|
|
1. **LIKE:** `contains()`/`like_escape()` в `app/services.py`; все поиски (`refs`, `prefixes`, `users`, журнал) экранируют `%` и `_`.
|
|||
|
|
2. **Журнал очистки:** неверный пароль → `journal.clear_failed` (осталось попыток), блокировка → `journal.clear_locked`; красные бейджи в UI.
|
|||
|
|
3. **Заголовки безопасности** (`SecurityHeadersMiddleware` в `app/main.py`): `Content-Security-Policy` (`default-src 'self'`, `style-src 'self' 'unsafe-inline'` — UI использует атрибуты `style`, `frame-ancestors 'none'`), `X-Frame-Options`, `X-Content-Type-Options`, `Referrer-Policy`; для `/docs`, `/redoc`, `/openapi.json` CSP не ставится (Swagger с CDN).
|
|||
|
|
4. **`force`-удаление префикса:** в журнале `diff = {"force": true, "addresses_deleted": N}`.
|
|||
|
|
5. **Отзыв токенов при смене пароля:** миграция `0005` (`users.password_changed_at`); в токене claim `pv` (версия пароля), `current_user` отклоняет токены с другой версией (401). Отклонение от плана: вместо сравнения `iat` — версия пароля (не зависит от точности часов).
|
|||
|
|
`POST /users/me/password` возвращает новый `access_token`, UI подхватывает его — текущая сессия не прерывается; сброс пароля администратором отзывает токены пользователя.
|
|||
|
|
- **Побочный эффект:** `tests/test_users.py::test_users_management` (строка «выданный ранее токен продолжает работать») теперь падает — поведение изменено намеренно; тест обновить на этапе ревью с тестами.
|
|||
|
|
- `README.md`: разделы API, «Пользователи и роли», «Журнал».
|
|||
|
|
|
|||
|
|
## Проверка
|
|||
|
|
Проверка: стенд `ipam_control_006` пересобран, миграции применены до 0008 (`alembic check` — расхождений нет); ручная проверка (скрипт во временной папке, в репозиторий не добавлялся); автотесты по условию этапа не писались. Заголовки на `/` есть, на `/docs` CSP нет; поиск `%` в организациях пуст; старый токен после смены пароля → 401, новый → 200; `addresses_deleted` в журнале. UI при этом не открывался в браузере — CSP проверить на этапе ревью (консоль браузера).
|