Система подтверждения опасных операций синхронизации¶
Обзор¶
Система подтверждения опасных операций синхронизации обеспечивает защиту от случайной потери данных при изменении структуры параметров в админке Django. При попытке выполнения операций, которые могут привести к потере данных (например, удаление колонок с данными), система запрашивает подтверждение пользователя.
Архитектура решения¶
Основные компоненты¶
- Savepoints - точки сохранения в транзакции для возможности отката
- SyncConfirmationRequired - исключение для опасных операций
- Диалог подтверждения - интерфейс для принятия решения пользователем
- Асинхронная синхронизация - принудительная синхронизация в отдельном процессе
Поток выполнения¶
graph TD
A[Пользователь сохраняет параметр] --> B[Создание savepoint]
B --> C[Сохранение изменений в БД]
C --> D[Попытка синхронизации force=False]
D --> E{SyncConfirmationRequired?}
E -->|Да| F[Показать диалог подтверждения]
E -->|Нет| G[Коммит savepoint]
G --> H[Успешное завершение]
F --> I{Пользователь подтвердил?}
I -->|Да| J[Запуск async синхронизации force=True]
I -->|Нет| K[Откат к savepoint]
J --> L[Коммит savepoint]
K --> M[Отмена изменений]
Реализация¶
1. Модификация ParameterAdmin¶
Создание savepoint в save_model:
def save_model(self, request, obj, form, change):
with transaction.atomic():
savepoint_id = transaction.savepoint()
request.session['parameter_savepoint_id'] = savepoint_id
super().save_model(request, obj, form, change)
self._pending_sync = True
Обработка синхронизации в response_change:
def response_change(self, request, obj):
if hasattr(self, '_pending_sync') and self._pending_sync:
try:
self._sync_parameter_after_save(request, obj)
transaction.savepoint_commit(savepoint_id)
except SyncConfirmationRequired as e:
# Сохранение данных в сессии и редирект на диалог
request.session['sync_confirmation_data'] = {
'parameter_id': obj.id,
'message': str(e),
'details': e.details,
'return_url': request.get_full_path()
}
return redirect('admin:parameters_confirm_sync_operations')
2. Диалог подтверждения¶
View confirm_sync_operations: - GET: Отображение информации об опасных операциях - POST с confirm=1: Запуск асинхронной синхронизации с force=True - POST с cancel=1: Откат к savepoint
Шаблон confirm_sync_operations.html: - Детальная информация о планируемых изменениях - Список опасных операций с описанием рисков - Кнопки подтверждения и отмены
3. Обработка MeasureAdmin¶
Аналогичная логика реализована для изменений мер: - Создание savepoint при сохранении - Обработка SyncConfirmationRequired - Перенаправление на тот же диалог подтверждения
Типы опасных операций¶
Система определяет следующие типы опасных операций:
delete_id_column¶
- Описание: Удаление колонки id
- Риск: Потеря первичных ключей и связей
- Действие: Всегда требует подтверждения
delete_dimension¶
- Описание: Удаление колонок измерений
- Риск: Потеря связей с иерархиями
- Действие: Требует подтверждения при наличии записей
delete_measure_with_data¶
- Описание: Удаление колонок мер с данными
- Риск: Потеря бизнес-данных
- Действие: Требует подтверждения при наличии не-NULL значений
alter_column_with_data¶
- Описание: Изменение типа колонки с данными
- Риск: Потеря данных при несовместимых типах
- Действие: Требует подтверждения при наличии данных
Безопасность данных¶
Механизмы защиты¶
- Savepoints: Возможность полного отката всех изменений
- Анализ данных: Проверка наличия данных перед опасными операциями
- Подробная информация: Детальное описание планируемых изменений
- Асинхронное выполнение: Принудительная синхронизация в отдельном процессе
Обработка ошибок¶
- Автоматический откат при любых ошибках в savepoint
- Логирование всех операций
- Информативные сообщения пользователю
- Ссылки на задачи Celery для отслеживания прогресса
Использование¶
Сценарии использования¶
- Добавление новой меры - безопасная операция, выполняется автоматически
- Удаление меры с данными - показывается диалог подтверждения
- Изменение типа меры - анализируется совместимость типов
- Изменение структуры измерений - проверяется влияние на данные
Действия пользователя¶
При появлении диалога подтверждения: 1. Внимательно изучить список опасных операций 2. Убедиться в наличии резервных копий данных 3. Выбрать одно из действий: - Подтвердить - запустить принудительную синхронизацию - Отменить - откатить все изменения
После подтверждения: 1. Отслеживать выполнение задачи по ссылке на TaskResult 2. Проверить результаты синхронизации 3. Убедиться в корректности данных
Тестирование¶
Основные тесты системы безопасности¶
Создан набор тестов test_admin_sync_confirmation.py:
test_parameter_save_creates_savepoint- создание savepointtest_sync_confirmation_required_handling- обработка исключенийtest_confirm_sync_operations_view_get- отображение диалогаtest_confirm_sync_operations_confirm- подтверждение операцийtest_confirm_sync_operations_cancel- отмена с откатом
Новые тесты в PLQM-1161¶
test_admin_unsafe_operations.py¶
Расположение: /src/planiqum/core/parameters/tests/test_admin_unsafe_operations.py
Назначение: Тестирование интеграции системы безопасности с Django админкой.
Ключевые тесты:
- test_admin_detects_unsafe_measure_deletion — обнаружение небезопасных операций удаления мер в админке
- test_admin_shows_confirmation_dialog — отображение диалога подтверждения в админке
- test_admin_executes_confirmed_operations — выполнение подтвержденных операций через админку
- test_admin_cancels_unsafe_operations — отмена небезопасных операций в админке
- test_admin_handles_measure_changes — обработка изменений мер в inline формах админки
- test_admin_handles_dimensions_changes — обработка изменений измерений в админке
Особенности тестов: - Тестируют полный flow от обнаружения до выполнения небезопасных операций - Проверяют интеграцию с Django админкой - Валидируют сериализацию данных в сессии - Проверяют обработку различных типов небезопасных операций - Тестируют работу с inline формами (меры, измерения)
Запуск тестов:
# Основные тесты системы безопасности
pytest src/planiqum/core/parameters/tests/test_admin_sync_confirmation.py -v
# Тесты интеграции с админкой
pytest src/planiqum/core/parameters/tests/test_admin_unsafe_operations.py -v
# Конкретный тест с отладочным выводом
pytest src/planiqum/core/parameters/tests/test_admin_unsafe_operations.py::test_admin_detects_unsafe_measure_deletion -v -s
# Все тесты системы безопасности
pytest src/planiqum/core/parameters/tests/test_admin_sync_confirmation.py src/planiqum/core/parameters/tests/test_admin_unsafe_operations.py -v
Конфигурация¶
Настройки в settings.py¶
Система использует существующие настройки:
- USE_CELERY - для асинхронного выполнения
- CELERY_* - настройки Celery для фоновых задач
Зависимости¶
- Django transactions и savepoints
- Celery для асинхронных задач
- django-celery-results для отслеживания задач
- Существующая система синхронизации параметров
Исправленные проблемы¶
Проблема с inline формами (исправлено)¶
Описание проблемы: При удалении мер через inline формы в админке параметра система не запускала синхронизацию и не показывала диалог подтверждения.
Причины:
1. В save_formset не устанавливался флаг _pending_sync
2. В модели Measure отсутствовал метод delete()
3. Функция on_measure_delete использовала устаревший метод syncdb()
Решение:
1. Обновлен save_formset - добавлена проверка изменений в inline формах:
def save_formset(self, request, form, formset, change):
has_changes = False
# Проверяем удаленные объекты
if hasattr(formset, 'deleted_objects') and formset.deleted_objects:
has_changes = True
# Проверяем измененные формы
for inline_form in formset.forms:
if inline_form.has_changed():
has_changes = True
break
super().save_formset(request, form, formset, change)
# Устанавливаем флаг синхронизации при наличии изменений
if has_changes:
self._pending_sync = True
-
Добавлен метод
delete()в модельMeasure:def delete(self, *args, **kwargs): # Удаляем таблицу ревизий, если используется if hasattr(self, 'use_revision') and self.use_revision: remove_measure_revision_table(self) super().delete(*args, **kwargs) -
Обновлена функция
on_measure_delete- использует новый методsync()вместоsyncdb()
Ограничения и известные проблемы¶
- Совместимость с транзакциями: Savepoints работают только внутри транзакций
- Сессии: Данные подтверждения хранятся в сессии пользователя
- Время жизни: Данные подтверждения не имеют автоматического срока истечения
- Concurrent access: Не защищено от одновременного изменения параметра
Дальнейшее развитие¶
Планируемые улучшения¶
- Модальные окна: Реализация диалога подтверждения в виде модального окна
- Предпросмотр изменений: Визуализация планируемых изменений структуры
- Уведомления: Email-уведомления о критических изменениях
- Аудит: Журнал всех подтвержденных опасных операций
Интеграция с другими компонентами¶
- Система прав доступа для ограничения опасных операций
- Интеграция с системой бэкапов для автоматического создания копий
- Webhook для уведомления внешних систем о структурных изменениях