deps.py 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849
  1. """FastAPI 依赖:当前用户与菜单权限校验"""
  2. from typing import Annotated, Callable
  3. from fastapi import Depends
  4. from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
  5. from sqlalchemy.orm import Session
  6. from app.core.database import get_db
  7. from app.core.response import AppHTTPError
  8. from app.core.security import TokenError, safe_decode_token
  9. from app.crud import menu as menu_crud
  10. from app.crud import user as user_crud
  11. from app.models.system import SysUser
  12. bearer_scheme = HTTPBearer(auto_error=False)
  13. def get_current_user(
  14. db: Annotated[Session, Depends(get_db)],
  15. creds: Annotated[HTTPAuthorizationCredentials | None, Depends(bearer_scheme)],
  16. ) -> SysUser:
  17. if creds is None or not creds.credentials:
  18. raise AppHTTPError(401, "未登录或令牌无效")
  19. try:
  20. payload = safe_decode_token(creds.credentials)
  21. except TokenError:
  22. raise AppHTTPError(401, "未登录或令牌无效") from None
  23. user_id = payload.get("sub")
  24. if not user_id:
  25. raise AppHTTPError(401, "未登录或令牌无效")
  26. user = user_crud.get_user_by_id(db, user_id)
  27. if not user or user.status != "0":
  28. raise AppHTTPError(401, "未登录或令牌无效")
  29. return user
  30. def require_menu(*codes: str) -> Callable:
  31. """当前用户角色若不拥有 codes 中任一权限点 → 403。"""
  32. needed = set(codes)
  33. def _dep(
  34. user: Annotated[SysUser, Depends(get_current_user)],
  35. db: Annotated[Session, Depends(get_db)],
  36. ) -> SysUser:
  37. if not menu_crud.role_has_any_menu_code(db, user.role_id, needed):
  38. raise AppHTTPError(403, "无权限")
  39. return user
  40. return _dep