using System.Security.Cryptography;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Testing;
using SQLInsight.Hub;
using SQLInsight.Licensing;
using Testcontainers.PostgreSql;
namespace SQLInsight.IntegrationTests;
///
/// SQLInsight Hub in-process on a real PostgreSQL, with a test signing key the hub trusts.
///
public sealed class HubFixture : IAsyncLifetime
{
public const string KeyId = "itest";
private readonly PostgreSqlContainer _postgres = new PostgreSqlBuilder("postgres:17-alpine").Build();
private readonly ECDsa _key = ECDsa.Create(ECCurve.NamedCurves.nistP256);
public WebApplicationFactory Factory { get; private set; } = null!;
public string PublicKey => Convert.ToBase64String(_key.ExportSubjectPublicKeyInfo());
public string ConnectionString => _postgres.GetConnectionString();
public async Task InitializeAsync()
{
await _postgres.StartAsync();
Factory = new WebApplicationFactory().WithWebHostBuilder(b =>
{
b.UseEnvironment("Development");
b.UseSetting("ConnectionStrings:Hub", ConnectionString);
b.UseSetting($"SQLInsight:Hub:TrustedKeys:{KeyId}", PublicKey);
});
await HubProgram.MigrateAsync(Factory.Services);
}
public string License(string customer, LicensePlan plan = LicensePlan.Professional, int maxInstances = 0, DateTimeOffset? expires = null, string? id = null) =>
SignedDocument.Sign(new License
{
LicenseId = id ?? Guid.NewGuid().ToString("N"),
Customer = customer,
Plan = plan,
IssuedAt = DateTimeOffset.UtcNow.AddDays(-1),
ExpiresAt = expires ?? DateTimeOffset.UtcNow.AddYears(1),
MaxInstances = maxInstances,
KeyId = KeyId,
}, _key);
public async Task DisposeAsync()
{
await Factory.DisposeAsync();
await _postgres.DisposeAsync();
_key.Dispose();
}
}