Files
PnvPanel/docs/backend-conventions.md
T

7.7 KiB
Raw Blame History

Backend Conventions

Структура решения

backend/
  PnvPanel.sln
  src/
    PnvPanel.Domain/
      Common/            # Entity, AggregateRoot, IDomainEvent, ValueObject base
      Nodes/             # Node, NodeCredentials, NodeStatus, события
      Inbounds/          # Inbound, VpnProtocol
      Configs/           # VpnConfig, ConfigStatus, TrafficLimit, события
      Plans/             # Plan
      Exceptions/        # DomainException и наследники
    PnvPanel.Application/
      Common/
        Behaviors/       # Validation, Logging, UnitOfWork, Authorization
        Interfaces/      # IAppDbContext, IXuiPanelGateway, ICurrentUser, IRealtimeNotifier, ...
        Messaging/       # ISender, ICommand<T>, IQuery<T>, ICommandHandler<,>, IQueryHandler<,>, IPipelineBehavior<,>
        Models/          # Result<T>, Error, PagedList<T>
        Mapping/         # Mapster-конфиги
      Auth/              # Register/Login/Refresh (Commands, Handlers, Validators, DTOs)
      Configs/           # CreateVpnConfig, EditVpnConfig, RotateVpnConfig, RevokeVpnConfig, GetMyConfigs, GetConfigLink, GetSubscription, ...
      Nodes/             # RegisterNode, SyncNode, ListNodes, ...
      Inbounds/          # PublishInbound, ListInbounds, ...
      Apps/              # (admin) CRUD каталога ClientApp; GetApps (по ОС) для юзера
      Admin/             # ListUsers, BlockUser/UnblockUser, ChangeUserRole, GetStats, Audit, ...
    PnvPanel.Infrastructure/
      Persistence/
        AppDbContext.cs
        Configurations/  # IEntityTypeConfiguration<T>
        Migrations/
      Identity/          # AppUser, AppRole, JwtTokenService, RefreshToken
      Xui/               # XuiPanelGateway, XuiClientFactory (per-node)
      Realtime/          # SignalRRealtimeNotifier
      BackgroundJobs/    # TrafficSyncService, NodeHealthCheckService
      Security/          # DataProtectionSecretProtector
      DependencyInjection.cs
    PnvPanel.Api/
      Endpoints/         # AuthEndpoints, ConfigEndpoints, NodeEndpoints, AdminEndpoints, SubscriptionEndpoints
      Hubs/              # PanelHub
      Middleware/        # ExceptionHandling, RequestCorrelation
      Extensions/        # AddApiServices, UseApiPipeline
      Program.cs
      appsettings*.json
  tests/
    PnvPanel.Domain.Tests/
    PnvPanel.Application.Tests/
    PnvPanel.Integration.Tests/     # Testcontainers PostgreSQL

Организация Application — по фичам (feature folders), внутри слоёв Clean Architecture.

Именование

  • Классы/методы/свойства — PascalCase; параметры/локальные — camelCase; приватные поля — _camelCase.
  • Команды — <Verb><Noun>Command (CreateVpnConfigCommand), запросы — <Get/List><Noun>Query.
  • Хендлеры — <Command/Query>Handler; валидаторы — <Command/Query>Validator.
  • DTO — суффикс Dto (VpnConfigDto); ответы эндпоинтов — Response, тела запросов — Request.
  • Async-методы — суффикс Async, всегда принимают CancellationToken.
  • Один публичный тип на файл; имя файла = имя типа.

Паттерны

  • Rich domain model: инварианты в сущностях (приватные сеттеры, фабричные методы Node.Create(...), поведенческие методы config.Revoke()), а не анемичные DTO-сущности.
  • CQRS через собственный диспетчер: хендлеры реализуют ICommandHandler<TCommand,TResult> / IQueryHandler<,>; ISender резолвит их из DI и прогоняет через IPipelineBehavior<,> (валидация, транзакция, логирование). Без внешних CQRS-библиотек.
  • Порты в Application, адаптеры в Infrastructure: никакого Npgsql/SignalR/ThreeXui.Net в Application/Domain.
  • IAppDbContext экспонирует DbSet<> и SaveChangesAsync; хендлеры пишут LINQ напрямую (репозитории — только для сложной агрегатной логики).
  • Result-модель: команды/запросы возвращают Result<T>; эндпоинт маппит в HTTP (.Match(...)).
  • Транзакция на команду: UnitOfWorkBehavior оборачивает выполнение команды в транзакцию.
  • Валидация: ValidationBehavior до хендлера; хендлер не проверяет формат ввода повторно.
  • Идемпотентность: команды к 3x-ui устойчивы к повторам; при частичном сбое — компенсация (создали клиента в панели, но упала БД → удалить клиента, вернуть ошибку).
  • Оптимистичная блокировка: на изменяемых сущностях (нода, конфиг) — xmin/rowversion, чтобы параллельные правки не затирали друг друга.

Работа с 3x-ui

  • Только через порт IXuiPanelGateway. Гейтвей принимает Node/NodeId и разруливает per-node клиента.
  • Пароли нод расшифровываются ISecretProtector внутри Infrastructure, никогда не покидают слой.
  • Сетевые ошибки/недоступность → Result.Failure/статус ноды, не «пробрасываем» наружу как 500.

Async / Cancellation

  • Всё I/O — асинхронно; пробрасывать CancellationToken до EF Core и HTTP-вызовов.
  • Не блокировать (.Result/.Wait()).

Ошибки и логирование

  • Единый ProblemDetails для ошибок API; коды: 400 (валидация), 401/403 (auth), 404, 409 (конфликт домена), 422, 429 (rate limit), 500.
  • Serilog со структурными полями (UserId, NodeId, ConfigId, CorrelationId); секреты не логировать.

Тестирование

  • Domain.Tests — инварианты и поведение сущностей, без моков.
  • Application.Tests — хендлеры с подменёнными портами (NSubstitute), проверка веток Result.
  • Integration.Tests — реальный PostgreSQL (Testcontainers), миграции, сквозные сценарии эндпоинтов; 3x-ui — мок гейтвея или фейковый HTTP-сервер.
  • Именование тестов: Method_Scenario_ExpectedResult.

Конфигурация

  • appsettings.json + appsettings.{Environment}.json + env vars (перекрывают).
  • Секреты (JWT-ключ, строка подключения, ключ шифрования) — user-secrets (dev) / env/secret-store (prod).
  • Строго типизированные IOptions<T> для секций конфига; валидация опций на старте.

Стиль и качество кода

  • .editorconfig + анализаторы (Microsoft.CodeAnalysis.NetAnalyzers), nullable reference types включены.
  • dotnet format в CI; предупреждения как ошибки для наших проектов.
  • Комментарии — по необходимости (почему, а не что); публичные контракты портов документируем XML-doc.