using Application.Abstractions.Data; using Application.Abstractions.Cache; using Application.Abstractions.Messaging; using Application.Helpers; using SharedKernel.Results; using Microsoft.EntityFrameworkCore; namespace Application.Features.Api.Auth.ResetPassword; internal sealed class Handler( IAppDbContext db, ICacheService cache ) : ICommandHandler { public async Task Handle(Command request, CancellationToken ct) { // 쿠키 인증 확인 if (request.CookieValue != "true") { return Result.Failure(Error.Unauthorized("Auth.NotVerified", "사전 인증을 먼저 수행하세요.")); } // 이메일 유효성 검사 if (string.IsNullOrWhiteSpace(request.Email)) { return Result.Failure(Error.Problem("Auth.EmailRequired", "이메일은 필수입니다.")); } // 비밀번호 유효성 검사 (복잡도 포함) if (string.IsNullOrWhiteSpace(request.Password)) { return Result.Failure(Error.Problem("Auth.PasswordRequired", "비밀번호는 필수입니다.")); } var accountConfig = await AccountConfigLoader.GetAccountConfigAsync(cache, db, ct); var passwordResult = PasswordPolicyValidator.Validate(request.Password, accountConfig); if (!passwordResult.IsSuccess) { return passwordResult; } var email = request.Email.Trim().ToLower(); // 회원 조회 var member = await db.Member.FirstOrDefaultAsync(m => m.Email == email, ct); if (member is null) { return Result.Failure(Error.NotFound("Auth.MemberNotFound", "회원 정보를 찾을 수 없습니다.")); } // 비밀번호 변경 member.SetPassword(request.Password); await db.SaveChangesAsync(ct); return Result.Success(); } }