using MongoDB.Entities; using PrivaPub.Domain.Relationships; using PrivaPub.Models.Federation; using PrivaPub.Models.Social; using PrivaPub.Tests.Support; using System.Text.Json.Nodes; namespace PrivaPub.Tests.Federation { // A remote account's Block of a persona, as Mastodon sends it (the pasture's last Mastodon expected failure, G-0002) [Trait("Category", "Integration")] public sealed class InboundBlockTests : IAsyncLifetime { Harness _harness; public async ValueTask InitializeAsync() { Assert.SkipUnless(MongoFixture.Enabled, MongoFixture.Skip); _harness = await Harness.Start(); } public async ValueTask DisposeAsync() { if (_harness != default) await _harness.DisposeAsync(); } static string Origin(RemoteActor actor) => new Uri(actor.Id).GetLeftPart(UriPartial.Authority); [Fact] public async Task A_block_ends_the_follows_both_ways_hides_the_blocker_and_its_undo_lifts_it() { var token = TestContext.Current.CancellationToken; var (_, alice) = await _harness.Persona("alice"); var carol = new RemoteActor(_harness.Peer, "carol"); await _harness.FollowedBy(alice, carol); await DB.Default.SaveAsync(new Following { AvatarId = alice.Id, TargetActorURI = carol.Id, State = FollowState.Accepted }, token); var block = new JsonObject { ["id"] = $"{Origin(carol)}/blocks/{Guid.NewGuid():N}", ["type"] = "Block", ["actor"] = carol.Id, ["object"] = alice.Uri }; await _harness.Deliver(carol, $"/peasants/{alice.UserName}/mouth", block); Assert.True(await DB.Default.Find().Match(b => b.AvatarId == alice.Id && b.ActorURI == carol.Id).ExecuteAnyAsync(token)); Assert.False(await DB.Default.Find().Match(f => f.LocalActorId == alice.Id && f.ActorURI == carol.Id).ExecuteAnyAsync(token)); Assert.False(await DB.Default.Find().Match(f => f.AvatarId == alice.Id && f.TargetActorURI == carol.Id).ExecuteAnyAsync(token)); Assert.Contains(carol.Id, await Hidden.AuthorsHiddenFrom(alice.Id, new[] { carol.Id }, forNotifications: false, token)); Assert.Contains(alice.Id, await Hidden.RecipientsHiding(new[] { alice.Id }, carol.Id, token)); await _harness.Deliver(carol, $"/peasants/{alice.UserName}/mouth", new JsonObject { ["id"] = $"{Origin(carol)}/undos/{Guid.NewGuid():N}", ["type"] = "Undo", ["actor"] = carol.Id, ["object"] = block }); Assert.False(await DB.Default.Find().Match(b => b.AvatarId == alice.Id && b.ActorURI == carol.Id).ExecuteAnyAsync(token)); Assert.Empty(await Hidden.AuthorsHiddenFrom(alice.Id, new[] { carol.Id }, forNotifications: false, token)); } [Fact] public async Task A_block_of_someone_who_is_not_ours_is_dropped() { var token = TestContext.Current.CancellationToken; var carol = new RemoteActor(_harness.Peer, "carol"); await _harness.Deliver(carol, "/human-centipede", new JsonObject { ["id"] = $"{Origin(carol)}/blocks/{Guid.NewGuid():N}", ["type"] = "Block", ["actor"] = carol.Id, ["object"] = $"{Origin(carol)}/users/somebody-else" }); Assert.False(await DB.Default.Find().Match(b => b.ActorURI == carol.Id).ExecuteAnyAsync(token)); } } }