using MongoDB.Entities; using PrivaPub.Federation.Objects; using PrivaPub.Models.Federation; using PrivaPub.Models.Jobs; using PrivaPub.Tests.Support; using System.Text.Json.Nodes; namespace PrivaPub.Tests.Federation { [Trait("Category", "Integration")] public sealed class ProvenanceTests : 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(); } [Fact] public async Task A_delivered_post_keeps_its_raw_object_how_it_came_and_every_edit() { var token = TestContext.Current.CancellationToken; var (_, alice) = await _harness.Persona("alice"); var mallory = new RemoteActor(_harness.Peer, "mallory"); var origin = new Uri(mallory.Id).GetLeftPart(UriPartial.Authority); var note = new JsonObject { ["id"] = $"{origin}/notes/{Guid.NewGuid():N}", ["type"] = "Note", ["attributedTo"] = mallory.Id, ["content"] = "

hi

", ["_misskey_quote"] = $"{origin}/notes/elsewhere", ["to"] = new JsonArray(Addressing.Public), ["cc"] = new JsonArray(alice.Uri), ["tag"] = new JsonArray(new JsonObject { ["type"] = "Mention", ["href"] = alice.Uri, ["name"] = "@alice" }) }; var create = new JsonObject { ["id"] = $"{origin}/activities/{Guid.NewGuid():N}", ["type"] = "Create", ["actor"] = mallory.Id, ["object"] = note.DeepClone() }; await _harness.Deliver(mallory, "/human-centipede", create); var edited = note.DeepClone().AsObject(); edited["content"] = "

hi again

"; edited["updated"] = DateTime.UtcNow.ToString("O"); await _harness.Deliver(mallory, "/human-centipede", new JsonObject { ["id"] = $"{origin}/activities/{Guid.NewGuid():N}", ["type"] = "Update", ["actor"] = mallory.Id, ["object"] = edited }); var record = await DB.Default.Find().Match(r => r.ObjectURI == note["id"]!.GetValue()).ExecuteFirstAsync(token); Assert.NotNull(record); Assert.Equal(ObjectPath.Delivered, record.Path); Assert.False(record.Refetched); Assert.Equal("shared", record.Inbox); Assert.Equal(mallory.KeyId, record.KeyId); Assert.Equal(create["id"]!.GetValue(), record.ActivityId); Assert.Contains("digest", record.SignedHeaders); Assert.Equal("

hi

", JsonNode.Parse(record.Raw)!["content"]!.GetValue()); Assert.Contains("legacy-quote", ObjectFeatures.Detect(JsonNode.Parse(record.Raw)!.AsObject())); Assert.Equal("

hi again

", JsonNode.Parse(Assert.Single(record.Revisions).Raw)!["content"]!.GetValue()); Assert.True(await DB.Default.Find().Match(j => j.Kind == JobKind.DescribeInstance && j.Payload == record.Host).ExecuteAnyAsync(token)); } } }