using Microsoft.AspNetCore.Mvc; using bitforum.Models.Log; using bitforum.DTOs.Request; using bitforum.DTOs.Response; using bitforum.Helpers; using bitforum.Services; using bitforum.Repository; namespace bitforum.Controllers.API.Auth { [ApiController] [Route("api/auth")] public class LoginController : ControllerBase { private readonly ILogger _logger; private readonly DefaultDbContext _db; private readonly IJwtAuthService _jwtAuthService; private readonly IMemberRepository _memberRepository; private ResultDto _result = new ResultDto(); public LoginController(ILogger logger, DefaultDbContext db, IJwtAuthService jwtAuthService, IMemberRepository memberRepository) { _logger = logger; _db = db; _jwtAuthService = jwtAuthService; _memberRepository = memberRepository; } // 로그인 [HttpPost("login")] public async Task> Login([FromBody] LoginDto request) { var loginLog = new LoginLog(); try { // 유효성 검사 if (!ModelState.IsValid) { _result.Errors = ModelState.GetErrors(); throw new Exception("유효성 검사에 실패하였습니다."); } loginLog.Account = request.Email; loginLog.Referer = HttpContext.Request.Headers["Referer"].ToString(); loginLog.Url = HttpContext.Request.Path.ToString(); loginLog.IpAddress = HttpContext.GetClientIP(); loginLog.UserAgent = Request.Headers["User-Agent"].ToString(); // 계정 확인 var member = await _memberRepository.FindMemberByEmail(request.Email); if (member == null) { loginLog.Reason = "계정을 찾을 수 없음"; throw new Exception("해당 정보로 귀하의 계정을 확인할 수 없습니다."); } if (member.IsDenied) { loginLog.Reason = "접속 차단되었음"; throw new Exception("접속이 차단되어 로그인이 불가합니다."); } if (!BCrypt.Net.BCrypt.Verify(request.Password, member.Password)) { loginLog.Reason = "비밀번호 틀림"; throw new Exception("해당 정보로 귀하의 계정을 확인할 수 없습니다."); } // 로그인 기록 loginLog.MemberID = member.ID; loginLog.Success = true; loginLog.Reason = "로그인 성공"; loginLog.CreatedAt = DateTime.UtcNow; // 로그인 시간, IP 갱신 member.LastLoginIp = HttpContext.GetClientIP(); member.LastLoginAt = DateTime.UtcNow; // JWT 토큰 발급 _jwtAuthService.SetAccessTokenAndCookieAsync(member); await _jwtAuthService.SetRefreshTokenAndCookieAsync(member); _result.Message = "로그인 성공"; } catch (Exception e) { _logger.LogError(e, e.Message); _result.Ok = false; _result.Status = StatusCodes.Status400BadRequest; _result.Message = e.Message; } await _db.LoginLog.AddAsync(loginLog); await _db.SaveChangesAsync(); return _result; } } }