using Microsoft.AspNetCore.Mvc; using System.Security.Claims; using TaxBaik.Web.Services; namespace TaxBaik.Web.Controllers; [ApiController] [Route("api/[controller]")] public class AuthController : ControllerBase { private readonly AuthService _authService; public AuthController(AuthService authService) { _authService = authService; } [HttpPost("login")] public async Task Login([FromBody] LoginRequest request) { if (string.IsNullOrWhiteSpace(request.Username) || string.IsNullOrWhiteSpace(request.Password)) return BadRequest(new ProblemDetails { Title = "로그인 정보가 필요합니다.", Status = StatusCodes.Status400BadRequest }); var tokenPair = await _authService.AuthenticateAndGenerateTokenPairAsync(request.Username, request.Password); if (tokenPair == null) return Unauthorized(new ProblemDetails { Title = "아이디 또는 비밀번호가 올바르지 않습니다.", Status = StatusCodes.Status401Unauthorized }); return Ok(new { token = tokenPair.AccessToken, accessToken = tokenPair.AccessToken, refreshToken = tokenPair.RefreshToken, expiresIn = tokenPair.ExpiresIn }); } [HttpPost("refresh")] public async Task Refresh([FromBody] RefreshTokenRequest request) { if (string.IsNullOrWhiteSpace(request.RefreshToken)) return BadRequest(new ProblemDetails { Title = "Refresh token이 필요합니다.", Status = StatusCodes.Status400BadRequest }); var tokenPair = await _authService.RefreshAccessTokenAsync(request.RefreshToken); if (tokenPair == null) return Unauthorized(new ProblemDetails { Title = "Refresh token이 유효하지 않습니다.", Status = StatusCodes.Status401Unauthorized }); return Ok(new { token = tokenPair.AccessToken, accessToken = tokenPair.AccessToken, refreshToken = tokenPair.RefreshToken, expiresIn = tokenPair.ExpiresIn }); } [HttpPost("change-password")] [Microsoft.AspNetCore.Authorization.Authorize] public async Task ChangePassword([FromBody] ChangePasswordRequest request) { var username = User.FindFirstValue(ClaimTypes.Name); if (string.IsNullOrWhiteSpace(username)) return Unauthorized(new ProblemDetails { Title = "인증 정보가 올바르지 않습니다.", Status = StatusCodes.Status401Unauthorized }); try { var changed = await _authService.ChangePasswordAsync(username, request.CurrentPassword, request.NewPassword); if (!changed) return Unauthorized(new ProblemDetails { Title = "현재 비밀번호가 올바르지 않습니다.", Status = StatusCodes.Status401Unauthorized }); return Ok(new { message = "비밀번호가 변경되었습니다." }); } catch (ArgumentException ex) { return BadRequest(new ProblemDetails { Title = ex.Message, Status = StatusCodes.Status400BadRequest }); } } [HttpPost("reset-password")] public async Task ResetPassword([FromBody] ResetPasswordRequest request) { try { var reset = await _authService.ResetPasswordAsync(request.Username, request.NewPassword, request.ResetToken); if (!reset) return Unauthorized(new ProblemDetails { Title = "재설정 토큰 또는 사용자 정보가 올바르지 않습니다.", Status = StatusCodes.Status401Unauthorized }); return Ok(new { message = "비밀번호가 재설정되었습니다." }); } catch (InvalidOperationException) { return StatusCode(StatusCodes.Status503ServiceUnavailable, new ProblemDetails { Title = "비밀번호 재설정 토큰이 서버에 설정되어 있지 않습니다.", Status = StatusCodes.Status503ServiceUnavailable }); } catch (ArgumentException ex) { return BadRequest(new ProblemDetails { Title = ex.Message, Status = StatusCodes.Status400BadRequest }); } } } public class LoginRequest { public string Username { get; set; } = string.Empty; public string Password { get; set; } = string.Empty; } public class ChangePasswordRequest { public string CurrentPassword { get; set; } = string.Empty; public string NewPassword { get; set; } = string.Empty; } public class ResetPasswordRequest { public string Username { get; set; } = string.Empty; public string NewPassword { get; set; } = string.Empty; public string ResetToken { get; set; } = string.Empty; } public class RefreshTokenRequest { public string RefreshToken { get; set; } = string.Empty; }