using PostFundManagement.Domain; using PostFundManagement.Domain.Abstractions; using PostFundManagement.Domain.Api; using PostFundManagement.Domain.Extensions; using PostFundManagement.Infrastructure.Database; namespace PostFundManagement.Api.Endpoints.Users; [ApiVersionTarget(1)] public class SyncUserEndpoint : IEndpoint { public void Map(IEndpointRouteBuilder builder) { builder.MapPost("api/users/sync", async (ClaimsPrincipal principal, IDbContextFactory contextFactory, CancellationToken cancellationToken = default) => { var sidClaim = principal.FindFirst("sid")?.Value ?? principal.FindFirst(ClaimTypes.Sid)?.Value; var emailClaim = principal.FindFirst("email")?.Value ?? principal.FindFirst(ClaimTypes.Email)?.Value; if (string.IsNullOrWhiteSpace(sidClaim)) return Results.BadRequest("Missing 'sid' claim in user token."); if (!Guid.TryParse(sidClaim, out var userId)) userId = new Guid(System.Security.Cryptography.MD5.HashData(System.Text.Encoding.UTF8.GetBytes(sidClaim))); using var context = await contextFactory.CreateDbContextAsync(cancellationToken); var user = await context.Users.FirstOrDefaultAsync(u => u.Id == userId, cancellationToken); var isNew = user == null; if (isNew) { user = new Domain.Entities.User { Id = userId, Email = emailClaim, Status = ActivityStatus.Active, LastLoginAt = DateTime.UtcNow }; context.Users.Add(user); } else { user!.Email = emailClaim; user.LastLoginAt = DateTime.UtcNow; context.Users.Update(user); } return await context.SaveChangesAsync(cancellationToken) > 0 ? Results.Ok(user) : Results.BadRequest("Failed to sync user"); }) .RequireAuthorization() .WithDescription("Synchronise caller user profile using id_token's SID, inserting/updating user details in database") .WithName(typeof(SyncUserEndpoint).ToEndpointName()) .MapToApiVersion(new ApiVersion(1)) .Produces(StatusCodes.Status200OK) .Produces(StatusCodes.Status400BadRequest) .Produces(StatusCodes.Status401Unauthorized) .WithTags(EndpointTags.Users); } }