menu_guard.py 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. """菜单 code 权限守卫"""
  2. from typing import Callable, Set
  3. from fastapi import Depends, HTTPException
  4. from sqlalchemy.orm import Session
  5. from app.core.auth import get_current_user
  6. from app.core.database import get_db
  7. from app.models.models import SysUserMenuScope
  8. ADMIN_ROLES = {"admin", "super_admin"}
  9. SUPER_ADMIN_ROLE = "super_admin"
  10. def require_admin_or_super_admin(current_user: dict = Depends(get_current_user)):
  11. """运营端角色守卫:admin / super_admin 可访问。"""
  12. role = current_user.get("role")
  13. if role not in ADMIN_ROLES:
  14. raise HTTPException(status_code=403, detail="需要运营人员权限")
  15. return current_user
  16. def get_user_menu_codes(db: Session, user_id: str) -> Set[str]:
  17. """读取用户授权的菜单 code 集合。"""
  18. if not user_id:
  19. return set()
  20. rows = (
  21. db.query(SysUserMenuScope.menu_code)
  22. .filter(
  23. SysUserMenuScope.user_id == user_id,
  24. SysUserMenuScope.is_del == 0,
  25. )
  26. .all()
  27. )
  28. return {str(row[0]).strip() for row in rows if row and row[0]}
  29. def require_menu_code(menu_code: str) -> Callable:
  30. """接口菜单权限守卫。super_admin 直接放行。"""
  31. normalized = (menu_code or "").strip()
  32. def _dep(
  33. current_user: dict = Depends(require_admin_or_super_admin),
  34. db: Session = Depends(get_db),
  35. ):
  36. role = current_user.get("role")
  37. if role == SUPER_ADMIN_ROLE:
  38. return current_user
  39. codes = get_user_menu_codes(db, current_user.get("user_id"))
  40. if normalized not in codes:
  41. raise HTTPException(status_code=403, detail="无菜单访问权限")
  42. return current_user
  43. return _dep