using System.Security.Claims; using FastEndpoints; using FluentValidation; using Microsoft.EntityFrameworkCore; using TrackQrApi.Data; using TrackQrApi.Features.Auth.Common; namespace TrackQrApi.Features.Auth.Endpoints; public class UpdateProfileRequest { public string? Email { get; set; } } public class UpdateProfileValidator : Validator { public UpdateProfileValidator() { RuleFor(x => x.Email) .EmailAddress().WithMessage("Invalid email address") .When(x => !string.IsNullOrEmpty(x.Email)); } } public class UpdateProfileEndpoint(AppDbContext db) : Endpoint { public override void Configure() { Put("/auth/profile"); } public override async Task HandleAsync(UpdateProfileRequest req, CancellationToken ct) { var userId = Guid.Parse(User.FindFirstValue(ClaimTypes.NameIdentifier)!); var user = await db.Users.FindAsync([userId], ct); if (user == null) { await HttpContext.Response.SendAsync(new MessageResponse("User not found"), 404, cancellation: ct); return; } if (!string.IsNullOrEmpty(req.Email) && req.Email != user.Email) { // Check if email is already taken var emailExists = await db.Users.AnyAsync(u => u.Email == req.Email && u.Id != userId, ct); if (emailExists) { await HttpContext.Response.SendAsync(new MessageResponse("Email is already in use"), 409, cancellation: ct); return; } user.Email = req.Email; user.VerifiedAt = null; // Reset verification when email changes } await db.SaveChangesAsync(ct); var response = new ProfileResponse( user.Id, user.Email, user.VerifiedAt != null, user.CreatedAt ); await HttpContext.Response.SendAsync(response, cancellation: ct); } }