Files
vconnect-api/app/services/auth_service.py
2025-12-08 21:35:55 +09:00

88 lines
3.0 KiB
Python

from sqlalchemy.orm import Session
from datetime import datetime
from typing import Optional
from app.models.user import User, UserRole
from app.schemas.auth import UserRegister, Token
from app.utils.security import hash_password, verify_password
from app.utils.jwt_handler import create_access_token, create_refresh_token
from app.utils.exceptions import AuthenticationError, ConflictError
class AuthService:
"""인증 관련 비즈니스 로직"""
@staticmethod
def register_user(db: Session, user_data: UserRegister) -> User:
"""사용자 등록"""
# 중복 체크
if db.query(User).filter(User.username == user_data.username).first():
raise ConflictError("이미 존재하는 사용자명입니다")
if db.query(User).filter(User.email == user_data.email).first():
raise ConflictError("이미 존재하는 이메일입니다")
# 새 사용자 생성
new_user = User(
username=user_data.username,
email=user_data.email,
hashed_password=hash_password(user_data.password),
full_name=user_data.full_name,
role=UserRole.USER
)
db.add(new_user)
db.commit()
db.refresh(new_user)
return new_user
@staticmethod
def authenticate_user(db: Session, username: str, password: str) -> User:
"""사용자 인증"""
user = db.query(User).filter(User.username == username).first()
if not user:
raise AuthenticationError("사용자를 찾을 수 없습니다")
if not user.is_active:
raise AuthenticationError("비활성화된 계정입니다")
if not verify_password(password, user.hashed_password):
raise AuthenticationError("비밀번호가 일치하지 않습니다")
# 마지막 로그인 시간 업데이트
user.last_login = datetime.utcnow()
db.commit()
return user
@staticmethod
def create_tokens(user: User) -> Token:
"""JWT 토큰 생성"""
token_data = {
"sub": str(user.id),
"username": user.username,
"role": user.role.value
}
access_token = create_access_token(token_data)
refresh_token = create_refresh_token(token_data)
return Token(
access_token=access_token,
refresh_token=refresh_token,
token_type="bearer",
expires_in=1800 # 30분
)
@staticmethod
def get_user_by_id(db: Session, user_id: int) -> Optional[User]:
"""사용자 ID로 조회"""
return db.query(User).filter(User.id == user_id).first()
@staticmethod
def get_user_by_username(db: Session, username: str) -> Optional[User]:
"""사용자명으로 조회"""
return db.query(User).filter(User.username == username).first()
auth_service = AuthService()