88 lines
3.0 KiB
Python
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()
|