using FastEndpoints; using Microsoft.AspNetCore.Identity; using System.Web; using Socialize.Api.Modules.Identity.Data; namespace Socialize.Api.Modules.Identity.Handlers; [PublicAPI] public record VerifyEmailRequest( string UserId, string Token); [PublicAPI] public record VerifyEmailResponse( string Message); [PublicAPI] public class VerifyEmailHandler( UserManager userManager) : Endpoint { public override void Configure() { AllowAnonymous(); Get("/api/users/verify-email"); Options(o => o.WithTags("Users")); } public override async Task HandleAsync( VerifyEmailRequest request, CancellationToken ct) { // Find user by ID User? user = await userManager.FindByIdAsync(request.UserId); if (user is null) { await SendStringAsync( "Invalid verification link", 400, cancellation: ct); return; } // Verify the token and confirm email string decoded = HttpUtility.UrlDecode(request.Token); string decodedWithPlus = request.Token.Replace(" ", "+"); IdentityResult result = await userManager.ConfirmEmailAsync(user, decodedWithPlus); if (!result.Succeeded) { await SendStringAsync( "Invalid verification link or the link has expired", 400, cancellation: ct); return; } await SendOkAsync( new VerifyEmailResponse("Email verification successful! You can now log in."), ct); } }