using Hutopy.Infrastructure.Security; using Hutopy.Modules.Creators.Data; namespace Hutopy.Modules.Creators.Features; [PublicAPI] public sealed class GetCreatorBySlugRequest { public required string Name { get; set; } } [PublicAPI] public record GetCreatorBySlugResponse { public Guid Id { get; init; } public Guid CreatedBy { get; init; } public DateTimeOffset CreatedAt { get; init; } public Guid? DeletedBy { get; init; } public DateTimeOffset? DeletedAt { get; init; } public bool IsDeleted { get; init; } public bool Verified { get; init; } public bool AcceptDonation { get; init; } public string? BannerUrl { get; init; } public string? PortraitUrl { get; init; } public required string Slug { get; init; } public required string Name { get; init; } public string? Title { get; init; } public Socials? Socials { get; init; } public Presentation? Presentation { get; init; } } [UsedImplicitly] public sealed class GetCreatorBySlugRequestValidator : Validator { public GetCreatorBySlugRequestValidator() { RuleFor(r => r.Name) .NotNull().WithMessage("You should specify the Name") .NotEmpty().WithMessage("You should specify a valid/not empty Name"); } } [PublicAPI] public class GetCreatorBySlugHandler( CreatorsDbContext context) : Endpoint { public override void Configure() { Get("/api/creators/@{Name}"); Options((o => o.WithTags("Creators"))); AllowAnonymous(); } public override async Task HandleAsync( GetCreatorBySlugRequest req, CancellationToken ct) { var creatorName = req.Name.ToLower(); var response = await context .Creators .IgnoreQueryFilters() .Where(c => EF.Functions.ILike(c.Slug, creatorName)) .AsNoTracking() .Select(c => new GetCreatorBySlugResponse { Id = c.Id, CreatedBy = c.CreatedBy, CreatedAt = c.CreatedAt, DeletedBy = c.DeletedBy, DeletedAt = c.DeletedAt, IsDeleted = c.IsDeleted, Verified = c.Verified, BannerUrl = c.BannerUrl, PortraitUrl = c.PortraitUrl, Slug = c.Slug, Name = c.Name, Title = c.Title, AcceptDonation = c.IsStripeChargesEnabled && c.IsStripePayoutReady, Socials = c.Socials, Presentation = c.Presentation }) .SingleOrDefaultAsync(ct); if (response is null) { await SendNotFoundAsync(ct); return; } bool isOwner = User.Identity?.IsAuthenticated == true && User.GetUserId() == response.CreatedBy; if (response.IsDeleted && !isOwner) { await SendNotFoundAsync(ct); } else { await SendAsync(response, cancellation: ct); } } }