Eerste commit
This commit is contained in:
@@ -0,0 +1,177 @@
|
||||
using System.Net;
|
||||
using System.Text.Json;
|
||||
using MijnBesluit.Protocol;
|
||||
using MijnBesluit.Server;
|
||||
|
||||
namespace MijnBesluit.SelfCheck;
|
||||
|
||||
/// <summary>
|
||||
/// Loopt de hele keten door: app -> socket -> dispatcher -> Application-laag -> opslag en terug.
|
||||
/// Alleen de database is hier vervangen door opslag in het geheugen.
|
||||
/// </summary>
|
||||
public static class EndToEndChecks
|
||||
{
|
||||
public static void Register(Runner runner)
|
||||
{
|
||||
runner.TestAsync("Van app tot kluis: registreren, familie, uitnodigen, bericht", async () =>
|
||||
{
|
||||
var wereld = new World();
|
||||
var sessies = new SessionStore(wereld.Clock);
|
||||
var dispatcher = new SocketDispatcher(sessies, work => work(new RequestScope
|
||||
{
|
||||
Accounts = wereld.Accounts,
|
||||
Families = wereld.Families,
|
||||
Vault = wereld.Vault,
|
||||
Messages = wereld.Messages,
|
||||
Legacy = wereld.Legacy,
|
||||
Overzicht = wereld.Overzicht,
|
||||
Samenvoegen = wereld.Samenvoegen
|
||||
}));
|
||||
|
||||
await using var server = new SocketListener(
|
||||
new SocketListenerOptions { Address = IPAddress.Loopback, Port = 0 },
|
||||
dispatcher.HandleAsync);
|
||||
server.Start();
|
||||
|
||||
await using var app = new MijnBesluitSocketClient("127.0.0.1", server.Port, useTls: false);
|
||||
|
||||
// Zonder token mag er niets.
|
||||
var zonderToken = await app.SendAsync(SocketActions.VaultList);
|
||||
Assert.True(zonderToken.Status == "Error" && zonderToken.Message!.Contains("Log opnieuw in"),
|
||||
"zonder geldige sessie wordt een verzoek geweigerd");
|
||||
|
||||
// Registreren gaat in twee stappen: code aanvragen, code invullen.
|
||||
var codeAanvraag = await app.SendAsync(SocketActions.RequestRegisterCode, new
|
||||
{
|
||||
email = "jan@example.nl",
|
||||
firstName = "Jan",
|
||||
lastName = "Jansen"
|
||||
});
|
||||
Assert.True(codeAanvraag.Status == "Ok", "de registratiecode wordt verstuurd");
|
||||
Assert.True(!JsonSerializer.Serialize(codeAanvraag.Payload, SocketFraming.Json).Contains("jan@example.nl"),
|
||||
"het antwoord toont het adres alleen afgeschermd");
|
||||
|
||||
var registratie = await app.SendAsync(SocketActions.Register, new
|
||||
{
|
||||
email = "jan@example.nl",
|
||||
code = wereld.LaatsteCodeUitMail("jan@example.nl")
|
||||
});
|
||||
Assert.True(registratie.Status == "Ok", "registreren lukt met de code uit de e-mail");
|
||||
app.Token = Field(registratie, "token");
|
||||
Assert.True(!string.IsNullOrEmpty(app.Token), "er komt een token terug");
|
||||
|
||||
// Kluisitem opslaan en weer openen, helemaal via de socket.
|
||||
var opslaan = await app.SendAsync(SocketActions.VaultSave, new
|
||||
{
|
||||
category = 3, // Wachtwoord
|
||||
title = "Bank",
|
||||
payload = new { website = "bank.nl", username = "jan", secret = "zeergeheim" },
|
||||
releasePolicy = 1, // Na overlijden
|
||||
releaseAt = (DateTime?)null
|
||||
});
|
||||
Assert.True(opslaan.Status == "Ok", "kluisitem opslaan lukt");
|
||||
|
||||
var lijst = await app.SendAsync(SocketActions.VaultList);
|
||||
Assert.True(lijst.Status == "Ok", "de kluislijst komt terug");
|
||||
Assert.True(!JsonSerializer.Serialize(lijst.Payload, SocketFraming.Json).Contains("zeergeheim"),
|
||||
"de lijst bevat geen geheimen, alleen titels");
|
||||
|
||||
var itemId = long.Parse(Field(opslaan, "itemId")!);
|
||||
var openen = await app.SendAsync(SocketActions.VaultOpen, new { id = itemId });
|
||||
Assert.True(JsonSerializer.Serialize(openen.Payload, SocketFraming.Json).Contains("zeergeheim"),
|
||||
"openen geeft de inhoud terug aan de eigenaar");
|
||||
|
||||
// Familie uitbreiden en uitnodigen.
|
||||
var familie = wereld.Store.Families.Single();
|
||||
var toevoegen = await app.SendAsync(SocketActions.AddMember, new
|
||||
{
|
||||
familyId = familie.Id,
|
||||
firstName = "Eva",
|
||||
lastName = "Jansen",
|
||||
email = "eva@example.nl",
|
||||
relation = 2, // Kind
|
||||
relationLabel = (string?)null
|
||||
});
|
||||
Assert.True(toevoegen.Status == "Ok", "familielid toevoegen lukt");
|
||||
var evaId = long.Parse(Field(toevoegen, "persoonId")!);
|
||||
|
||||
var uitnodigen = await app.SendAsync(SocketActions.Invite, new { familyId = familie.Id, personId = evaId });
|
||||
Assert.True(uitnodigen.Status == "Ok", "uitnodigen lukt");
|
||||
Assert.True(!JsonSerializer.Serialize(uitnodigen.Payload, SocketFraming.Json)
|
||||
.Contains(wereld.Store.Invitations.Single().Email),
|
||||
"het antwoord bevat geen uitnodigingstoken");
|
||||
|
||||
// Eva neemt de uitnodiging aan vanaf haar eigen toestel.
|
||||
var mail = wereld.Email.Sent.Last(m => m.To == "eva@example.nl");
|
||||
var token = mail.Body.Split("/uitnodiging/")[1].Split('"')[0];
|
||||
|
||||
await using var appVanEva = new MijnBesluitSocketClient("127.0.0.1", server.Port, useTls: false);
|
||||
var accepteren = await appVanEva.SendAsync(SocketActions.AcceptInvitation, new { token });
|
||||
Assert.True(accepteren.Status == "Ok", "Eva kan de uitnodiging aannemen via de app");
|
||||
appVanEva.Token = Field(accepteren, "token");
|
||||
|
||||
// Jan ziet nu dat het profiel geclaimd is.
|
||||
var leden = await app.SendAsync(SocketActions.ListMembers, new { familyId = familie.Id });
|
||||
var ledenJson = JsonSerializer.Serialize(leden.Payload, SocketFraming.Json);
|
||||
Assert.True(ledenJson.Contains("\"state\":2"), "Jan ziet het profiel van Eva als geclaimd");
|
||||
|
||||
// Jan zet een bericht klaar voor Eva, te bezorgen na zijn overlijden.
|
||||
var bericht = await app.SendAsync(SocketActions.MessageCompose, new
|
||||
{
|
||||
toPersonId = evaId,
|
||||
subject = "Voor later",
|
||||
text = "Ik ben trots op je.",
|
||||
deliverAt = (DateTime?)null,
|
||||
afterDeath = true,
|
||||
kind = 0,
|
||||
vaultFileId = (long?)null
|
||||
});
|
||||
Assert.True(bericht.Status == "Ok", "bericht klaarzetten lukt");
|
||||
|
||||
var inboxVanEva = await appVanEva.SendAsync(SocketActions.Inbox);
|
||||
Assert.True(JsonSerializer.Serialize(inboxVanEva.Payload, SocketFraming.Json) == "[]",
|
||||
"Eva ziet het bericht nog niet");
|
||||
|
||||
// Uitloggen maakt het token onbruikbaar.
|
||||
await app.SendAsync(SocketActions.SignOut);
|
||||
var naUitloggen = await app.SendAsync(SocketActions.VaultList);
|
||||
Assert.True(naUitloggen.Status == "Error", "na uitloggen werkt het token niet meer");
|
||||
});
|
||||
|
||||
runner.TestAsync("Verlopen sessie wordt geweigerd", async () =>
|
||||
{
|
||||
var wereld = new World();
|
||||
var sessies = new SessionStore(wereld.Clock, TimeSpan.FromHours(1));
|
||||
var dispatcher = new SocketDispatcher(sessies, work => work(new RequestScope
|
||||
{
|
||||
Accounts = wereld.Accounts, Families = wereld.Families, Vault = wereld.Vault,
|
||||
Messages = wereld.Messages, Legacy = wereld.Legacy, Overzicht = wereld.Overzicht
|
||||
}));
|
||||
|
||||
await using var server = new SocketListener(
|
||||
new SocketListenerOptions { Address = IPAddress.Loopback, Port = 0 }, dispatcher.HandleAsync);
|
||||
server.Start();
|
||||
|
||||
await using var app = new MijnBesluitSocketClient("127.0.0.1", server.Port, useTls: false);
|
||||
await app.SendAsync(SocketActions.RequestRegisterCode,
|
||||
new { email = "a@example.nl", firstName = "A", lastName = "A" });
|
||||
var reg = await app.SendAsync(SocketActions.Register,
|
||||
new { email = "a@example.nl", code = wereld.LaatsteCodeUitMail("a@example.nl") });
|
||||
app.Token = Field(reg, "token");
|
||||
Assert.True((await app.SendAsync(SocketActions.VaultList)).Status == "Ok", "meteen na inloggen werkt het");
|
||||
|
||||
wereld.Clock.Advance(TimeSpan.FromHours(2));
|
||||
Assert.True((await app.SendAsync(SocketActions.VaultList)).Status == "Error", "na twee uur is de sessie verlopen");
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>Haalt één veld uit de payload van een antwoord.</summary>
|
||||
private static string? Field(SocketResponse response, string name)
|
||||
{
|
||||
var json = JsonSerializer.Serialize(response.Payload, SocketFraming.Json);
|
||||
using var doc = JsonDocument.Parse(json);
|
||||
return doc.RootElement.TryGetProperty(name, out var value)
|
||||
? (value.ValueKind == JsonValueKind.String ? value.GetString() : value.ToString())
|
||||
: null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user