using FastEndpoints; using Microsoft.EntityFrameworkCore; using Socialize.Api.Data; using Socialize.Api.Modules.Comments.Data; using Socialize.Api.Modules.ContentItems.Data; using Socialize.Api.Infrastructure.Security; namespace Socialize.Api.Modules.Comments.Handlers; public record GetCommentsRequest(Guid ContentItemId); public record CommentDto( Guid Id, Guid WorkspaceId, Guid ContentItemId, Guid? ParentCommentId, Guid AuthorUserId, string AuthorDisplayName, string AuthorEmail, string? AuthorPortraitUrl, string Body, string? AttachmentFileName, string? AttachmentContentType, long? AttachmentSizeBytes, string? AttachmentBlobUrl, DateTimeOffset CreatedAt); public class GetCommentsHandler( AppDbContext dbContext, AccessScopeService accessScopeService) : Endpoint> { public override void Configure() { Get("/api/comments"); Options(o => o.WithTags("Comments")); } public override async Task HandleAsync(GetCommentsRequest request, CancellationToken ct) { ContentItem? item = await dbContext.ContentItems .SingleOrDefaultAsync(candidate => candidate.Id == request.ContentItemId, ct); if (item is null) { await SendNotFoundAsync(ct); return; } if (!await accessScopeService.CanReviewContentAsync(User, item.WorkspaceId, item.ClientId, item.CampaignId, ct)) { await SendForbiddenAsync(ct); return; } List comments = await dbContext.Comments .Where(comment => comment.ContentItemId == request.ContentItemId) .OrderBy(comment => comment.CreatedAt) .ToListAsync(ct); List authorIds = comments .Select(comment => comment.AuthorUserId) .Distinct() .ToList(); Dictionary authorPortraits = await dbContext.Users .Where(user => authorIds.Contains(user.Id)) .ToDictionaryAsync(user => user.Id, user => user.PortraitUrl, ct); List dtos = comments .Select(comment => new CommentDto( comment.Id, comment.WorkspaceId, comment.ContentItemId, comment.ParentCommentId, comment.AuthorUserId, comment.AuthorDisplayName, comment.AuthorEmail, authorPortraits.GetValueOrDefault(comment.AuthorUserId), comment.Body, comment.AttachmentFileName, comment.AttachmentContentType, comment.AttachmentSizeBytes, comment.AttachmentBlobUrl, comment.CreatedAt)) .ToList(); await SendOkAsync(dtos, ct); } }