- Added `BaseAddress` property to `UpdateNodeCommand` and `UpdateNodeBody` for improved node management. - Implemented validation for the base address in `UpdateNodeCommandHandler`, ensuring it is a valid absolute URI. - Updated `Node` class to support address updates, including logic to invalidate cached clients on address changes. - Enhanced frontend components to handle base address input in the node editing dialog and API requests. - Updated validation rules to enforce base address requirements in `UpdateNodeCommandValidator`.
80 lines
2.8 KiB
C#
80 lines
2.8 KiB
C#
using Microsoft.EntityFrameworkCore;
|
|
using PnvPanel.Application.Common.Interfaces;
|
|
using PnvPanel.Application.Common.Messaging;
|
|
using PnvPanel.Application.Common.Models;
|
|
using PnvPanel.Domain.Audit;
|
|
using PnvPanel.Domain.Nodes;
|
|
|
|
namespace PnvPanel.Application.Admin.Nodes;
|
|
|
|
public sealed class UpdateNodeCommandHandler(
|
|
IAppDbContext dbContext,
|
|
IXuiPanelGateway gateway,
|
|
ISecretProtector secretProtector,
|
|
ICurrentUser currentUser
|
|
) : ICommandHandler<UpdateNodeCommand, Result<NodeDto>>
|
|
{
|
|
public async Task<Result<NodeDto>> Handle(
|
|
UpdateNodeCommand command,
|
|
CancellationToken cancellationToken
|
|
)
|
|
{
|
|
var node = await dbContext.Nodes.FirstOrDefaultAsync(
|
|
n => n.Id == command.NodeId,
|
|
cancellationToken
|
|
);
|
|
if (node is null)
|
|
return Result.Failure<NodeDto>(NodeErrors.NotFound);
|
|
|
|
if (!Uri.TryCreate(command.BaseAddress, UriKind.Absolute, out var baseAddress))
|
|
return Result.Failure<NodeDto>(NodeErrors.InvalidBaseAddress);
|
|
|
|
var addressChanged = baseAddress != node.BaseAddress;
|
|
if (addressChanged)
|
|
{
|
|
var validation = gateway.ValidateBaseAddress(baseAddress);
|
|
if (!validation.IsSuccess)
|
|
return Result.Failure<NodeDto>(validation.Error);
|
|
}
|
|
|
|
node.UpdateDetails(command.Name, command.Location);
|
|
|
|
if (addressChanged)
|
|
node.UpdateAddress(baseAddress);
|
|
|
|
if (command.IsEnabled)
|
|
node.Enable();
|
|
else
|
|
node.Disable();
|
|
|
|
var credentialsChanged =
|
|
!string.IsNullOrWhiteSpace(command.Username)
|
|
&& !string.IsNullOrWhiteSpace(command.Password);
|
|
if (credentialsChanged)
|
|
{
|
|
node.UpdateCredentials(
|
|
new NodeCredentials(command.Username!, secretProtector.Protect(command.Password!))
|
|
);
|
|
}
|
|
|
|
// Клиент в гейтвее закэширован per-node (адрес+креденшлы захвачены при первом создании) —
|
|
// при смене любого из них старый закэшированный клиент нужно выбросить, иначе гейтвей
|
|
// продолжит стучаться по старому адресу/с старым паролем до перезапуска процесса.
|
|
if (addressChanged || credentialsChanged)
|
|
gateway.InvalidateClient(node.Id);
|
|
|
|
dbContext.AuditLogs.Add(
|
|
AuditLog.Create(
|
|
currentUser.UserId,
|
|
"NodeUpdated",
|
|
"Node",
|
|
node.Id.ToString(),
|
|
metadata: null,
|
|
AuditSource.Web
|
|
)
|
|
);
|
|
|
|
return Result.Success(NodeDto.FromDomain(node));
|
|
}
|
|
}
|