using System.Security.Cryptography; using IdentityShroud.Core.Contracts; using IdentityShroud.Core.Helpers; using IdentityShroud.Core.Messages.Realm; using IdentityShroud.Core.Model; using IdentityShroud.Core.Security.Keys; using IdentityShroud.Core.Security.Keys.Rsa; using Microsoft.EntityFrameworkCore; namespace IdentityShroud.Core.Services; public record RealmCreateResponse(Guid Id, string Slug, string Name); public class RealmService( Db db, IKeyService keyService) : IRealmService { public async Task FindById(Guid id, CancellationToken ct = default) { return await db.Realms .SingleOrDefaultAsync(r => r.Id == id, ct); } public async Task FindBySlug(string slug, CancellationToken ct = default) { return await db.Realms .SingleOrDefaultAsync(r => r.Slug == slug, ct); } public async Task> Create(RealmCreateRequest request, CancellationToken ct = default) { Realm realm = new() { Id = request.Id ?? Guid.CreateVersion7(), Slug = request.Slug ?? SlugHelper.GenerateSlug(request.Name), Name = request.Name, }; realm.Keys.Add(keyService.CreateKey(GetKeyPolicy(realm))); db.Add(realm); await db.SaveChangesAsync(ct); return new RealmCreateResponse( realm.Id, realm.Slug, realm.Name); } /// /// Place holder for getting policies from the realm and falling back to sane defaults when no policies have been set. /// /// /// private KeyPolicy GetKeyPolicy(Realm _) => new RsaKeyPolicy(); public async Task LoadActiveKeys(Realm realm) { await db.Entry(realm).Collection(r => r.Keys) .Query() .Where(k => k.RevokedAt == null) .LoadAsync(); } }