using FastEndpoints; using Microsoft.EntityFrameworkCore; using Socialize.Api.Data; using Socialize.Api.Infrastructure.Security; using Socialize.Api.Modules.Clients.Data; namespace Socialize.Api.Modules.Clients.Handlers; public record UpdateClientRequest( string Name, string? PortraitUrl, string Status, string? PrimaryContactName, string? PrimaryContactEmail, string? PrimaryContactPortraitUrl); public class UpdateClientRequestValidator : Validator { public UpdateClientRequestValidator() { RuleFor(x => x.Name).NotEmpty().MaximumLength(256); RuleFor(x => x.PortraitUrl).MaximumLength(2048); RuleFor(x => x.Status).NotEmpty().MaximumLength(64); RuleFor(x => x.PrimaryContactName).MaximumLength(256); RuleFor(x => x.PrimaryContactEmail).MaximumLength(256).EmailAddress().When(x => !string.IsNullOrWhiteSpace(x.PrimaryContactEmail)); RuleFor(x => x.PrimaryContactPortraitUrl).MaximumLength(2048); } } public class UpdateClientHandler( AppDbContext clientsDbContext, AccessScopeService accessScopeService) : Endpoint { public override void Configure() { Put("/api/clients/{id}"); Options(o => o.WithTags("Clients")); } public override async Task HandleAsync(UpdateClientRequest request, CancellationToken ct) { Guid id = Route("id"); Client? client = await clientsDbContext.Clients.SingleOrDefaultAsync(candidate => candidate.Id == id, ct); if (client is null) { await SendNotFoundAsync(ct); return; } if (!await accessScopeService.CanManageWorkspaceAsync(User, client.WorkspaceId, ct)) { await SendForbiddenAsync(ct); return; } string normalizedName = request.Name.Trim(); string normalizedStatus = request.Status.Trim(); string? normalizedPortraitUrl = request.PortraitUrl?.Trim(); string? normalizedPrimaryContactName = request.PrimaryContactName?.Trim(); string? normalizedPrimaryContactEmail = request.PrimaryContactEmail?.Trim(); string? normalizedPrimaryContactPortraitUrl = request.PrimaryContactPortraitUrl?.Trim(); bool duplicateClient = await clientsDbContext.Clients .AnyAsync( candidate => candidate.Id != id && candidate.WorkspaceId == client.WorkspaceId && candidate.Name == normalizedName, ct); if (duplicateClient) { AddError(request => request.Name, "A client with this name already exists in the active workspace."); await SendErrorsAsync(StatusCodes.Status409Conflict, ct); return; } client.Name = normalizedName; client.Status = normalizedStatus; client.PortraitUrl = string.IsNullOrWhiteSpace(normalizedPortraitUrl) ? null : normalizedPortraitUrl; client.PrimaryContactName = string.IsNullOrWhiteSpace(normalizedPrimaryContactName) ? null : normalizedPrimaryContactName; client.PrimaryContactEmail = string.IsNullOrWhiteSpace(normalizedPrimaryContactEmail) ? null : normalizedPrimaryContactEmail; client.PrimaryContactPortraitUrl = string.IsNullOrWhiteSpace(normalizedPrimaryContactPortraitUrl) ? null : normalizedPrimaryContactPortraitUrl; await clientsDbContext.SaveChangesAsync(ct); ClientDto dto = new( client.Id, client.WorkspaceId, client.Name, client.Status, client.PortraitUrl, client.PrimaryContactName, client.PrimaryContactEmail, client.PrimaryContactPortraitUrl); await SendOkAsync(dto, ct); } }