using FastEndpoints; using TaxBaik.Web.Services; namespace TaxBaik.Web.Endpoints.Auth; public class LoginRequest { public string Username { get; set; } = string.Empty; public string Password { get; set; } = string.Empty; } public class TokenPairResponse { public string Token { get; set; } = string.Empty; public string AccessToken { get; set; } = string.Empty; public string RefreshToken { get; set; } = string.Empty; public int ExpiresIn { get; set; } } public class LoginEndpoint : Endpoint { private readonly AuthService _authService; public LoginEndpoint(AuthService authService) { _authService = authService; } public override void Configure() { Post("/api/auth/login"); AllowAnonymous(); } public override async Task HandleAsync(LoginRequest request, CancellationToken ct) { if (string.IsNullOrWhiteSpace(request.Username) || string.IsNullOrWhiteSpace(request.Password)) { ThrowError("로그인 정보가 필요합니다."); } var authResult = await _authService.AuthenticateAndGenerateTokenPairAsync(request.Username, request.Password); if (!authResult.IsSuccess || authResult.TokenPair is null) { ThrowError(authResult.FailureReason == AuthFailureReason.DatabaseUnavailable ? "로그인 서비스를 일시적으로 사용할 수 없습니다." : "아이디 또는 비밀번호가 올바르지 않습니다."); } await SendAsync(new TokenPairResponse { Token = authResult.TokenPair!.AccessToken, AccessToken = authResult.TokenPair.AccessToken, RefreshToken = authResult.TokenPair.RefreshToken, ExpiresIn = authResult.TokenPair.ExpiresIn }, 200, cancellation: ct); } }