77 lines
2.3 KiB
Python
77 lines
2.3 KiB
Python
"""移动市场接口的严格菜单权限守卫。"""
|
|
from typing import Callable, Iterable
|
|
|
|
from fastapi import Depends, HTTPException
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app.core.auth import get_current_user
|
|
from app.core.database import get_db
|
|
from app.services.web_auth_roles import (
|
|
iter_user_menu_perm_codes,
|
|
resolve_web_role_for_user,
|
|
)
|
|
|
|
|
|
def require_market_menu_permission(
|
|
*,
|
|
user_id: str,
|
|
tenant_no: str,
|
|
required: str,
|
|
granted: Iterable[str],
|
|
) -> bool:
|
|
"""严格判断当前租户用户是否拥有指定移动市场权限码。"""
|
|
uid = (user_id or "").strip()
|
|
tenant = (tenant_no or "").strip()
|
|
code = (required or "").strip()
|
|
if not uid or not tenant or not code:
|
|
return False
|
|
return code in {(item or "").strip() for item in granted if item}
|
|
|
|
|
|
def user_has_tenant_menu_perm(
|
|
db: Session,
|
|
*,
|
|
user_id: str,
|
|
tenant_no: str,
|
|
perm_code: str,
|
|
) -> bool:
|
|
"""按显式租户读取用户权限,不回退默认租户。"""
|
|
tenant = (tenant_no or "").strip()
|
|
uid = (user_id or "").strip()
|
|
if not tenant or not uid:
|
|
return False
|
|
granted = iter_user_menu_perm_codes(db, uid, tenant_no=tenant)
|
|
return require_market_menu_permission(
|
|
user_id=uid,
|
|
tenant_no=tenant,
|
|
required=perm_code,
|
|
granted=granted,
|
|
)
|
|
|
|
|
|
def require_market_menu_code(menu_code: str) -> Callable:
|
|
"""为移动市场 API 提供租户化、精确匹配的菜单权限依赖。"""
|
|
required = (menu_code or "").strip()
|
|
|
|
async def dependency(
|
|
user: dict = Depends(get_current_user),
|
|
db: Session = Depends(get_db),
|
|
) -> dict:
|
|
tenant_no = str(user.get("tenant_no") or "").strip()
|
|
user_id = str(user.get("user_id") or "").strip()
|
|
if not tenant_no or not user_id:
|
|
raise HTTPException(status_code=403, detail="用户租户或身份信息缺失")
|
|
tenant_role = resolve_web_role_for_user(
|
|
db, user_id, tenant_no=tenant_no
|
|
)
|
|
if tenant_role != "super_admin" and not user_has_tenant_menu_perm(
|
|
db,
|
|
user_id=user_id,
|
|
tenant_no=tenant_no,
|
|
perm_code=required,
|
|
):
|
|
raise HTTPException(status_code=403, detail="无移动端菜单权限")
|
|
return user
|
|
|
|
return dependency
|