From eb7f160b2398a556be6a51961430ab3da6fa805c Mon Sep 17 00:00:00 2001 From: Laura Hausmann Date: Fri, 9 Feb 2024 11:37:38 +0100 Subject: [PATCH] [backend/federation] Handle note delete activities (ISH-12) --- .../ActivityPub/ActivityHandlerService.cs | 11 +++++++-- .../Core/Services/NoteService.cs | 24 +++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/Iceshrimp.Backend/Core/Federation/ActivityPub/ActivityHandlerService.cs b/Iceshrimp.Backend/Core/Federation/ActivityPub/ActivityHandlerService.cs index 5ac12cd1..59f1f8fb 100644 --- a/Iceshrimp.Backend/Core/Federation/ActivityPub/ActivityHandlerService.cs +++ b/Iceshrimp.Backend/Core/Federation/ActivityPub/ActivityHandlerService.cs @@ -33,12 +33,19 @@ public class ActivityHandlerService( switch (activity) { case ASCreate: { - //TODO: implement the rest + //TODO: should we handle other types of creates? if (activity.Object is not ASNote note) throw GracefulException.UnprocessableEntity("Create activity object is invalid"); await noteSvc.ProcessNoteAsync(note, activity.Actor); return; } + case ASDelete: { + //TODO: handle user deletes + if (activity.Object is not ASNote note) + throw GracefulException.UnprocessableEntity("Delete activity object is invalid"); + await noteSvc.DeleteNoteAsync(note, activity.Actor); + return; + } case ASFollow: { if (activity.Object is not { } obj) throw GracefulException.UnprocessableEntity("Follow activity object is invalid"); @@ -64,7 +71,7 @@ public class ActivityHandlerService( return; } case ASUndo: { - //TODO: implement the rest + //TODO: what other types of undo objects are there? if (activity.Object is not ASActivity { Type: ASActivity.Types.Follow, Object: not null } undoActivity) throw new NotImplementedException("Unsupported undo operation"); await UnfollowAsync(undoActivity.Object, activity.Actor); diff --git a/Iceshrimp.Backend/Core/Services/NoteService.cs b/Iceshrimp.Backend/Core/Services/NoteService.cs index 88efa21e..136d2048 100644 --- a/Iceshrimp.Backend/Core/Services/NoteService.cs +++ b/Iceshrimp.Backend/Core/Services/NoteService.cs @@ -61,6 +61,30 @@ public class NoteService( return note; } + public async Task DeleteNoteAsync(ASNote note, ASActor actor) { + // ReSharper disable once EntityFramework.NPlusOne.IncompleteDataQuery (it doesn't know about IncludeCommonProperties()) + var dbNote = await db.Notes.IncludeCommonProperties().FirstOrDefaultAsync(p => p.Uri == note.Id); + if (dbNote == null) { + logger.LogDebug("Note '{id}' isn't known, skipping", note.Id); + return; + } + + var user = await userResolver.ResolveAsync(actor.Id); + + // ReSharper disable once EntityFramework.NPlusOne.IncompleteDataUsage (same reason as above) + if (dbNote.User != user) { + logger.LogDebug("Note '{id}' isn't owned by actor requesting its deletion, skipping", note.Id); + return; + } + + logger.LogDebug("Deleting note '{id}' owned by {userId}", note.Id, user.Id); + + user.NotesCount--; + db.Remove(dbNote); + + await db.SaveChangesAsync(); + } + public async Task ProcessNoteAsync(ASNote note, ASActor actor) { var dbHit = await db.Notes.IncludeCommonProperties().FirstOrDefaultAsync(p => p.Uri == note.Id);