using Microsoft.EntityFrameworkCore; using PnvPanel.Application.Auth; using PnvPanel.Application.Common.Interfaces; using PnvPanel.Application.Common.Messaging; using PnvPanel.Application.Common.Models; namespace PnvPanel.Application.Configs.GetConfigLink; public sealed class GetConfigLinkQueryHandler(IAppDbContext dbContext, IXuiPanelGateway gateway, ICurrentUser currentUser) : IQueryHandler> { public async Task> Handle(GetConfigLinkQuery query, CancellationToken cancellationToken) { if (currentUser.UserId is not { } userId) return Result.Failure(AuthErrors.Unauthorized); var config = await dbContext.VpnConfigs.AsNoTracking() .FirstOrDefaultAsync(c => c.Id == query.ConfigId && c.UserId == userId, cancellationToken); if (config is null) return Result.Failure(ConfigErrors.NotFound); var inbound = await dbContext.Inbounds.AsNoTracking().FirstOrDefaultAsync(i => i.Id == config.InboundId, cancellationToken); if (inbound is null) return Result.Failure(ConfigErrors.InboundNotAvailable); var node = await dbContext.Nodes.AsNoTracking().FirstOrDefaultAsync(n => n.Id == inbound.NodeId, cancellationToken); if (node is null) return Result.Failure(ConfigErrors.NodeDisabled); var linkResult = await gateway.BuildConnectionStringAsync( node, inbound, config.ClientExternalId, config.Label ?? config.ClientEmail, node.BaseAddress.Host, cancellationToken); if (!linkResult.IsSuccess) return Result.Failure(linkResult.Error); return Result.Success(new ConfigLinkDto(linkResult.Value, config.SubscriptionToken)); } }