using Hutopy.Infrastructure.BlobStorage.Contracts; using Hutopy.Modules.Creators.Data; namespace Hutopy.Modules.Creators.Features; [PublicAPI] public record ChangeLogoRequest( Guid CreatorId, IFormFile File); [PublicAPI] public record ChangeLogoResponse( string BlobUrl); [PublicAPI] public sealed class ChangeLogoRequestValidator : Validator { public ChangeLogoRequestValidator() { RuleFor(x => x.CreatorId) .NotNull() .NotEmpty(); RuleFor(x => x.File) .NotNull() .NotEmpty(); } } [PublicAPI] public class ChangeLogoHandler( CreatorsDbContext context, IBlobStorage blobStorage) : Endpoint { public override void Configure() { Post("/api/creators/{CreatorId}/logo"); Options(o => o.WithTags("Creators")); AllowFileUploads(); } public override async Task HandleAsync( ChangeLogoRequest request, CancellationToken ct) { Creator? creator = await context .Creators .SingleOrDefaultAsync( c => c.Id == request.CreatorId, ct); if (creator is null) { await SendNotFoundAsync(ct); return; } string blobUrl = await blobStorage.UploadFileAsync( ContainerNames.Creators, $"{request.CreatorId}/{SubDirectoryNames.Profile}/{CommonFileNames.ProfilePicture}", request.File.OpenReadStream(), request.File.ContentType, ct); creator.PortraitUrl = $"{blobUrl}?t={DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}"; await context.SaveChangesAsync(ct); await SendOkAsync( new ChangeLogoResponse(blobUrl), ct); } }