IdentityShroud/IdentityShroud.Core.Tests/Services/RealmServiceTests.cs
eelke 644b005f2a Support rotation of master key.
The EncryptionService now loads a set of keys and uses the active one to encrypt and selects key based on keyid during decryption. Introduced EncryptedValue to hold keyId and encrypted data.

(There are no intermeddiate keys yet)
2026-02-24 06:32:58 +01:00

142 lines
No EOL
4.4 KiB
C#

using IdentityShroud.Core.Contracts;
using IdentityShroud.Core.Model;
using IdentityShroud.Core.Security.Keys;
using IdentityShroud.Core.Services;
using IdentityShroud.Core.Tests.Fixtures;
using Microsoft.EntityFrameworkCore;
namespace IdentityShroud.Core.Tests.Services;
public class RealmServiceTests : IClassFixture<DbFixture>
{
private readonly DbFixture _dbFixture;
private readonly IKeyService _keyService = Substitute.For<IKeyService>();
public RealmServiceTests(DbFixture dbFixture)
{
_dbFixture = dbFixture;
using Db db = dbFixture.CreateDbContext();
if (!db.Database.EnsureCreated())
TruncateTables(db);
}
private void TruncateTables(Db db)
{
db.Database.ExecuteSqlRaw("TRUNCATE realm CASCADE;");
}
[Theory]
[InlineData(null)]
[InlineData("a7c2a39c-3ed9-4790-826e-43bb2e5e480c")]
public async Task Create(string? idString)
{
// Setup
Guid? realmId = null;
if (idString is not null)
realmId = new(idString);
RealmCreateResponse? val;
await using (var db = _dbFixture.CreateDbContext())
{
_keyService.CreateKey(Arg.Any<KeyPolicy>())
.Returns(new RealmKey()
{
Id = Guid.NewGuid(),
KeyType = "TST",
Key = new("kid", [21]),
CreatedAt = DateTime.UtcNow
});
// Act
RealmService sut = new(db, _keyService);
var response = await sut.Create(
new(realmId, "slug", "New realm"),
TestContext.Current.CancellationToken);
// Verify
val = ResultAssert.Success(response);
if (realmId.HasValue)
Assert.Equal(realmId, val.Id);
else
Assert.NotEqual(Guid.Empty, val.Id);
Assert.Equal("slug", val.Slug);
Assert.Equal("New realm", val.Name);
_keyService.Received().CreateKey(Arg.Any<KeyPolicy>());
}
await using (var db = _dbFixture.CreateDbContext())
{
var dbRecord = await db.Realms
.Include(e => e.Keys)
.SingleAsync(e => e.Id == val.Id, TestContext.Current.CancellationToken);
Assert.Equal("TST", dbRecord.Keys[0].KeyType);
}
}
[Theory]
[InlineData("slug", null)]
[InlineData("foo", "Foo")]
public async Task FindBySlug(string slug, string? name)
{
await using (var setupContext = _dbFixture.CreateDbContext())
{
setupContext.Realms.Add(new()
{
Slug = "foo",
Name = "Foo",
});
setupContext.Realms.Add(new()
{
Slug = "bar",
Name = "Bar",
});
await setupContext.SaveChangesAsync(TestContext.Current.CancellationToken);
}
await using var actContext = _dbFixture.CreateDbContext();
// Act
RealmService sut = new(actContext, _keyService);
var result = await sut.FindBySlug(slug, TestContext.Current.CancellationToken);
// Verify
Assert.Equal(name, result?.Name);
}
[Theory]
[InlineData("b0423bba-2411-497b-a5b6-c5adf404b862", true)]
[InlineData("65ac9dba-6d43-4fa4-b57f-133ed639fbcb", false)]
public async Task FindById(string idString, bool shouldFind)
{
Guid id = new(idString);
await using (var setupContext = _dbFixture.CreateDbContext())
{
setupContext.Realms.Add(new()
{
Id = new("b0423bba-2411-497b-a5b6-c5adf404b862"),
Slug = "foo",
Name = "Foo",
});
setupContext.Realms.Add(new()
{
Id = new("d4ffc7d0-7b2c-4f02-82b9-a74610435b0d"),
Slug = "bar",
Name = "Bar",
});
await setupContext.SaveChangesAsync(TestContext.Current.CancellationToken);
}
await using var actContext = _dbFixture.CreateDbContext();
// Act
RealmService sut = new(actContext, _keyService);
Realm? result = await sut.FindById(id, TestContext.Current.CancellationToken);
// Verify
if (shouldFind)
Assert.NotNull(result);
else
Assert.Null(result);
}
}