SPMS_API/SPMS.Application/Services/AuthService.cs
seonkyu.kim b11c8dc918 feat: 관리자 로그인 API 구현 (#36)
- LoginRequestDto, LoginResponseDto 추가
- IAuthService, AuthService 구현 (BCrypt 비밀번호 검증)
- AdminRepository 구현 (GetByEmailAsync)
- AuthController 추가 (POST /v1/in/auth/login)
- DI 등록 (IAuthService, IAdminRepository)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-09 22:16:25 +09:00

87 lines
2.6 KiB
C#

using Microsoft.Extensions.Options;
using SPMS.Application.DTOs.Auth;
using SPMS.Application.Interfaces;
using SPMS.Application.Settings;
using SPMS.Domain.Common;
using SPMS.Domain.Exceptions;
using SPMS.Domain.Interfaces;
namespace SPMS.Application.Services;
public class AuthService : IAuthService
{
private readonly IAdminRepository _adminRepository;
private readonly IUnitOfWork _unitOfWork;
private readonly IJwtService _jwtService;
private readonly JwtSettings _jwtSettings;
public AuthService(
IAdminRepository adminRepository,
IUnitOfWork unitOfWork,
IJwtService jwtService,
IOptions<JwtSettings> jwtSettings)
{
_adminRepository = adminRepository;
_unitOfWork = unitOfWork;
_jwtService = jwtService;
_jwtSettings = jwtSettings.Value;
}
public async Task<LoginResponseDto> LoginAsync(LoginRequestDto request)
{
// 1. 이메일로 관리자 조회
var admin = await _adminRepository.GetByEmailAsync(request.Email);
if (admin is null)
{
throw new SpmsException(
ErrorCodes.LoginFailed,
"이메일 또는 비밀번호가 일치하지 않습니다.",
401);
}
// 2. 삭제된 계정 확인
if (admin.IsDeleted)
{
throw new SpmsException(
ErrorCodes.LoginFailed,
"이메일 또는 비밀번호가 일치하지 않습니다.",
401);
}
// 3. 비밀번호 검증 (BCrypt)
if (!BCrypt.Net.BCrypt.Verify(request.Password, admin.Password))
{
throw new SpmsException(
ErrorCodes.LoginFailed,
"이메일 또는 비밀번호가 일치하지 않습니다.",
401);
}
// 4. 토큰 생성
var accessToken = _jwtService.GenerateAccessToken(
admin.Id,
admin.Role.ToString());
var refreshToken = _jwtService.GenerateRefreshToken();
// 5. 최종 로그인 시간 업데이트
admin.LastLoginAt = DateTime.UtcNow;
_adminRepository.Update(admin);
await _unitOfWork.SaveChangesAsync();
// 6. 응답 반환
return new LoginResponseDto
{
AccessToken = accessToken,
RefreshToken = refreshToken,
ExpiresIn = _jwtSettings.ExpiryMinutes * 60,
Admin = new AdminInfoDto
{
AdminCode = admin.AdminCode,
Email = admin.Email,
Name = admin.Name,
Role = admin.Role.ToString()
}
};
}
}