Handler.cs 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. using Application.Abstractions.Data;
  2. using Application.Abstractions.Messaging;
  3. using Domain.Entities.EmailVerification.ValueObject;
  4. using SharedKernel.Results;
  5. using Microsoft.EntityFrameworkCore;
  6. namespace Application.Features.Api.MyPage.VerifyEmail;
  7. internal sealed class Handler(IAppDbContext db) : IQueryHandler<Query, Result>
  8. {
  9. public async Task<Result> Handle(Query request, CancellationToken ct)
  10. {
  11. if (string.IsNullOrWhiteSpace(request.Token))
  12. {
  13. return Result.Failure(Error.Problem("MyPage.TokenRequired", "인증 토큰은 필수입니다."));
  14. }
  15. var verifyToken = await db.EmailVerifyToken.FirstOrDefaultAsync(t => t.Token == request.Token && t.Type == VerificationType.ChangedEmail, ct);
  16. if (verifyToken is null)
  17. {
  18. return Result.Failure(Error.NotFound("MyPage.TokenNotFound", "유효하지 않은 인증 토큰입니다."));
  19. }
  20. if (verifyToken.IsVerified)
  21. {
  22. return Result.Failure(Error.Problem("MyPage.AlreadyVerified", "이미 인증된 토큰입니다."));
  23. }
  24. if (verifyToken.Expiration < DateTime.UtcNow)
  25. {
  26. return Result.Failure(Error.Problem("MyPage.TokenExpired", "인증 토큰이 만료되었습니다."));
  27. }
  28. // AdditionalData.Email = 기존 이메일, verifyToken.Email = 새 이메일
  29. var oldEmail = verifyToken.AdditionalData?.Email;
  30. if (string.IsNullOrWhiteSpace(oldEmail))
  31. {
  32. return Result.Failure(Error.Problem("MyPage.InvalidToken", "인증 토큰 데이터가 올바르지 않습니다."));
  33. }
  34. var member = await db.Member.FirstOrDefaultAsync(m => m.Email == oldEmail, ct);
  35. if (member is null)
  36. {
  37. return Result.Failure(Error.NotFound("MyPage.MemberNotFound", "회원 정보를 찾을 수 없습니다."));
  38. }
  39. // 새 이메일이 다른 회원에게 사용 중인지 확인
  40. var newEmail = verifyToken.Email;
  41. var emailExists = await db.Member.AnyAsync(m => m.Email == newEmail && m.ID != member.ID, ct);
  42. if (emailExists)
  43. {
  44. return Result.Failure(Error.Conflict("MyPage.EmailExists", "이미 사용 중인 이메일입니다."));
  45. }
  46. verifyToken.MarkVerified();
  47. member.SetEmail(newEmail);
  48. member.MarkEmailVerified();
  49. await db.SaveChangesAsync(ct);
  50. return Result.Success();
  51. }
  52. }