| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 |
- using Microsoft.AspNetCore.Mvc;
- using bitforum.DTOs.Request;
- using bitforum.DTOs.Response;
- using bitforum.Constants;
- using bitforum.Helpers;
- using bitforum.Services;
- using bitforum.Repository;
- namespace bitforum.Controllers.API.Auth
- {
- [ApiController]
- [Route("api/auth")]
- public class PasswordController : ControllerBase
- {
- private readonly ILogger<PasswordController> _logger;
- private readonly DefaultDbContext _db;
- private readonly IConfigService _configService;
- private readonly IMailService _mailService;
- private readonly IMemberRepository _memberRepository;
- private ResultDto _result = new ResultDto();
- public PasswordController(ILogger<PasswordController> logger, DefaultDbContext db, IConfigService configService, IMailService mailService, IEmailVerifyNumberRepository emailVerifyNumberRepository, IMemberRepository memberRepository)
- {
- _logger = logger;
- _db = db;
- _configService = configService;
- _mailService = mailService;
- _memberRepository = memberRepository;
- }
- // 비밀번호 재설정 요청
- [HttpGet("forgot-password/{email}")]
- public async Task<ActionResult<ResultDto>> ForgotPassword([FromRoute] string email)
- {
- try
- {
- if (string.IsNullOrEmpty(email))
- {
- throw new Exception("잘못된 접근입니다.");
- }
- // 이메일 거부 목록 확인
- if (_configService.IsDeniedEmail(email))
- {
- throw new Exception($"`{email}`은 조회할 수 없습니다.");
- }
- // 회원 확인
- var member = await _memberRepository.FindMemberByEmail(email);
- if (member is null)
- {
- throw new Exception("회원 정보를 찾을 수 없습니다.");
- }
- // 차단 회원은 거부
- if (member.IsDenied)
- {
- throw new Exception("권한이 없습니다.");
- }
- await _mailService.SendForgotPasswordEmailAsync(member);
- _result.Message = "이메일 인증 확인 후 비밀번호를 변경할 수 있습니다.";
- }
- catch (Exception e)
- {
- _logger.LogError(e, e.Message);
- _result.Ok = false;
- _result.Status = StatusCodes.Status400BadRequest;
- _result.Message = e.Message;
- }
- return _result;
- }
- // 비밀번호 변경 처리
- [HttpPost("reset-password")]
- public async Task<ActionResult<ResultDto>> ResetPassword([FromBody] ResetPasswordDto request)
- {
- try
- {
- var cookieName = $"isVerified-{VerificationType.ForgotPassword}";
- if (!Request.Cookies.ContainsKey(cookieName) || Request.Cookies[cookieName] != "true")
- {
- throw new Exception("사전 인증을 먼저 수행하세요.");
- }
- // 유효성 검사
- if (!ModelState.IsValid)
- {
- _result.Errors = ModelState.GetErrors();
- throw new Exception("유효성 검사에 실패하였습니다.");
- }
- // 회원 확인
- var member = await _memberRepository.FindMemberByEmail(request.Email);
- if (member is null)
- {
- throw new Exception("회원 정보를 찾을 수 없습니다.");
- }
- var newPassword = BCrypt.Net.BCrypt.HashPassword(request.Password);
- if (member.Password == newPassword)
- {
- throw new Exception("기존 비밀번호와 동일합니다.");
- }
- var isValid = _configService.IsPasswordPolicyValid(request.Password);
- if (!isValid)
- {
- string message = "";
- int minLengthConfig = Config.Register.PasswordMinLength ?? 6;
- int uppercaseLengthConfig = Config.Register.PasswordUppercaseLength ?? 0;
- int numbersLengthConfig = Config.Register.PasswordNumbersLength ?? 0;
- int specialCharsLengthConfig = Config.Register.PasswordSpecialcharsLength ?? 0;
- // 위에 데이터로 안내 문구 만들어줘
- if (minLengthConfig > 0)
- {
- message += $"최소 {minLengthConfig}자 이상, ";
- }
- if (uppercaseLengthConfig > 0)
- {
- message += $"대문자 {uppercaseLengthConfig}자 이상, ";
- }
- if (numbersLengthConfig > 0)
- {
- message += $"숫자 {numbersLengthConfig}자 이상, ";
- }
- if (specialCharsLengthConfig > 0)
- {
- message += $"특수문자 {specialCharsLengthConfig}자 이상, ";
- }
- message = message.TrimEnd(',', ' ');
- throw new Exception($"입력하신 비밀번호는 사용하실 수 없습니다. 다음 조건을 충족해주세요.\n\n{message}");
- }
- member.Password = newPassword;
- member.PasswordUpdatedAt = DateTime.UtcNow;
- await _db.SaveChangesAsync();
- await _mailService.SendChangedPasswordEmailAsync(member);
- // 쿠키 삭제
- Response.Cookies.Delete(cookieName);
- _result.Message = "비밀번호가 변경되었습니다.";
- }
- catch (Exception e)
- {
- _logger.LogError(e, e.Message);
- _result.Ok = false;
- _result.Status = StatusCodes.Status400BadRequest;
- _result.Message = e.Message;
- }
- return _result;
- }
- }
- }
|