""" 인증 라우터 - 로그인 - 로그아웃 - 현재 사용자 정보 조회 """ from fastapi import APIRouter, Depends, HTTPException, status, Response from fastapi.security import OAuth2PasswordRequestForm from sqlalchemy.orm import Session from datetime import timedelta from database import get_db from models import User from schemas import Token, User as UserSchema, UserLogin from auth import ( verify_password, create_access_token, get_current_user, ACCESS_TOKEN_EXPIRE_HOURS ) router = APIRouter() @router.post("/login", response_model=Token) async def login( response: Response, form_data: OAuth2PasswordRequestForm = Depends(), db: Session = Depends(get_db) ): """로그인 Args: form_data: OAuth2 폼 데이터 (username, password) Returns: Token: JWT 액세스 토큰 HTTP-only 쿠키에도 토큰 저장 """ # 사용자 조회 user = db.query(User).filter(User.username == form_data.username).first() # 사용자 존재 여부 및 비밀번호 검증 if not user or not verify_password(form_data.password, user.password_hash): raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="사용자명 또는 비밀번호가 잘못되었습니다", headers={"WWW-Authenticate": "Bearer"}, ) # 비활성화된 사용자 체크 if not user.is_active: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="비활성화된 사용자입니다" ) # JWT 토큰 생성 access_token_expires = timedelta(hours=ACCESS_TOKEN_EXPIRE_HOURS) access_token = create_access_token( data={"sub": user.username}, expires_delta=access_token_expires ) # HTTP-only 쿠키에 토큰 저장 response.set_cookie( key="access_token", value=access_token, httponly=True, max_age=ACCESS_TOKEN_EXPIRE_HOURS * 3600, secure=False, # HTTPS 사용 시 True로 변경 samesite="lax" ) return {"access_token": access_token, "token_type": "bearer"} @router.post("/logout") async def logout(response: Response): """로그아웃 쿠키에서 토큰 제거 """ response.delete_cookie(key="access_token") return {"message": "로그아웃 되었습니다"} @router.get("/me", response_model=UserSchema) async def get_me(current_user: User = Depends(get_current_user)): """현재 로그인한 사용자 정보 조회 Returns: User: 현재 사용자 정보 """ return current_user @router.get("/check") async def check_auth(current_user: User = Depends(get_current_user)): """인증 상태 확인 (프론트엔드용) Returns: dict: 인증 여부 및 사용자 정보 """ return { "authenticated": True, "user": { "id": current_user.id, "username": current_user.username, "role": current_user.role, "store_id": current_user.store_id, "franchise_id": current_user.franchise_id } }