Implement activation checks across various commands and queries
CI / Backend (build + test) (push) Successful in 1m26s
CI / Frontend (lint + typecheck + build) (push) Successful in 30s

- Introduced `IRequiresActivation` interface to enforce activation requirements for multiple commands and queries, ensuring that only activated users can create, edit, or access configurations, news, and applications.
- Updated the `RequireActivationBehavior` to handle activation checks uniformly, returning appropriate errors for unauthenticated or inactive users.
- Enhanced error handling by adding `NotActivated` error to provide clear feedback for users attempting to access restricted features.
- Updated documentation to reflect the new activation requirements and their implications on user access and functionality.
This commit is contained in:
Leonid Pershin
2026-07-13 18:51:03 +03:00
parent 7f9a441050
commit 14b64a3140
23 changed files with 183 additions and 45 deletions
+11 -7
View File
@@ -73,9 +73,11 @@ PnvPanel — backend на **ASP.NET Core (.NET 10)** по принципам **C
[backend-conventions.md](backend-conventions.md)).
- **DTO**: плоские `record`, конвертация из сущностей — статический метод `FromDomain(...)` на самом
DTO, без маппера (Mapster/AutoMapper).
- **Pipeline behaviors**: `ValidationBehavior`, `LoggingBehavior`, `UnitOfWorkBehavior` (транзакция +
`SaveChangesAsync` на команду). Отдельного `AuthorizationBehavior` нет — авторизация (роль,
активация) — это либо `RequireAuthorization()`/`RequireRole(...)` на эндпоинте, либо явная проверка
- **Pipeline behaviors** (порядок: Logging → Validation → RequireActivation → UnitOfWork):
`LoggingBehavior`, `ValidationBehavior`, `RequireActivationBehavior` (403 `Auth.NotActivated` для
запросов с маркером `IRequiresActivation` — конфиги, новости, каталог приложений), `UnitOfWorkBehavior`
(транзакция + `SaveChangesAsync` на команду). Отдельного `AuthorizationBehavior` для ролей нет —
роль проверяется через `RequireAuthorization()`/`RequireRole(...)` на эндпоинте либо явной проверкой
в начале хендлера (например, «инбаунд доступен роли пользователя»).
- **Result<T>**: явная модель успеха/ошибки (`Result`/`Result<T>`, `Error` с `ErrorType`) вместо
исключений для управляемых сценариев.
@@ -131,10 +133,11 @@ PnvPanel — backend на **ASP.NET Core (.NET 10)** по принципам **C
Пример потока «создать конфиг» (`backend/src/PnvPanel.Application/Configs/Create/CreateVpnConfigCommandHandler.cs`):
```
POST /api/configs
→ CreateVpnConfigCommand
→ CreateVpnConfigCommand (IRequiresActivation)
→ ValidationBehavior (FluentValidation — формат inboundId/label)
→ RequireActivationBehavior (403 Auth.NotActivated, если аккаунт не активирован)
→ CreateVpnConfigCommandHandler
· проверяет активацию + роль инбаунда (доменные проверки)
· проверяет роль инбаунда (доменная проверка)
· SELECT pg_advisory_xact_lock(hashtext(userId)) — сериализует параллельные создания
· пересчитывает текущее число активных конфигов и сверяет с AppRole.MaxConfigs
· IXuiPanelGateway.AddClientAsync(node, inbound, ...) // 3x-ui, получает ClientExternalId
@@ -253,8 +256,9 @@ POST /api/configs
вошедшим — `POST /api/auth/change-password`.
- **AuthZ**: именованных policy нет — либо `.RequireAuthorization()` (любой вошедший) или
`.RequireAuthorization(policy => policy.RequireRole(RoleNames.Admin))` на группе эндпоинтов, либо
явная проверка внутри хендлера (владение конфигом — сравнение `VpnConfig.UserId` с `ICurrentUser`;
активация — `ConfigErrors.NotActivated`).
явная проверка внутри хендлера (владение конфигом — сравнение `VpnConfig.UserId` с `ICurrentUser`).
Активация — не в хендлере, а в pipeline behavior (`RequireActivationBehavior`, срабатывает на
запросах с маркером `IRequiresActivation`: конфиги, новости, каталог приложений) — `AuthErrors.NotActivated`.
- **Секреты нод**: шифруются `ISecretProtector` (Data Protection) перед сохранением; в API/логи не попадают.
- **CSRF**: явного анти-CSRF токена нет — все мутации API читают авторизацию только из
`Authorization: Bearer` (JS должен явно прочитать access-token из памяти и подставить заголовок,