From 6dc4b29ebac261a26c5c44ff4da9dd620ea956a8 Mon Sep 17 00:00:00 2001 From: Laura Hausmann Date: Sat, 16 Mar 2024 18:22:46 +0100 Subject: [PATCH] [backend/federation] Correctly handle multiple pinned notes in the same thread --- .../Core/Services/NoteService.cs | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/Iceshrimp.Backend/Core/Services/NoteService.cs b/Iceshrimp.Backend/Core/Services/NoteService.cs index 4b769a99..7e05c3ac 100644 --- a/Iceshrimp.Backend/Core/Services/NoteService.cs +++ b/Iceshrimp.Backend/Core/Services/NoteService.cs @@ -45,8 +45,9 @@ public class NoteService( PollService pollSvc ) { - private readonly List _resolverHistory = []; - private int _recursionLimit = 100; + private const int DefaultRecursionLimit = 100; + private readonly List _resolverHistory = []; + private int _recursionLimit = DefaultRecursionLimit; public async Task CreateNoteAsync( User user, Note.NoteVisibility visibility, string? text = null, string? cw = null, Note? reply = null, @@ -538,7 +539,7 @@ public class NoteService( throw GracefulException.UnprocessableEntity("Cannot renote or quote a pure renote"); if (dbNote.Reply?.IsPureRenote ?? false) throw GracefulException.UnprocessableEntity("Cannot reply to a pure renote"); - + if (dbNote.Renote != null && dbNote.Renote.User != user) { if (await db.Blockings.AnyAsync(p => p.Blockee == user && p.Blocker == dbNote.Renote.User)) @@ -941,8 +942,16 @@ public class NoteService( return result.Where(p => p != null).Cast().ToList(); } - public async Task ResolveNoteAsync(string uri, ASNote? fetchedNote = null, User? user = null) + public async Task ResolveNoteAsync( + string uri, ASNote? fetchedNote = null, User? user = null, bool clearHistory = false + ) { + if (clearHistory) + { + _resolverHistory.Clear(); + _recursionLimit = DefaultRecursionLimit; + } + //TODO: is this enough to prevent DoS attacks? if (_recursionLimit-- <= 0) throw GracefulException.UnprocessableEntity("Refusing to resolve threads this long"); @@ -1155,7 +1164,9 @@ public class NoteService( if (collection is not { Items: not null }) return; var items = await collection.Items.Take(10).Select(p => objectResolver.ResolveObject(p)).AwaitAllAsync(); - var notes = await items.OfType().Select(p => ResolveNoteAsync(p.Id, p)).AwaitAllNoConcurrencyAsync(); + var notes = await items.OfType() + .Select(p => ResolveNoteAsync(p.Id, p, null, true)) + .AwaitAllNoConcurrencyAsync(); var previousPins = await db.Users.Where(p => p.Id == user.Id) .Select(p => p.PinnedNotes.Select(i => i.Id)) .FirstOrDefaultAsync() ?? [];