Add factory reset functionality and update identity service
CI / Backend (build + test) (push) Successful in 1m18s
CI / Frontend (lint + typecheck + build) (push) Successful in 32s

- Introduced a new DELETE endpoint `/api/admin/maintenance/factory-reset` for a complete reset of the admin panel, removing all users except the current admin and clearing various data.
- Implemented the `FactoryReset` method in `AdminMaintenanceEndpoints` to handle the reset logic.
- Added a new method `ListAllUserIdsExceptAsync` in `IIdentityService` to retrieve user IDs excluding a specified user, aiding in the factory reset process.
- Updated the frontend to include a confirmation dialog for the factory reset action, enhancing user experience and safety.
- Enhanced localization support for the new factory reset feature in both Russian and English, ensuring clarity for all users.
This commit is contained in:
Leonid Pershin
2026-07-14 18:58:51 +03:00
parent 94ba514b8e
commit 701c3a1d51
16 changed files with 564 additions and 64 deletions
+13
View File
@@ -183,6 +183,7 @@ Support.CannotRequestAdminRole`), либо все три поля новой р
| DELETE | `/api/admin/maintenance/tickets/closed` | — | `{ deletedCount }` — удаляет все тикеты в статусе `Closed` вместе с комментариями и вложениями (файлы стираются с диска через `IFileStorage.DeleteAsync`) |
| DELETE | `/api/admin/maintenance/audit-logs` | query: `olderThanDays` (13650) | `{ deletedCount }` — удаляет записи `AuditLog` старше `olderThanDays` дней |
| DELETE | `/api/admin/maintenance/apps/disabled` | — | `{ deletedCount }` — удаляет все `ClientApp` с `IsEnabled = false` |
| DELETE | `/api/admin/maintenance/factory-reset` | — | `204 No Content` — полный сброс панели к состоянию свежего деплоя |
Тикет/комментарий/вложение — плоские сущности без FK-каскада (см. `SupportTicket`), поэтому хендлер
удаляет вручную в порядке вложения → комментарии → тикеты.
@@ -191,6 +192,18 @@ Support.CannotRequestAdminRole`), либо все три поля новой р
её `CreatedAt` позже порога, поэтому она не удаляет сама себя. Полного удаления всего журнала нет
осознанно — `AuditLog` в проекте append-only, доступна только очистка по возрасту.
**`factory-reset`** — самая деструктивная операция панели, на фронте спрятана под спойлер
(«Опасная зона») и требует ввести фразу-подтверждение в диалоге (не просто `confirm()`). Удаляет:
всех пользователей кроме текущего админа, все `VpnConfig`/`TrafficSample` (конфиги сначала best-effort
отзываются на нодах через `IXuiPanelGateway.RemoveClientAsync` — недоступная нода не блокирует сброс),
все `Node`/`Inbound`, тикеты с перепиской/вложениями (+файлы), `NewsPost`, весь `AuditLog`, все
кастомные роли (`AppRole.IsSystem == false`) и `ClientApp` — каталог приложений затем пересеивается
через `IClientAppCatalogSeeder` (тот же сервис, что использует `DbInitializer` при первом старте).
Не атомарно целиком (несколько `SaveChangesAsync` внутри хендлера, как и в `DeleteUserCommandHandler`) —
при сбое посередине возможно частичное состояние, компенсации нет, это осознанный компромисс для
редкой ручной админской операции. Финальная запись `FactoryReset` в аудит добавляется уже после
очистки самого журнала.
## Admin — Activation, Roles
| Метод | Путь | Роль | Тело запроса | Тело ответа |
+11 -3
View File
@@ -187,9 +187,17 @@ AppUser
| `CreatedAt` | `DateTimeOffset` | |
Пишется из хендлеров (или обработчиков доменных событий), append-only — из приложения ничего не
удаляет и не редактирует записи. Единственное исключение — retention-очистка по возрасту (вкладка
«Обслуживание», `DELETE /api/admin/maintenance/audit-logs?olderThanDays=N`), доступная только
админу; полного удаления журнала осознанно нет.
удаляет и не редактирует записи. Исключения — retention-очистка по возрасту (вкладка «Обслуживание»,
`DELETE /api/admin/maintenance/audit-logs?olderThanDays=N`) и полный сброс панели (см. ниже), оба
доступны только админу; отдельной кнопки «удалить весь журнал» без сброса всей панели осознанно нет.
### Полный сброс панели
Вкладка «Обслуживание» → «Опасная зона» (спойлер + подтверждение фразой в диалоге, не просто
`confirm()`) — `DELETE /api/admin/maintenance/factory-reset`. Возвращает панель к состоянию свежего
деплоя: удаляет всех пользователей кроме текущего админа, конфиги (сначала best-effort отзываются
на нодах 3x-ui), ноды/инбаунды, тикеты, новости, весь аудит и кастомные роли; каталог приложений
пересеивается из `seed/client-apps.json`. Необратимо, не атомарно целиком — подробности и полный
список удаляемого см. [api-design.md](api-design.md#admin--maintenance).
### AppUser — расширения (Identity)
`AppUser` живёт в Identity (`Infrastructure`). **Логин — по `UserName`** (уникальный, обязательный).