Files
social-media/backend/src/Socialize.Api/Modules/Clients/Handlers/ChangeClientPortrait.cs

69 lines
2.0 KiB
C#

using FastEndpoints;
using Microsoft.EntityFrameworkCore;
using Socialize.Api.Data;
using Socialize.Api.Infrastructure.BlobStorage.Contracts;
using Socialize.Api.Infrastructure.Security;
using Socialize.Api.Modules.Clients.Data;
namespace Socialize.Api.Modules.Clients.Handlers;
public record ChangeClientPortraitRequest(
IFormFile File);
public record ChangeClientPortraitResponse(
string BlobUrl);
public sealed class ChangeClientPortraitRequestValidator : Validator<ChangeClientPortraitRequest>
{
public ChangeClientPortraitRequestValidator()
{
RuleFor(x => x.File)
.NotNull()
.NotEmpty();
}
}
public class ChangeClientPortraitHandler(
AppDbContext clientsDbContext,
IBlobStorage blobStorage,
AccessScopeService accessScopeService)
: Endpoint<ChangeClientPortraitRequest, ChangeClientPortraitResponse>
{
public override void Configure()
{
Post("/api/clients/{id}/portrait");
Options(o => o.WithTags("Clients"));
AllowFileUploads();
}
public override async Task HandleAsync(ChangeClientPortraitRequest request, CancellationToken ct)
{
Guid id = Route<Guid>("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 blobUrl = await blobStorage.UploadFileAsync(
ContainerNames.Clients,
$"{client.Id}/{SubDirectoryNames.Profile}/{CommonFileNames.LogoPicture}",
request.File.OpenReadStream(),
request.File.ContentType,
ct);
client.PortraitUrl = blobUrl;
await clientsDbContext.SaveChangesAsync(ct);
await SendOkAsync(new ChangeClientPortraitResponse(blobUrl), ct);
}
}