from fastapi import APIRouter, Depends, HTTPException, status from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials from sqlalchemy.orm import Session from app.database import get_db from app.schemas.auth import UserRegister, UserLogin, Token, UserResponse, CurrentUser from app.services.auth_service import auth_service from app.utils.jwt_handler import decode_token from app.utils.exceptions import AuthenticationError router = APIRouter() security = HTTPBearer() # 현재 사용자 가져오기 의존성 async def get_current_user( credentials: HTTPAuthorizationCredentials = Depends(security), db: Session = Depends(get_db) ) -> CurrentUser: """JWT 토큰에서 현재 사용자 정보 추출""" token = credentials.credentials payload = decode_token(token) if not payload: raise AuthenticationError("유효하지 않은 토큰입니다") user_id = payload.get("sub") if not user_id: raise AuthenticationError("토큰 정보가 올바르지 않습니다") user = auth_service.get_user_by_id(db, int(user_id)) if not user: raise AuthenticationError("사용자를 찾을 수 없습니다") if not user.is_active: raise AuthenticationError("비활성화된 계정입니다") return CurrentUser( id=user.id, username=user.username, email=user.email, role=user.role, is_active=user.is_active ) @router.post("/register", response_model=UserResponse, status_code=status.HTTP_201_CREATED) async def register(user_data: UserRegister, db: Session = Depends(get_db)): """ 회원가입 새로운 사용자 계정을 생성합니다. """ user = auth_service.register_user(db, user_data) return user @router.post("/login", response_model=Token) async def login(login_data: UserLogin, db: Session = Depends(get_db)): """ 로그인 사용자 인증 후 JWT 토큰을 발급합니다. """ user = auth_service.authenticate_user(db, login_data.username, login_data.password) tokens = auth_service.create_tokens(user) return tokens @router.get("/me", response_model=UserResponse) async def get_me( current_user: CurrentUser = Depends(get_current_user), db: Session = Depends(get_db) ): """ 현재 사용자 정보 조회 JWT 토큰을 기반으로 현재 로그인한 사용자 정보를 반환합니다. """ user = auth_service.get_user_by_id(db, current_user.id) return user @router.post("/refresh", response_model=Token) async def refresh_token( credentials: HTTPAuthorizationCredentials = Depends(security), db: Session = Depends(get_db) ): """ 토큰 갱신 Refresh Token을 사용하여 새로운 Access Token을 발급합니다. """ token = credentials.credentials payload = decode_token(token) if not payload or payload.get("type") != "refresh": raise AuthenticationError("유효하지 않은 Refresh Token입니다") user_id = payload.get("sub") user = auth_service.get_user_by_id(db, int(user_id)) if not user or not user.is_active: raise AuthenticationError("사용자를 찾을 수 없습니다") tokens = auth_service.create_tokens(user) return tokens