RegisterController.cs 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. using Microsoft.AspNetCore.Mvc;
  2. using bitforum.DTOs.Request;
  3. using bitforum.DTOs.Response;
  4. using bitforum.Helpers;
  5. using bitforum.Services;
  6. using bitforum.Constants;
  7. using bitforum.Repository;
  8. using bitforum.Models.Account;
  9. namespace bitforum.Controllers.API.Auth
  10. {
  11. [ApiController]
  12. [Route("api/auth")]
  13. public class RegisterController : ControllerBase
  14. {
  15. private readonly ILogger<RegisterController> _logger;
  16. private readonly DefaultDbContext _db;
  17. private readonly IConfigService _configService;
  18. private readonly IMailService _mailService;
  19. private readonly IMemberRepository _memberRepository;
  20. private ResultDto _result = new ResultDto();
  21. public RegisterController(ILogger<RegisterController> logger, DefaultDbContext db, IConfigService configService, IMailService mailService, IMemberRepository memberRepository)
  22. {
  23. _logger = logger;
  24. _db = db;
  25. _configService = configService;
  26. _mailService = mailService;
  27. _memberRepository = memberRepository;
  28. }
  29. // 회원가입 요청
  30. [HttpPost("register")]
  31. public async Task<ActionResult<ResultDto>> Register([FromBody] RegisterDto request)
  32. {
  33. try
  34. {
  35. // 회원 가입 차단
  36. if (_configService.IsRegisterBlock())
  37. {
  38. throw new Exception("현재 회원가입이 일시 중단되었습니다.");
  39. }
  40. // 유효성 검사
  41. if (!ModelState.IsValid)
  42. {
  43. _result.Errors = ModelState.GetErrors();
  44. throw new Exception("유효성 검사에 실패하였습니다.");
  45. }
  46. // 이메일 거부 목록 확인
  47. if (_configService.IsDeniedEmail(request.Email))
  48. {
  49. throw new Exception($"`{request.Email}`은 사용할 수 없는 이메일입니다.");
  50. }
  51. // 이메일 중복 확인
  52. if (await _memberRepository.IsExistEmail(request.Email))
  53. {
  54. throw new Exception("이미 가입된 이메일입니다.");
  55. }
  56. // 비밀번호 정책 확인
  57. if (!_configService.IsPasswordPolicyValid(request.Password))
  58. {
  59. throw new Exception("비밀번호 구성이 적절하지 않습니다.");
  60. }
  61. bool isNew = false;
  62. var member = await _memberRepository.FindNonMemberByEmail(request.Email);
  63. if (member == null)
  64. {
  65. member = new Models.Account.Member
  66. {
  67. Email = request.Email,
  68. CreatedAt = DateTime.UtcNow
  69. };
  70. isNew = true;
  71. }
  72. member.Password = BCrypt.Net.BCrypt.HashPassword(request.Password);
  73. member.SignupIP = HttpContext.GetClientIP();
  74. member.PasswordUpdatedAt = DateTime.UtcNow;
  75. if (isNew)
  76. {
  77. await _db.Member.AddAsync(member);
  78. }
  79. await _db.SaveChangesAsync();
  80. if (member.ID > 0)
  81. {
  82. await _db.MemberApprove.AddAsync(new MemberApprove
  83. {
  84. MemberID = member.ID
  85. });
  86. }
  87. bool isRegisterEmailAuth = _configService.IsRegisterEmailAuth();
  88. if (isRegisterEmailAuth)
  89. {
  90. // 회원가입 이메일 인증 메일 발송
  91. await _mailService.SendRegisterEmailAsync(member);
  92. _result.Message = "이메일 인증 후 회원가입이 완료됩니다.";
  93. }
  94. else
  95. {
  96. // 회원가입 완료 메일 발송
  97. await _mailService.SendRegistrationEmailAsync(member);
  98. _result.Message = "회원가입을 환영합니다.";
  99. }
  100. _result.Data = new { isRegisterEmailAuth };
  101. }
  102. catch (Exception e)
  103. {
  104. _logger.LogError(e, e.Message);
  105. _result.Ok = false;
  106. _result.Status = StatusCodes.Status400BadRequest;
  107. _result.Message = e.Message;
  108. }
  109. return _result;
  110. }
  111. // 회원가입 수락
  112. [HttpGet("registration/{email}")]
  113. public async Task<ActionResult<ResultDto>> Registration([FromRoute] string email)
  114. {
  115. try
  116. {
  117. var cookieName = $"isVerified-{VerificationType.Registration}";
  118. if (!Request.Cookies.ContainsKey(cookieName) || Request.Cookies[cookieName] != "true")
  119. {
  120. throw new Exception("사전 인증을 먼저 수행하세요.");
  121. }
  122. if (string.IsNullOrEmpty(email))
  123. {
  124. throw new Exception("이메일을 입력해주세요.");
  125. }
  126. // 회원 확인
  127. var member = await _memberRepository.FindNonMemberByEmail(email);
  128. if (member is null)
  129. {
  130. throw new Exception("회원 정보를 찾을 수 없습니다.");
  131. }
  132. member.IsEmailVerified = true;
  133. member.EmailVerifiedAt = DateTime.UtcNow;
  134. await _db.SaveChangesAsync();
  135. await _mailService.SendRegistrationEmailAsync(member);
  136. _result.Message = "회원가입을 환영합니다.";
  137. // 쿠키 삭제
  138. Response.Cookies.Delete(cookieName);
  139. }
  140. catch (Exception e)
  141. {
  142. _logger.LogError(e, e.Message);
  143. _result.Ok = false;
  144. _result.Status = StatusCodes.Status400BadRequest;
  145. _result.Message = e.Message;
  146. }
  147. return _result;
  148. }
  149. }
  150. }