diff --git a/PrivaPub.Tests/Domain/TimelineTests.cs b/PrivaPub.Tests/Domain/TimelineTests.cs
index 6420503..8673cc6 100644
--- a/PrivaPub.Tests/Domain/TimelineTests.cs
+++ b/PrivaPub.Tests/Domain/TimelineTests.cs
@@ -122,6 +122,26 @@ namespace PrivaPub.Tests.Domain
Assert.DoesNotContain("
parent
", (await Home(bobRoot, bob.Id)).Select(p => p.ContentHtml));
}
+ [Fact]
+ public async Task A_remote_delete_takes_the_post_out_of_home()
+ {
+ var (bobRoot, bob) = await _harness.Persona("bob");
+ var carol = new RemoteActor(_harness.Peer, "carol");
+ await Accepted(bobRoot, bob.Id, carol);
+ var create = Create(carol, text: "soon gone");
+ await _harness.Deliver(carol, "/human-centipede", create);
+ Assert.Single(await Home(bobRoot, bob.Id));
+
+ await _harness.Deliver(carol, "/human-centipede", new JsonObject
+ {
+ ["id"] = $"{new Uri(carol.Id).GetLeftPart(UriPartial.Authority)}/deletes/{Guid.NewGuid():N}", ["type"] = "Delete", ["actor"] = carol.Id,
+ ["object"] = new JsonObject { ["id"] = create["object"]!["id"]!.GetValue(), ["type"] = "Tombstone" }
+ });
+
+ Assert.Empty(await Home(bobRoot, bob.Id));
+ Assert.False(await DB.Default.Find().Match(e => e.AvatarId == bob.Id).ExecuteAnyAsync(TestContext.Current.CancellationToken));
+ }
+
[Fact]
public async Task A_mention_notifies_the_persona()
{
diff --git a/PrivaPub/Federation/Inbox/Handlers/DeleteHandler.cs b/PrivaPub/Federation/Inbox/Handlers/DeleteHandler.cs
index 7529b3b..b43d064 100644
--- a/PrivaPub/Federation/Inbox/Handlers/DeleteHandler.cs
+++ b/PrivaPub/Federation/Inbox/Handlers/DeleteHandler.cs
@@ -7,6 +7,7 @@ using PrivaPub.Federation.Rendering;
using PrivaPub.Models.Federation;
using PrivaPub.Models.Group;
using PrivaPub.Models.Post;
+using PrivaPub.Models.Social;
using PrivaPub.Models.User;
using PrivaPub.StaticServices;
@@ -56,11 +57,19 @@ namespace PrivaPub.Federation.Inbox.Handlers
if (follower.LocalActorKind == LocalActorKind.Group)
await RemoveForeignMember(follower.LocalActorId, actor.ActorURI, token);
}
+ await DB.Default.DeleteAsync(f => f.TargetActorURI == actor.ActorURI);
+ await DB.Default.DeleteAsync(e => e.AuthorAccountId == actor.ID);
return;
}
- await DB.Default.DeleteAsync(p => p.ObjectURI == objectUri && p.ActorURI == actor.ActorURI);
- return;
- }
+ var post = await _dbEntities.Posts.Match(p => p.ObjectURI == objectUri && p.ActorURI == actor.ActorURI).ExecuteFirstAsync(token);
+ if (post == default)
+ return;
+ await DB.Default.DeleteAsync(post.ID);
+ await DB.Default.DeleteAsync(e => e.PostId == post.ID || e.ReblogOfPostId == post.ID);
+ await DB.Default.DeleteAsync(p => p.ReblogOfPostId == post.ID);
+ if (!string.IsNullOrEmpty(post.AnsweringToPostId))
+ await DB.Default.Update().MatchID(post.AnsweringToPostId).Modify(b => b.Inc(p => p.RepliesCount, -1)).ExecuteAsync(token);
+ }
}
}