[backend/api] Add pagination data to note likes and note renotes responses

This commit is contained in:
Laura Hausmann 2024-09-28 01:13:25 +02:00 committed by Lilian
parent 2078ce3747
commit 55530f482d
No known key found for this signature in database
4 changed files with 48 additions and 42 deletions

View file

@ -217,24 +217,27 @@ public class NoteController(
[HttpGet("{id}/likes")] [HttpGet("{id}/likes")]
[Authenticate] [Authenticate]
[Authorize] [Authorize]
[LinkPagination(20, 40)]
[ProducesResults(HttpStatusCode.OK)] [ProducesResults(HttpStatusCode.OK)]
[ProducesErrors(HttpStatusCode.NotFound)] [ProducesErrors(HttpStatusCode.NotFound)]
public async Task<IEnumerable<UserResponse>> GetNoteLikes(string id) public async Task<IEnumerable<UserResponse>> GetNoteLikes(string id, PaginationQuery pq)
{ {
var user = HttpContext.GetUser(); var user = HttpContext.GetUser();
var note = await db.Notes var note = await db.Notes
.Where(p => p.Id == id) .Where(p => p.Id == id)
.EnsureVisibleFor(user) .EnsureVisibleFor(user)
.FirstOrDefaultAsync() ?? .FirstOrDefaultAsync() ??
throw GracefulException.NotFound("Note not found"); throw GracefulException.NotFound("Note not found");
var users = await db.NoteLikes var users = await db.NoteLikes
.Where(p => p.Note == note) .Where(p => p.Note == note)
.Include(p => p.User.UserProfile) .Include(p => p.User.UserProfile)
.Select(p => p.User) .Paginate(pq, ControllerContext)
.ToListAsync(); .Wrap(p => p.User)
.ToListAsync();
return await userRenderer.RenderMany(users); HttpContext.SetPaginationData(users);
return await userRenderer.RenderMany(users.Select(p => p.Entity));
} }
[HttpPost("{id}/renote")] [HttpPost("{id}/renote")]
@ -278,26 +281,29 @@ public class NoteController(
[HttpGet("{id}/renotes")] [HttpGet("{id}/renotes")]
[Authenticate] [Authenticate]
[Authorize] [Authorize]
[LinkPagination(20, 40)]
[ProducesResults(HttpStatusCode.OK)] [ProducesResults(HttpStatusCode.OK)]
[ProducesErrors(HttpStatusCode.NotFound)] [ProducesErrors(HttpStatusCode.NotFound)]
public async Task<IEnumerable<UserResponse>> GetRenotes(string id) public async Task<IEnumerable<UserResponse>> GetRenotes(string id, PaginationQuery pq)
{ {
var user = HttpContext.GetUser(); var user = HttpContext.GetUser();
var note = await db.Notes var note = await db.Notes
.Where(p => p.Id == id) .Where(p => p.Id == id)
.EnsureVisibleFor(user) .EnsureVisibleFor(user)
.FirstOrDefaultAsync() ?? .FirstOrDefaultAsync() ??
throw GracefulException.NotFound("Note not found"); throw GracefulException.NotFound("Note not found");
var users = await db.Notes var users = await db.Notes
.Where(p => p.Renote == note && p.IsPureRenote) .Where(p => p.Renote == note && p.IsPureRenote)
.EnsureVisibleFor(user) .EnsureVisibleFor(user)
.Include(p => p.User.UserProfile) .Include(p => p.User.UserProfile)
.FilterHidden(user, db) .FilterHidden(user, db)
.Select(p => p.User) .Paginate(pq, ControllerContext)
.ToListAsync(); .Wrap(p => p.User)
.ToListAsync();
return await userRenderer.RenderMany(users); HttpContext.SetPaginationData(users);
return await userRenderer.RenderMany(users.Select(p => p.Entity));
} }
[HttpGet("{id}/quotes")] [HttpGet("{id}/quotes")]
@ -311,21 +317,21 @@ public class NoteController(
var user = HttpContext.GetUser(); var user = HttpContext.GetUser();
var note = await db.Notes var note = await db.Notes
.Where(p => p.Id == id) .Where(p => p.Id == id)
.EnsureVisibleFor(user) .EnsureVisibleFor(user)
.FirstOrDefaultAsync() ?? .FirstOrDefaultAsync() ??
throw GracefulException.NotFound("Note not found"); throw GracefulException.NotFound("Note not found");
var renotes = await db.Notes var renotes = await db.Notes
.Where(p => p.Renote == note && p.IsQuote) .Where(p => p.Renote == note && p.IsQuote)
.Include(p => p.User.UserProfile) .Include(p => p.User.UserProfile)
.EnsureVisibleFor(user) .EnsureVisibleFor(user)
.FilterHidden(user, db) .FilterHidden(user, db)
.Paginate(pq, ControllerContext) .Paginate(pq, ControllerContext)
.ToListAsync(); .ToListAsync();
return await noteRenderer.RenderMany(renotes.EnforceRenoteReplyVisibility(), user, return await noteRenderer.RenderMany(renotes.EnforceRenoteReplyVisibility(), user,
Filter.FilterContext.Threads); Filter.FilterContext.Threads);
} }
[HttpPost("{id}/react/{name}")] [HttpPost("{id}/react/{name}")]

View file

@ -8,7 +8,7 @@ namespace Iceshrimp.Backend.Core.Database.Tables;
[Index(nameof(UserId))] [Index(nameof(UserId))]
[Index(nameof(NoteId))] [Index(nameof(NoteId))]
[Index(nameof(UserId), nameof(NoteId), IsUnique = true)] [Index(nameof(UserId), nameof(NoteId), IsUnique = true)]
public class NoteLike public class NoteLike : IEntity
{ {
[Key] [Key]
[Column("id")] [Column("id")]

View file

@ -360,6 +360,13 @@ public static class QueryableExtensions
return Paginate(query, pq, filter.DefaultLimit, filter.MaxLimit); return Paginate(query, pq, filter.DefaultLimit, filter.MaxLimit);
} }
public static IQueryable<EntityWrapper<TResult>> Wrap<TSource, TResult>(
this IQueryable<TSource> query, Expression<Func<TSource, TResult>> predicate
) where TSource : IEntity
{
return query.Select(p => new EntityWrapper<TResult> { Id = p.Id, Entity = predicate.Compile().Invoke(p) });
}
public static IQueryable<Note> HasVisibility(this IQueryable<Note> query, Note.NoteVisibility visibility) public static IQueryable<Note> HasVisibility(this IQueryable<Note> query, Note.NoteVisibility visibility)
{ {
return query.Where(note => note.Visibility == visibility); return query.Where(note => note.Visibility == visibility);

View file

@ -1,7 +0,0 @@
namespace Iceshrimp.Shared.Schemas.Web;
public class PaginationWrapper<T>
{
public required string Id { get; set; }
public required T Entity { get; set; }
}