Задачи 006-010: пользователи, исправление удаления, журнал отказов, групповые операции, автовыделение префиксов
006 Пользователи: API /users (CRUD, смена своего пароля), раздел UI «Пользователи»,
события журнала user.*, защита от отключения/удаления себя и последнего админа.
007 Исправление удаления организации: VRF удаляются явным DELETE до организации
(без relationship() порядок DELETE не гарантирован → ложный 409).
008 Журнал фиксирует отказы в удалении (<entity>.delete_blocked) со списком
мешающих объектов в «Данных»: организация, VRF, тип устройства, префикс, пользователь.
009 Выбор строк чекбоксами и групповые операции в UI (удаление, смена типа устройств,
статус префиксов и адресов, доступ пользователей); цикл запросов из UI, итог и список отказов.
010 Автовыделение следующего вложенного префикса: POST/GET /prefixes/{id}/subnets/next,
первый свободный выровненный блок; пункт «Добавить вложенный (авто)» в меню префикса.
Тесты: 14 (добавлены сценарии для 006, 007/008, 010); исправлена нестабильность
тестов журнала (IPv6-группы с ведущими нулями нормализуются PostgreSQL).
Документация: README.md, docs/changes/006-010 (планы и итоги).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
a846d30872
commit
cd09ef0805
23 files changed
+988
-49
No files matched your search
@@ -37,15 +37,30 @@ alembic/ scripts/{gen_env,seed_demo}.py tests/ docs/changes/
|
||||
имена могут совпадать; в одном VRF может быть много префиксов. Принадлежность VRF организации префикса гарантирует составной FK в БД.
|
||||
- Смена VRF у префикса (`PATCH /prefixes/{id}` с `vrf_id`) — только среди VRF той же организации; переносится префикс вместе с вложенными,
|
||||
дубль CIDR в целевом VRF → 409 (без частичных изменений), VRF другой организации → 422.
|
||||
- VRF, тип устройства, организация с зависимыми объектами не удаляются (409).
|
||||
- Автовыделение вложенного префикса (изменение 010): `POST /prefixes/{id}/subnets/next` с `length` (например 30) создаёт дочерний префикс в первом свободном выровненном блоке родителя (учитываются вложенные префиксы
|
||||
и адреса родителя); `GET` с тем же путём и `?length=` — предпросмотр. Нет места → 409, недопустимый размер → 422. В UI — пункт «Добавить вложенный (авто)» в меню «⋯» префикса.
|
||||
- VRF, тип устройства, организация с зависимыми объектами не удаляются (409). У организации без префиксов, устройств и операторов
|
||||
служебный VRF `default` удаляется вместе с ней (исправлено в изменении 007: раньше такое удаление давало 409).
|
||||
|
||||
## API (`/api/v1`)
|
||||
`POST /auth/login` · `GET /auth/me` · `GET /overview`
|
||||
CRUD: `/organizations`, `/vrfs`, `/isps`, `/device-types`, `/devices`, `/prefixes`, `/addresses/{id}`
|
||||
CRUD: `/organizations`, `/vrfs`, `/isps`, `/device-types`, `/devices`, `/prefixes`, `/addresses/{id}`, `/users`
|
||||
Адреса префикса: `GET|POST /prefixes/{id}/addresses` (`status`, `q`, `limit`, `offset`), `POST …/addresses/next` — автоназначение из пула.
|
||||
Ошибки: `{code, message, fields}` (для блокировок/лимитов — дополнительные поля `attempts_left`, `retry_after_seconds`). Каждое изменение пишется в `audit_log`.
|
||||
|
||||
### Пользователи и роли
|
||||
- `GET|POST /users`, `PATCH|DELETE /users/{id}` — управление учётными записями, только `admin`: логин (3–100 символов, латиница,
|
||||
цифры, `. _ -`), роль, доступ и пароль (при сбросе администратором). Логин после создания не меняется — он же `sub` в токене.
|
||||
- `POST /users/me/password {current_password, new_password}` — смена своего пароля, доступна любой роли; неверный текущий пароль → 403.
|
||||
- Занятый логин (в том числе в другом регистре) → 409; служебные логины `system` и `anonymous`, короткий логин или пароль → 422.
|
||||
- Свою учётную запись нельзя понизить, отключить или удалить, как и последнего активного администратора → 409.
|
||||
- Отключение действует немедленно (токен проверяется по `users.is_active` на каждом запросе), а смена пароля уже выданные токены
|
||||
не отзывает — они живут до истечения `JWT_TTL_MINUTES`. Роль `viewer` видит реестр и журнал, но любые изменения получает с 403.
|
||||
- Изменения пишутся в журнал: `user.created`, `user.updated`, `user.password_reset`, `user.deleted` (значения паролей не сохраняются).
|
||||
|
||||
### Журнал
|
||||
- Отказ в удалении по бизнес-правилу (409: организация, VRF, тип устройства, префикс с адресами, пользователь) фиксируется событием `<сущность>.delete_blocked` (изменение 008);
|
||||
в «Данных» записи — `reason` и `blocked_by` со списками мешающих объектов (`total` и до 20 названий: префиксы, устройства, операторы, адреса).
|
||||
- `GET /audit` — поиск и фильтры: `q` (сообщение, метка объекта, начало ID записи), `event_type` (`prefix.created`), `entity_type`, `actor` (`ui:admin`, `system`, `anonymous`), `date_from`/`date_to` (UTC), `limit`/`offset`; `GET /audit/summary`, `/audit/facets`, `/audit/{uid}`.
|
||||
- `GET|PUT /journal/settings` — ротация: `retention_days` (по умолчанию 90) и `max_entries` (100 000), `0` — без ограничения. Ротация идёт раз в час и сразу при сохранении настроек
|
||||
(advisory-lock защищает от параллельного запуска); каждая ротация с удалениями фиксируется записью `journal.rotated`. Запись — только admin.
|
||||
@@ -57,9 +72,14 @@ CRUD: `/organizations`, `/vrfs`, `/isps`, `/device-types`, `/devices`, `/prefixe
|
||||
- В журнал пишутся также входы (`session.login`, `session.failed` — актор `anonymous`) и служебные события (`journal.*`, актор `system`).
|
||||
|
||||
## Поведение таблиц UI
|
||||
Администратор может выбирать строки чекбоксами (в шапке — «выбрать все») на экранах «Организации», «Операторы», «Устройства», «Префиксы» (листовые), «Адреса» (кроме «Свободен») и «Пользователи» (кроме себя);
|
||||
в «Журнале» выбора нет. Панель над таблицей: «Удалить» везде, «Сменить тип» (устройства), «Статус» (префиксы, адреса), «Разрешить/Отключить доступ» (пользователи). Операции идут по одному запросу
|
||||
на объект (изменение 009): итог «выполнено N из M», отказы (зависимые объекты, свой аккаунт, последний администратор) показаны списком с причиной, попадают в журнал как `*.delete_blocked`,
|
||||
и остаются выбранными. Префиксы удаляются без `force`: префикс с адресами удаляется из одиночного меню строки.
|
||||
Строка реестра кликабельна целиком (как в журнале): «Префиксы» — лист открывает адреса подсети, родитель сворачивает/разворачивает ветку; «Организации» — префиксы организации;
|
||||
«Операторы», «Устройства» и «Адреса» — окно редактирования (свободный адрес — «Назначить адрес» с этим IP). Ссылки, шеврон, меню «⋯» работают как раньше и не запускают действие строки;
|
||||
Ctrl/Shift+клик и выделение текста тоже игнорируются.
|
||||
Экран «Пользователи» доступен только администратору: создание, редактирование роли и доступа, удаление на месте, а свой пароль меняется кнопкой «Сменить пароль» в шапке.
|
||||
|
||||
## Тесты
|
||||
Идут против приложения в контейнерах, учётные данные берутся из `.env`:
|
||||
|
||||
Reference in new issue
Block a user