using Hutopy.Infrastructure.Security; using Hutopy.Modules.Creators.Data; namespace Hutopy.Modules.Creators.Features; [PublicAPI] public record CreateCreatorRequest( Guid SlugReservationId, Guid CreatorId); [PublicAPI] public sealed class CreateCreatorRequestValidator : Validator { public CreateCreatorRequestValidator() { RuleFor(r => r.SlugReservationId) .NotNull() .NotEmpty() .WithMessage("You should specify a valid SlugReservationId"); RuleFor(r => r.CreatorId) .NotNull() .NotEmpty() .WithMessage("You should specify a valid CreatorId"); } } [PublicAPI] public sealed class CreateCreatorHandler( CreatorsDbContext context) : Endpoint { public override void Configure() { Post("/api/creators"); Options(o => o.WithTags("Creators")); } public override async Task HandleAsync( CreateCreatorRequest req, CancellationToken ct) { await using var transaction = await context.Database.BeginTransactionAsync(ct); try { var slug = await context .Slugs .SingleAsync(s => s.Id == req.SlugReservationId, ct); if (slug.UsedBy is not null || slug.ReservedUntil < DateTimeOffset.UtcNow || slug.CreatedBy != User.GetUserId()) { await SendErrorsAsync(500, ct); return; } slug.UsedBy = req.CreatorId; await context.Creators.AddAsync( new Creator { Id = req.CreatorId, CreatedBy = User.GetUserId(), Name = slug.Name, Slug = slug.NormalizedName }, ct); await context.SaveChangesAsync(ct); await transaction.CommitAsync(ct); await SendOkAsync(ct); } catch (Exception) { await transaction.RollbackAsync(ct); } } }