mobile_menu_guard.py 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. """移动市场接口的严格菜单权限守卫。"""
  2. from typing import Callable, Iterable
  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.services.web_auth_roles import (
  8. iter_user_menu_perm_codes,
  9. resolve_web_role_for_user,
  10. )
  11. def require_market_menu_permission(
  12. *,
  13. user_id: str,
  14. tenant_no: str,
  15. required: str,
  16. granted: Iterable[str],
  17. ) -> bool:
  18. """严格判断当前租户用户是否拥有指定移动市场权限码。"""
  19. uid = (user_id or "").strip()
  20. tenant = (tenant_no or "").strip()
  21. code = (required or "").strip()
  22. if not uid or not tenant or not code:
  23. return False
  24. return code in {(item or "").strip() for item in granted if item}
  25. def user_has_tenant_menu_perm(
  26. db: Session,
  27. *,
  28. user_id: str,
  29. tenant_no: str,
  30. perm_code: str,
  31. ) -> bool:
  32. """按显式租户读取用户权限,不回退默认租户。"""
  33. tenant = (tenant_no or "").strip()
  34. uid = (user_id or "").strip()
  35. if not tenant or not uid:
  36. return False
  37. granted = iter_user_menu_perm_codes(db, uid, tenant_no=tenant)
  38. return require_market_menu_permission(
  39. user_id=uid,
  40. tenant_no=tenant,
  41. required=perm_code,
  42. granted=granted,
  43. )
  44. def require_market_menu_code(menu_code: str) -> Callable:
  45. """为移动市场 API 提供租户化、精确匹配的菜单权限依赖。"""
  46. required = (menu_code or "").strip()
  47. async def dependency(
  48. user: dict = Depends(get_current_user),
  49. db: Session = Depends(get_db),
  50. ) -> dict:
  51. tenant_no = str(user.get("tenant_no") or "").strip()
  52. user_id = str(user.get("user_id") or "").strip()
  53. if not tenant_no or not user_id:
  54. raise HTTPException(status_code=403, detail="用户租户或身份信息缺失")
  55. tenant_role = resolve_web_role_for_user(
  56. db, user_id, tenant_no=tenant_no
  57. )
  58. if tenant_role != "super_admin" and not user_has_tenant_menu_perm(
  59. db,
  60. user_id=user_id,
  61. tenant_no=tenant_no,
  62. perm_code=required,
  63. ):
  64. raise HTTPException(status_code=403, detail="无移动端菜单权限")
  65. return user
  66. return dependency