using System.Security.Cryptography; using IdentityShroud.Core.Contracts; using IdentityShroud.Core.Model; using Microsoft.EntityFrameworkCore; namespace IdentityShroud.Core.Services; public class ClientService( Db db, IEncryptionService cryptor, IClock clock) : IClientService { public async Task> Create(Guid realmId, ClientCreateRequest request, CancellationToken ct = default) { Client client = new() { RealmId = realmId, ClientId = request.ClientId, Name = request.Name, Description = request.Description, SignatureAlgorithm = request.SignatureAlgorithm, AllowClientCredentialsFlow = request.AllowClientCredentialsFlow ?? false, CreatedAt = clock.UtcNow(), }; if (client.AllowClientCredentialsFlow) { client.Secrets.Add(CreateSecret()); } await db.AddAsync(client, ct); await db.SaveChangesAsync(ct); return client; } public async Task GetByClientId(string clientId, CancellationToken ct = default) { return await db.Clients.FirstOrDefaultAsync(c => c.ClientId == clientId, ct); } public async Task FindById(int id, CancellationToken ct = default) { return await db.Clients.FirstOrDefaultAsync(c => c.Id == id, ct); } private ClientSecret CreateSecret() { byte[] secret = RandomNumberGenerator.GetBytes(24); return new ClientSecret() { CreatedAt = clock.UtcNow(), SecretEncrypted = cryptor.Encrypt(secret), }; } }