[FEAT] (사용자 로직) : 인증 서비스 구현 완료

v0.1.2 (2025-11-16)
- 로그인, 로그아웃, 토큰 갱신, 회원가입 API 구현 완료
- 로그 포맷 통일화
This commit is contained in:
2025-11-16 16:20:45 +09:00
parent ae2766cff5
commit e20c7d58b1
21 changed files with 792 additions and 56 deletions

View File

@@ -12,9 +12,12 @@ from repositories import UserRepository, UserIpsRepository
import settings
from utils import func
from utils.response import *
from utils.account_lock_policy import AccountLockPolicy
from utils.db_decorators import transactional
from services.auth.cache_service import JWTBlacklistService
from extensions import custom_logger
logger = custom_logger(f"{settings.LOG_PREFIX}_auth_service")
@@ -26,7 +29,7 @@ class AuthService:
@staticmethod
@transactional
def register(user_data: Dict[str, Any]) -> Users:
def register(user_data: Dict[str, Any]) -> Optional[Users]:
"""회원 가입"""
# Pydantic 검증
@@ -40,7 +43,7 @@ class AuthService:
# 중복 검사
if user_repo.exists_by_id(user_id):
...
return None
# 비밀번호 생성
hash_password = func.hash_password(password)
@@ -48,7 +51,7 @@ class AuthService:
# 사용자 생성
user = Users(
id=user_id,
password=hash_password,
hash_password=hash_password,
user_name=user_name
)
@@ -59,7 +62,7 @@ class AuthService:
@staticmethod
@transactional
def login(credentials: Dict[str, Any]) -> Tuple[Users, str, str]:
def login(credentials: Dict[str, Any]) -> Optional[Tuple[Users, str, str]]:
# Pydantic 검증
check_user_dto = user_dto.CheckUserDTO(**credentials)
@@ -69,7 +72,7 @@ class AuthService:
# 사용자 조회
user = user_repo.find_by_id(check_user_dto.id)
if not user:
...
return None
# 계정 잠금 정책 체크
lock_policy = AccountLockPolicy(
@@ -78,14 +81,13 @@ class AuthService:
)
if lock_policy.is_locked(user.count):
...
return None
# 비밀번호 검증
if not func.verify_password(check_user_dto.password, user.password):
user.increment_failed_login()
user_repo.update(user)
# commit되어 실패 횟수 기록
...
return None
# 로그인 성공 - 실패 횟수 초기화
user.reset_failed_login()
@@ -99,19 +101,26 @@ class AuthService:
logger.info(f"사용자 로그인: {user.id}")
return user, access_token, refresh_token
return (user, access_token, refresh_token)
@staticmethod
def refresh_access_token(user_uuid: str) -> str:
"""엑세스 토큰 갱신"""
access_token = create_access_token(identity=user_uuid)
logger.debug(f"Access Token 재발급: {user_uuid}")
return access_token
try:
"""엑세스 토큰 갱신"""
access_token = create_access_token(identity=user_uuid)
logger.debug(f"Access Token 재발급: {user_uuid}")
return access_token
except Exception as e:
logger.exception(f"유저 ({user_uuid}) 엑세스 토큰 갱신에 실패하였습니다. error={str(e)}")
return None
@staticmethod
def logout(jti: str) -> bool:
"""로그아웃 (JWT 블랙리스트 추가)"""
...
success = JWTBlacklistService.add(jti)
if success:
logger.info(f"로그아웃 처리 완료 - JTI 블랙리스트 추가: {jti}")
return success
@staticmethod
@transactional
@@ -125,9 +134,13 @@ class AuthService:
user_agent = request.headers.get('User-Agent', '') if request.headers else ''
# 기존 IP 기록 조회 로직
if True:
...
existing_ip = user_ips_repo.find_by_user_and_ip(user, ip_address)
if existing_ip:
# 존재하면 마지막 접속 시간 업데이트
user_ips_repo.update_last_access(user.user_uuid, ip_address)
else:
# 없으면 새로 생성
user_ips = UserIps(
user_uuid=user.user_uuid,
user_ip=ip_address,