Files
ayurishchevandClaude Sonnet 5 cd09ef0805 Задачи 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>
2026-09-26 13:25:33 +03:00

3.1 KiB
Raw Permalink Blame History

Итог: журнал фиксирует отклонённые удаления (изменение 008)

Что сделано

  • Событие <entity>.delete_blocked (organization, vrf, device_type, prefix, user) пишется при каждом отказе в удалении по бизнес-правилу (409). Ответ API не менялся: тот же код и текст. Фильтры и список типов событий журнала подхватили новый тип без правок.
  • app/services.py: refuse_delete() (запись в журнал + commit + 409) и blockers() (общее число и до 20 названий мешающих объектов).
  • Вызовы: delete_org (префиксы CIDR (VRF), устройства, операторы — все группы сразу), delete_vrf (префиксы), delete_type (устройства; тип по умолчанию), delete_prefix (адреса, кроме force=true), delete_user (свой аккаунт, единственный активный администратор).
  • «Данные» записи (audit_log.diff, схема БД не менялась): {"reason": "…", "blocked_by": {"prefixes": {"total": 13, "items": ["10.0.0.0/8 (default)", …]}, "devices": {…}, "isps": {…}}}; для отказов без связанных объектов — только reason. Окно записи уже выводит diff как JSON.
  • UI (web/app.js): жёлтый бейдж для delete_blocked в журнале и подпись «отклонено» в последних изменениях на «Обзоре».
  • Тест: test_delete_organization расширен — запись organization.delete_blocked с blocked_by.prefixes.

Проверка

  • Полный набор тестов: 13 passed. Вручную отказы на организацию, VRF, свой аккаунт и тип по умолчанию дали записи с ожидаемым содержимым.
  • Первая версия падала 500 (JOIN без левой стороны в запросе списка префиксов организации) — поймано тестом, исправлено select_from(Prefix).
  • При ручной проверке демо-префикс 10.0.0.0/8 был удалён ошибочно (у него нет собственных адресов, отказа не было) и восстановлен через API: дерево прежнее, но id стал 67.
  • Стенд ipam_control_006 пересобран только по сервису app.

Ограничения

  • Журналируются только отказы удаления; прочие 409 (дубли, «нет свободных адресов», отказ понизить свой аккаунт при PATCH) — нет.
  • Каждая повторная попытка даёт новую запись (дедупликации нет).