98 lines
4.0 KiB
C#
98 lines
4.0 KiB
C#
using Microsoft.Extensions.Caching.Memory;
|
|||
|
|
using Microsoft.Extensions.Localization;
|
||
|
|
using Microsoft.Extensions.Logging.Abstractions;
|
||
|
|
|
||
|
|
using MongoDB.Entities;
|
||
|
|
|
||
|
|
using PrivaPub.Domain.Social;
|
||
|
|
using PrivaPub.Federation.Actors;
|
||
|
|
using PrivaPub.Federation.Inbox;
|
||
|
|
using PrivaPub.Federation.Inbox.Handlers;
|
||
|
|
using PrivaPub.Federation.Outbox;
|
||
|
|
using PrivaPub.Infrastructure.Jobs;
|
||
|
|
using PrivaPub.Models;
|
||
|
|
using PrivaPub.Models.Jobs;
|
||
|
|
using PrivaPub.Models.User;
|
||
|
|
using PrivaPub.Resources;
|
||
|
|
using PrivaPub.StaticServices;
|
||
|
|
|
||
|
|
using System.Text.Json;
|
||
|
|
using System.Text.Json.Nodes;
|
||
|
|
|
||
|
|
namespace PrivaPub.Tests.Support
|
||
|
|
{
|
||
|
|
public sealed class Harness : IAsyncDisposable
|
||
|
|
{
|
||
|
|
public const string Host = "privapub.test";
|
||
|
|
public const string Base = "https://" + Host;
|
||
|
|
|
||
|
|
Harness(Peer peer)
|
||
|
|
{
|
||
|
|
Peer = peer;
|
||
|
|
var cache = new MemoryCache(new MemoryCacheOptions());
|
||
|
|
Local = new LocalActorService(Db, new StaticOptions<AppConfiguration>(new AppConfiguration { BackendBaseAddress = Base }));
|
||
|
|
Remote = new RemoteActorService(Peer.Http(cache), Local, cache, Db);
|
||
|
|
Delivery = new DeliveryService(Db, Queue);
|
||
|
|
Receiver = new InboxReceiver(Local, Remote, Queue, new NoBlocks(), NullLogger<InboxReceiver>.Instance);
|
||
|
|
Processor = new InboxProcessor(Remote, new IActivityHandler[]
|
||
|
|
{
|
||
|
|
new FollowHandler(Db, Local, Remote, Delivery),
|
||
|
|
new AcceptHandler(Db, Local),
|
||
|
|
new RejectHandler(Db, Local),
|
||
|
|
new UndoHandler(Db, Local, Remote, Delivery),
|
||
|
|
new CreateHandler(Db, Local, Remote, Delivery, new NoBlocks()),
|
||
|
|
new DeleteHandler(Db, Local, Remote, Delivery),
|
||
|
|
new UpdateHandler(Db, Local, Remote)
|
||
|
|
}, NullLogger<InboxProcessor>.Instance);
|
||
|
|
Follows = new FollowService(Db, Local, Remote, Delivery, new KeyLocalizer<GenericRes>(), NullLogger<FollowService>.Instance);
|
||
|
|
}
|
||
|
|
|
||
|
|
public Peer Peer { get; }
|
||
|
|
public DbEntities Db { get; } = new();
|
||
|
|
public JobQueue Queue { get; } = new();
|
||
|
|
public LocalActorService Local { get; }
|
||
|
|
public RemoteActorService Remote { get; }
|
||
|
|
public DeliveryService Delivery { get; }
|
||
|
|
public InboxReceiver Receiver { get; }
|
||
|
|
public InboxProcessor Processor { get; }
|
||
|
|
public FollowService Follows { get; }
|
||
|
|
|
||
|
|
public static async Task<Harness> Start() => new(await Peer.Start());
|
||
|
|
|
||
|
|
public async Task<(string RootId, LocalActor Avatar)> Persona(string name, string rootId = default)
|
||
|
|
{
|
||
|
|
rootId ??= Guid.NewGuid().ToString("N")[..24];
|
||
|
|
var (privateKey, publicKey) = Keys.NewKeyPair();
|
||
|
|
var avatar = new Avatar { UserName = $"{name}{Guid.NewGuid():N}"[..20], Name = name, PrivateKey = privateKey, PublicKey = publicKey };
|
||
|
|
await DB.Default.SaveAsync(avatar);
|
||
|
|
await DB.Default.SaveAsync(new RootToAvatar { RootId = rootId, AvatarId = avatar.ID });
|
||
|
|
return (rootId, Local.FromAvatar(avatar));
|
||
|
|
}
|
||
|
|
|
||
|
|
public async Task<InboxResult> Deliver(RemoteActor sender, string path, JsonNode activity)
|
||
|
|
{
|
||
|
|
var result = await Receiver.Receive(sender.Post(Host, path, activity), default, CancellationToken.None);
|
||
|
|
var dedupe = "inbox|" + (activity is JsonObject ? activity["id"]?.GetValue<string>() : default);
|
||
|
|
var job = await DB.Default.Find<Job>().Match(j => j.DedupeKey == dedupe).ExecuteFirstAsync();
|
||
|
|
if (job != default)
|
||
|
|
Assert.Equal(JobResult.Done, (await Processor.Handle(job, CancellationToken.None)).Result);
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
public async Task<List<JsonObject>> Outgoing(string inbox) =>
|
||
|
|
(await DB.Default.Find<Job>().Match(j => j.Kind == JobKind.Deliver).ExecuteAsync())
|
||
|
|
.Select(j => JsonSerializer.Deserialize<DeliveryPayload>(j.Payload))
|
||
|
|
.Where(p => p.Inbox == inbox)
|
||
|
|
.Select(p => JsonNode.Parse(p.Body)!.AsObject())
|
||
|
|
.ToList();
|
||
|
|
|
||
|
|
public async ValueTask DisposeAsync() => await Peer.DisposeAsync();
|
||
|
|
}
|
||
|
|
|
||
|
|
public sealed class KeyLocalizer<T> : IStringLocalizer<T>
|
||
|
|
{
|
||
|
|
public LocalizedString this[string name] => new(name, name);
|
||
|
|
public LocalizedString this[string name, params object[] arguments] => new(name, string.Format(name, arguments));
|
||
|
|
public IEnumerable<LocalizedString> GetAllStrings(bool includeParentCultures) => Enumerable.Empty<LocalizedString>();
|
||
|
|
}
|
||
|
|
}
|