using System.Data; using Dapper; using Npgsql; namespace KArtSell.Modules.IdentityAccess.ManageIdentityAndRoles.Features.RegisterIdentity; public interface IRegisterIdentitySql { Task EmailExistsAsync(string email, CancellationToken ct); Task CreateIdentityAsync(NpgsqlConnection conn, NpgsqlTransaction transaction, Guid id, string email, string displayName, string correlationId, CancellationToken ct); Task<(Guid Id, string Email, string DisplayName, string State)> GetIdentityAsync(Guid id, CancellationToken ct); } public sealed class RegisterIdentitySql : IRegisterIdentitySql { private readonly Func> _connectionFactory; public RegisterIdentitySql(Func> connectionFactory) { _connectionFactory = connectionFactory; } public async Task EmailExistsAsync(string email, CancellationToken ct) { using var conn = await _connectionFactory(); const string sql = """ SELECT EXISTS(SELECT 1 FROM public.identity WHERE email = @email) """; return await conn.QuerySingleAsync(sql, new { email }, commandTimeout: 5); } public async Task CreateIdentityAsync(NpgsqlConnection conn, NpgsqlTransaction transaction, Guid id, string email, string displayName, string correlationId, CancellationToken ct) { const string sql = """ INSERT INTO public.identity (identity_id, email, display_name, state, created_at, updated_at, published_at, revision_version, correlation_id, username) VALUES (@id, @email, @displayName, @state, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 1, @correlationId, @email) ON CONFLICT (email) DO NOTHING RETURNING identity_id; """; var result = await conn.QuerySingleOrDefaultAsync( new CommandDefinition( sql, new { id, email, displayName, state = Domain.IdentityState.Active, correlationId }, transaction, commandTimeout: 5, cancellationToken: ct)); return result ?? Guid.Empty; } public async Task<(Guid Id, string Email, string DisplayName, string State)> GetIdentityAsync(Guid id, CancellationToken ct) { using var conn = await _connectionFactory(); const string sql = """ SELECT identity_id, email, display_name, state FROM public.identity WHERE identity_id = @id """; var row = await conn.QuerySingleOrDefaultAsync(sql, new { id }, commandTimeout: 5); if (row is null) throw new InvalidOperationException($"Identity {id} not found"); return ((Guid)row.identity_id, (string)row.email, (string)row.display_name, (string)row.state); } }