using FastEndpoints; using Microsoft.EntityFrameworkCore; using Socialize.Api.Data; using Socialize.Api.Infrastructure.BlobStorage.Contracts; using Socialize.Api.Infrastructure.Security; using Socialize.Api.Modules.Workspaces.Data; namespace Socialize.Api.Modules.Workspaces.Handlers; public record ChangeWorkspaceLogoRequest( IFormFile File); public record ChangeWorkspaceLogoResponse( string BlobUrl); public sealed class ChangeWorkspaceLogoRequestValidator : Validator { public ChangeWorkspaceLogoRequestValidator() { RuleFor(x => x.File) .NotNull() .NotEmpty(); } } public class ChangeWorkspaceLogoHandler( AppDbContext dbContext, IBlobStorage blobStorage, AccessScopeService accessScopeService) : Endpoint { public override void Configure() { Post("/api/workspaces/{id}/logo"); Options(o => o.WithTags("Workspaces")); AllowFileUploads(); } public override async Task HandleAsync(ChangeWorkspaceLogoRequest request, CancellationToken ct) { Guid id = Route("id"); Workspace? workspace = await dbContext.Workspaces.SingleOrDefaultAsync(candidate => candidate.Id == id, ct); if (workspace is null) { await SendNotFoundAsync(ct); return; } if (!await accessScopeService.CanManageWorkspaceAsync(User, workspace.Id, ct)) { await SendForbiddenAsync(ct); return; } string blobUrl = await blobStorage.UploadFileAsync( ContainerNames.Workspaces, $"{workspace.Id}/{SubDirectoryNames.Profile}/{CommonFileNames.LogoPicture}", request.File.OpenReadStream(), request.File.ContentType, ct); workspace.LogoUrl = blobUrl; await dbContext.SaveChangesAsync(ct); await SendOkAsync(new ChangeWorkspaceLogoResponse(blobUrl), ct); } }