FastAPI - MiniProject - 3

김기훈·2025년 10월 29일

부트캠프 프로젝트

목록 보기
5/39

권한 처리 (자기 글만 수정 가능)

# app/api/vi/diary.py

from fastapi import APIRouter, Depends, HTTPException
from app.models.diary import Diary
from app.core.dependencies import get_current_user
from app.models.user import User

router = APIRouter(prefix="/diary", tags=["Diary"])

@router.put("/{diary_id}")
async def update_diary(
    diary_id: int,
    title: str,
    content: str,
    current_user: User = Depends(get_current_user)
):
    # 글 존재 여부 확인
    diary = await Diary.get_or_none(id=diary_id)
    if not diary:
        raise HTTPException(status_code=404, detail="Diary not found")

    # 권한 체크: 본인 글인지 확인
    if diary.user_id != current_user.id:
        raise HTTPException(status_code=403, detail="You are not the author of this diary")

    # 수정
    diary.title = title
    diary.content = content
    await diary.save()

    return {"message": "Diary updated successfully", "diary": diary}

권한처리(자기글만 삭제가능)

async def update_diary(
    diary_id: int,
    title: str,
    content: str,
    current_user: User = Depends(get_current_user)
):

@router.delete("/{diary_id}")
async def delete_diary(
    diary_id: int,
    current_user: User = Depends(get_current_user)
):
    diary = await Diary.get_or_none(id=diary_id)
    if not diary:
        raise HTTPException(status_code=404, detail="Diary not found")

    if diary.user_id != current_user.id:
        raise HTTPException(status_code=403, detail="You are not the author of this diary")

    await diary.delete()
    return {"message": "Diary deleted successfully"}

  • 비동기 뷰 함수 정의
    • diary_id: int:
      • 경로 파라미터(path param). URL의 {diary_id}를 정수로 받음.
    • title: str, content: str:
      • 쿼리 스트링 또는 폼/바디로 들어올 수 있는 함수 파라미터.
    • current_user: User = Depends(get_current_user):
      • 요청 헤더의 Bearer 토큰을 읽어 get_current_user가 현재 로그인한 유저를 찾아서 주입.
      • 인증 실패/만료/블랙리스트면 여기서 예외 발생.

diary = await Diary.get_or_none(id=diary_id)


핵심

  • current_user: User = Depends(get_current_user)
    • 이 엔드포인트를 실행하기 전에, get_current_user() 함수를 먼저 실행해서
    • 로그인한 사용자를 찾아내고, 그 결과(User 객체)를 current_user 변수에 자동으로 넣어달라

Depends()

  • 의존성 주입(Dependency Injection) 기능
    • 공통적으로 필요한 로직을 함수 바깥에서 자동으로 실행하게 해주는 FastAPI의 도우미

get_current_user()

from fastapi import Depends, HTTPException
from jose import jwt, JWTError
from app.core.config import settings
from app.repositories.user_repo import UserRepository
from app.repositories.token_repo import TokenRepository
from fastapi.security import OAuth2PasswordBearer

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/auth/login")

async def get_current_user(token: str = Depends(oauth2_scheme)):
    # 1️⃣ 토큰 블랙리스트 체크 (로그아웃된 토큰인지)
    if await TokenRepository.is_blacklisted(token):
        raise HTTPException(status_code=401, detail="Token has been revoked")

    try:
        # 2️⃣ 토큰 복호화
        payload = jwt.decode(token, settings.SECRET_KEY, algorithms=[settings.ALGORITHM])
        username: str = payload.get("sub")

        # 3️⃣ 토큰 안에 username 정보가 없으면 오류
        if username is None:
            raise HTTPException(status_code=401, detail="Invalid token")

    except JWTError:
        # 4️⃣ 서명 검증 실패 or 만료
        raise HTTPException(status_code=401, detail="Invalid token")

    # 5️⃣ DB에서 유저 정보 가져오기
    user = await UserRepository.get_by_username(username)
    if not user:
        raise HTTPException(status_code=404, detail="User not found")

    # 6️⃣ 모든 검증 통과 시 유저 객체 반환
    return user
단계설명실패 시
요청 헤더의 Authorization: Bearer <token> 에서 토큰 꺼냄 (oauth2_scheme)자동 401
DB에서 블랙리스트 여부 확인 (로그아웃된 토큰 차단)401
JWT 토큰 복호화 → payload 추출401
sub(username) 가져와서 검증401
DB에서 해당 username 유저 조회404
성공 시 User 객체 반환-
profile
안녕하세요.

0개의 댓글