Enhance Docker setup and user notification features
CI / Backend (build + test) (push) Failing after 1m35s
CI / Frontend (lint + typecheck + build) (push) Successful in 35s

- Updated docker-compose.yml to include environment variables and health checks for the app service.
- Modified Dockerfile to install curl for health checks and adjusted the build process for backend services.
- Improved user notification handling in activation, blocking, and config revocation commands by integrating Telegram notifications.
- Added new test cases to validate the updated command handlers and Telegram notifier functionality.
- Enhanced documentation to reflect the new Telegram bot features and user management improvements.
This commit is contained in:
Leonid Pershin
2026-07-02 01:16:53 +03:00
parent 7b6fe9ad78
commit ed07221ca5
15 changed files with 404 additions and 34 deletions
@@ -262,7 +262,7 @@ public sealed class PnvBotUpdateHandler(
{
const string text = "Привет! Это бот PnvPanel.\n\n"
+ "/configs — мои конфиги\n"
+ "/login — войти на сайт без пароля\n"
+ "Вход без пароля запускается кнопкой «Войти через Telegram» на сайте — бот пришлёт запрос на подтверждение.\n"
+ "/unlink — отвязать Telegram\n"
+ "/help — эта справка";
await botClient.SendMessage(chatId, text, cancellationToken: cancellationToken);
@@ -9,7 +9,8 @@ using PnvPanel.Domain.Activation;
namespace PnvPanel.Application.Admin.Activation;
public sealed class ApproveActivationCommandHandler(
IAppDbContext dbContext, IIdentityService identityService, IRealtimeNotifier notifier, ICurrentUser currentUser)
IAppDbContext dbContext, IIdentityService identityService, IRealtimeNotifier notifier,
ITelegramNotifier telegramNotifier, ICurrentUser currentUser)
: ICommandHandler<ApproveActivationCommand, Result>
{
public async Task<Result> Handle(ApproveActivationCommand command, CancellationToken cancellationToken)
@@ -33,6 +34,7 @@ public sealed class ApproveActivationCommandHandler(
return activateResult;
await notifier.NotifyUserActivatedAsync(request.UserId, cancellationToken);
await telegramNotifier.NotifyUserAsync(request.UserId, "✅ Ваш аккаунт активирован администратором.", cancellationToken);
return Result.Success();
}
}
@@ -10,7 +10,7 @@ namespace PnvPanel.Application.Admin.Users;
/// <summary>Блокировка гасит все активные конфиги в 3x-ui (см. architecture.md).</summary>
public sealed class BlockUserCommandHandler(
IAppDbContext dbContext, IIdentityService identityService, IXuiPanelGateway gateway,
IRealtimeNotifier notifier, ICurrentUser currentUser)
IRealtimeNotifier notifier, ITelegramNotifier telegramNotifier, ICurrentUser currentUser)
: ICommandHandler<BlockUserCommand, Result>
{
public async Task<Result> Handle(BlockUserCommand command, CancellationToken cancellationToken)
@@ -44,6 +44,8 @@ public sealed class BlockUserCommandHandler(
dbContext.AuditLogs.Add(AuditLog.Create(
currentUser.UserId, "UserBlocked", "User", command.UserId.ToString(), metadata: null, AuditSource.Web));
await telegramNotifier.NotifyUserAsync(command.UserId, "⛔ Ваш аккаунт заблокирован администратором.", cancellationToken);
return Result.Success();
}
}
@@ -9,7 +9,8 @@ using PnvPanel.Domain.Configs;
namespace PnvPanel.Application.Admin.Users;
public sealed class ForceRevokeConfigCommandHandler(
IAppDbContext dbContext, IXuiPanelGateway gateway, IRealtimeNotifier notifier, ICurrentUser currentUser)
IAppDbContext dbContext, IXuiPanelGateway gateway, IRealtimeNotifier notifier,
ITelegramNotifier telegramNotifier, ICurrentUser currentUser)
: ICommandHandler<ForceRevokeConfigCommand, Result>
{
public async Task<Result> Handle(ForceRevokeConfigCommand command, CancellationToken cancellationToken)
@@ -35,6 +36,9 @@ public sealed class ForceRevokeConfigCommandHandler(
dbContext.AuditLogs.Add(AuditLog.Create(
currentUser.UserId, "ConfigForceRevoked", "VpnConfig", config.Id.ToString(), metadata: null, AuditSource.Web));
await telegramNotifier.NotifyUserAsync(
config.UserId, $"⚠️ Администратор отозвал ваш конфиг «{config.Label ?? config.ClientEmail}».", cancellationToken);
return Result.Success();
}
}