[backend/api] Fix unpaginated remote emoji lookup

This commit is contained in:
Laura Hausmann 2025-02-06 19:30:58 +01:00
parent 014f35af6c
commit e5c2edf8cb
No known key found for this signature in database
GPG key ID: D044E84C5BE01605
5 changed files with 49 additions and 31 deletions

View file

@ -1,8 +1,10 @@
using System.Net; using System.Net;
using System.Net.Mime; using System.Net.Mime;
using Iceshrimp.Backend.Controllers.Shared.Attributes; using Iceshrimp.Backend.Controllers.Shared.Attributes;
using Iceshrimp.Backend.Controllers.Shared.Schemas;
using Iceshrimp.Backend.Core.Configuration; using Iceshrimp.Backend.Core.Configuration;
using Iceshrimp.Backend.Core.Database; using Iceshrimp.Backend.Core.Database;
using Iceshrimp.Backend.Core.Extensions;
using Iceshrimp.Backend.Core.Middleware; using Iceshrimp.Backend.Core.Middleware;
using Iceshrimp.Backend.Core.Services; using Iceshrimp.Backend.Core.Services;
using Iceshrimp.Shared.Schemas.Web; using Iceshrimp.Shared.Schemas.Web;
@ -46,25 +48,28 @@ public class EmojiController(
.ToListAsync(); .ToListAsync();
} }
[HttpGet("remote")] [HttpGet("remote/{host?}")]
[Authorize("role:moderator")] [Authorize("role:moderator")]
[RestPagination(100, 500)]
[ProducesResults(HttpStatusCode.OK)] [ProducesResults(HttpStatusCode.OK)]
public async Task<IEnumerable<EmojiResponse>> GetRemoteEmoji() public async Task<PaginationWrapper<List<EmojiResponse>>> GetRemoteEmoji(string? host, PaginationQuery pq)
{ {
return await db.Emojis var res = await db.Emojis
.Where(p => p.Host != null) .Where(p => host == null ? p.Host != null : p.Host == host)
.Select(p => new EmojiResponse .Select(p => new EmojiResponse
{ {
Id = p.Id, Id = p.Id,
Name = p.Name, Name = p.Name,
Uri = p.Uri, Uri = p.Uri,
Aliases = p.Aliases, Aliases = p.Aliases,
Category = p.Host, Category = p.Host,
PublicUrl = p.GetAccessUrl(instance.Value), PublicUrl = p.GetAccessUrl(instance.Value),
License = p.License, License = p.License,
Sensitive = p.Sensitive Sensitive = p.Sensitive
}) })
.ToListAsync(); .ToListAsync();
return HttpContext.CreatePaginationWrapper(pq, res);
} }
[HttpGet("{id}")] [HttpGet("{id}")]
@ -72,8 +77,8 @@ public class EmojiController(
[ProducesErrors(HttpStatusCode.NotFound)] [ProducesErrors(HttpStatusCode.NotFound)]
public async Task<EmojiResponse> GetEmoji(string id) public async Task<EmojiResponse> GetEmoji(string id)
{ {
var emoji = await db.Emojis.FirstOrDefaultAsync(p => p.Id == id) ?? var emoji = await db.Emojis.FirstOrDefaultAsync(p => p.Id == id)
throw GracefulException.NotFound("Emoji not found"); ?? throw GracefulException.NotFound("Emoji not found");
return new EmojiResponse return new EmojiResponse
{ {
@ -155,8 +160,8 @@ public class EmojiController(
public async Task<EmojiResponse> UpdateEmoji(string id, UpdateEmojiRequest request) public async Task<EmojiResponse> UpdateEmoji(string id, UpdateEmojiRequest request)
{ {
var emoji = await emojiSvc.UpdateLocalEmojiAsync(id, request.Name, request.Aliases, request.Category, var emoji = await emojiSvc.UpdateLocalEmojiAsync(id, request.Name, request.Aliases, request.Category,
request.License, request.Sensitive) ?? request.License, request.Sensitive)
throw GracefulException.NotFound("Emoji not found"); ?? throw GracefulException.NotFound("Emoji not found");
return new EmojiResponse return new EmojiResponse
{ {

View file

@ -1,12 +1,11 @@
using Iceshrimp.Shared.Helpers;
namespace Iceshrimp.Backend.Core.Database; namespace Iceshrimp.Backend.Core.Database;
public interface IEntity public interface IEntity : IIdentifiable;
{
public string Id { get; }
}
public class EntityWrapper<T> : IEntity public class EntityWrapper<T> : IEntity
{ {
public required T Entity { get; init; } public required T Entity { get; init; }
public required string Id { get; init; } public required string Id { get; init; }
} }

View file

@ -2,6 +2,7 @@ using Iceshrimp.Backend.Controllers.Shared.Attributes;
using Iceshrimp.Backend.Controllers.Shared.Schemas; using Iceshrimp.Backend.Controllers.Shared.Schemas;
using Iceshrimp.Backend.Core.Database; using Iceshrimp.Backend.Core.Database;
using Iceshrimp.Backend.Core.Middleware; using Iceshrimp.Backend.Core.Middleware;
using Iceshrimp.Shared.Helpers;
using Iceshrimp.Shared.Schemas.Web; using Iceshrimp.Shared.Schemas.Web;
using Microsoft.AspNetCore.Http.Extensions; using Microsoft.AspNetCore.Http.Extensions;
@ -10,7 +11,7 @@ namespace Iceshrimp.Backend.Core.Extensions;
public static partial class HttpContextExtensions public static partial class HttpContextExtensions
{ {
public static PaginationWrapper<TData> CreatePaginationWrapper<TData>( public static PaginationWrapper<TData> CreatePaginationWrapper<TData>(
this HttpContext ctx, PaginationQuery query, IEnumerable<IEntity> paginationData, TData data this HttpContext ctx, PaginationQuery query, IEnumerable<IIdentifiable> paginationData, TData data
) )
{ {
var attr = ctx.GetEndpoint()?.Metadata.GetMetadata<RestPaginationAttribute>(); var attr = ctx.GetEndpoint()?.Metadata.GetMetadata<RestPaginationAttribute>();
@ -37,7 +38,7 @@ public static partial class HttpContextExtensions
public static PaginationWrapper<TData> CreatePaginationWrapper<TData>( public static PaginationWrapper<TData> CreatePaginationWrapper<TData>(
this HttpContext ctx, PaginationQuery query, TData data this HttpContext ctx, PaginationQuery query, TData data
) where TData : IEnumerable<IEntity> ) where TData : IEnumerable<IIdentifiable>
{ {
return CreatePaginationWrapper(ctx, query, data, data); return CreatePaginationWrapper(ctx, query, data, data);
} }

View file

@ -10,8 +10,11 @@ internal class EmojiControllerModel(ApiClient api)
public Task<List<EmojiResponse>> GetAllEmojiAsync() => public Task<List<EmojiResponse>> GetAllEmojiAsync() =>
api.CallAsync<List<EmojiResponse>>(HttpMethod.Get, "/emoji"); api.CallAsync<List<EmojiResponse>>(HttpMethod.Get, "/emoji");
public Task<List<EmojiResponse>> GetRemoteEmojiAsync() => public Task<PaginationWrapper<List<EmojiResponse>>> GetRemoteEmojiAsync(PaginationQuery pq) =>
api.CallAsync<List<EmojiResponse>>(HttpMethod.Get, "/emoji/remote"); api.CallAsync<PaginationWrapper<List<EmojiResponse>>>(HttpMethod.Get, "/emoji/remote", pq);
public Task<PaginationWrapper<List<EmojiResponse>>> GetRemoteEmojiAsync(string instance, PaginationQuery pq) =>
api.CallAsync<PaginationWrapper<List<EmojiResponse>>>(HttpMethod.Get, $"/emoji/remote/{instance}", pq);
public Task<EmojiResponse> UploadEmojiAsync(IBrowserFile file, string? name) => public Task<EmojiResponse> UploadEmojiAsync(IBrowserFile file, string? name) =>
api.CallAsync<EmojiResponse>(HttpMethod.Post, "/emoji", api.CallAsync<EmojiResponse>(HttpMethod.Post, "/emoji",
@ -31,4 +34,4 @@ internal class EmojiControllerModel(ApiClient api)
public Task<EmojiResponse?> GetEmojiAsync(string id) => public Task<EmojiResponse?> GetEmojiAsync(string id) =>
api.CallNullableAsync<EmojiResponse>(HttpMethod.Get, $"/emoji/{id}"); api.CallNullableAsync<EmojiResponse>(HttpMethod.Get, $"/emoji/{id}");
} }

View file

@ -106,7 +106,17 @@
{ {
State = State.Loading; State = State.Loading;
Emojis = Source == "remote" ? await Api.Emoji.GetRemoteEmojiAsync() : await Api.Emoji.GetAllEmojiAsync(); if (Source == "remote")
{
//TODO: impolement proper pagination
var res = await Api.Emoji.GetRemoteEmojiAsync(new PaginationQuery());
Emojis = res.Data;
}
else
{
Emojis = await Api.Emoji.GetAllEmojiAsync();
}
if (Emojis.Count == 0) if (Emojis.Count == 0)
{ {
State = State.Empty; State = State.Empty;