schoolbridge / backend /app /auth.py
tsKim
feat: schoolbridge spaces deploy (extract-text endpoint added)
7f105c8
"""사용자 식별 + 역할 검증.
X-User-Id 헤더로 사용자를 식별하고, 역할(teacher/parent)에 따른 권한을 검증한다.
시연 단계라 별도 비밀번호/토큰 없이 헤더 한 줄로 처리. 실제 운영 시 JWT/세션 도입 예정.
"""
from fastapi import Depends, Header, HTTPException, status
from app.models.schemas import UserProfile
# 모듈 레벨 인메모리 사용자 저장소. user.py 라우터와 공유.
_user_store: dict[str, UserProfile] = {}
def get_user(user_id: str) -> UserProfile | None:
return _user_store.get(user_id)
def upsert_user(profile: UserProfile) -> UserProfile:
_user_store[profile.user_id] = profile
return profile
def list_users() -> list[UserProfile]:
return list(_user_store.values())
def seed_demo_users() -> None:
"""시연용 기본 계정 시드. 이미 존재하면 덮어쓰지 않음."""
demos = [
UserProfile(user_id="teacher_001", role="teacher"),
UserProfile(user_id="teacher_002", role="teacher"),
UserProfile(user_id="parent_001", role="parent"),
UserProfile(user_id="parent_002", role="parent"),
UserProfile(user_id="parent_003", role="parent"),
]
for profile in demos:
_user_store.setdefault(profile.user_id, profile)
def require_user(x_user_id: str = Header(..., description="요청자 사용자 ID")) -> UserProfile:
"""X-User-Id 헤더 필수. 등록되지 않은 ID면 401."""
if not x_user_id:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="X-User-Id 헤더가 필요합니다",
)
profile = _user_store.get(x_user_id)
if profile is None:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail=f"등록되지 않은 사용자: {x_user_id}",
)
return profile
def require_teacher(user: UserProfile = Depends(require_user)) -> UserProfile:
if user.role != "teacher":
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="선생님 권한이 필요합니다",
)
return user
def require_parent(user: UserProfile = Depends(require_user)) -> UserProfile:
if user.role != "parent":
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="학부모 권한이 필요합니다",
)
return user