using Hutopy.Infrastructure.Security; using Hutopy.Modules.Contents.Data; namespace Hutopy.Modules.Contents.Features; [PublicAPI] public record RemovePhotoFromAlbumRequest( Guid AlbumId, Guid PhotoId); [PublicAPI] public sealed class RemovePhotoFromAlbumRequestValidator : Validator { public RemovePhotoFromAlbumRequestValidator() { RuleFor(x => x.AlbumId) .NotNull() .NotEmpty(); RuleFor(x => x.PhotoId) .NotNull() .NotEmpty(); } } [PublicAPI] public class RemovePhotoFromAlbumHandler( ContentsDbContext context) : Endpoint { public override void Configure() { Delete("/api/albums/{AlbumId}/photos/{PhotoId}"); Options(o => o.WithTags("Albums")); } public override async Task HandleAsync( RemovePhotoFromAlbumRequest request, CancellationToken ct) { Guid userId = User.GetUserId(); Album? album = await context .Albums .Include(a => a.Photos) .SingleOrDefaultAsync( a => a.Id == request.AlbumId && a.CreatedBy == userId, ct); if (album is null) { await SendNotFoundAsync(ct); return; } AlbumPhoto? photo = album.Photos .SingleOrDefault(p => p.Id == request.PhotoId); if (photo is null) { await SendNotFoundAsync(ct); return; } // Soft delete the photo photo.DeletedBy = userId; photo.DeletedAt = DateTimeOffset.UtcNow; await context.SaveChangesAsync(ct); await SendNoContentAsync(ct); } }