fix: 基于实际用户拥有菜单返回tree

main
NoahLan 4 months ago
parent 94010c8c2b
commit 269d453e07

@ -1,6 +1,6 @@
import copy
from apiflask import APIBlueprint
from flask_jwt_extended import jwt_required
from flask_jwt_extended import jwt_required, current_user
from iti.applications.common.exceptions.biz_exp import BizException
from iti.applications.extensions import db
from iti.applications.models import SysMenu, sys_role_menu
@ -10,7 +10,7 @@ from iti.applications.routes.sys.schemas.menu import (
MenuUpdateRequest,
MenuExistsRequest,
)
from iti.applications.service.sys_menu import get_menu_tree
from iti.applications.service.sys_menu import get_menu_tree, get_user_menu_ids
from iti.applications.models import SysMenuSchema
from iti.applications.common.enums import MenuTypeEnum
from sqlalchemy import select, delete, func, exists
@ -40,7 +40,10 @@ def get_menu_tree_api():
过滤条件
- 状态为启用
- 类型为非按钮
- 基于当前用户实际拥有的菜单
"""
# 获取当前用户拥有的菜单ID
user_menu_ids = get_user_menu_ids(current_user.id)
return success(
get_menu_tree(
type_filter=[
@ -48,7 +51,8 @@ def get_menu_tree_api():
MenuTypeEnum.CATALOG,
MenuTypeEnum.EMBEDDED,
MenuTypeEnum.LINK,
]
],
user_menu_ids=user_menu_ids,
)
)

@ -1,13 +1,31 @@
from sqlalchemy.orm import noload
from sqlalchemy.sql._typing import ColumnExpressionArgument
from typing import List, Dict, Any, Optional
from typing import List, Dict, Any, Optional, Set
from iti.applications.extensions import db
from iti.applications.models import SysMenu
from iti.applications.models.sys_rel_role_menu import sys_role_menu
from iti.applications.models.sys_rel_user_role import sys_user_role
from iti.applications.common.enums import StatusEnum, MenuTypeEnum
from iti.applications.common.utils import (
build_tree_from_list,
)
from sqlalchemy import select
from sqlalchemy import select, distinct
def get_user_menu_ids(user_id: str) -> Set[str]:
"""
获取用户拥有的所有菜单ID通过角色关联
Args:
user_id: 用户ID
Returns:
用户拥有的菜单ID集合
"""
menu_ids = db.session.scalars(
select(distinct(sys_role_menu.c.menu_id))
.join(sys_user_role, sys_role_menu.c.role_id == sys_user_role.c.role_id)
.filter(sys_user_role.c.user_id == user_id)
).all()
return set(menu_ids)
def get_menu_tree(
@ -15,6 +33,7 @@ def get_menu_tree(
include_disabled: bool = True,
type_filter: Optional[List[MenuTypeEnum]] = None,
status_filter: Optional[List[StatusEnum]] = None,
user_menu_ids: Optional[Set[str]] = None,
) -> List[Dict[str, Any]]:
"""
获取菜单树
@ -23,6 +42,7 @@ def get_menu_tree(
include_disabled: 是否包含禁用菜单
type_filter: 菜单类型过滤 不填为不限制
status_filter: 状态过滤 不填为不限制
user_menu_ids: 用户拥有的菜单ID集合用于过滤用户实际拥有的菜单
"""
# 获取所有菜单数据
cte_query = build_descendants_cte(SysMenu.parent_id == parent_id)
@ -32,6 +52,8 @@ def get_menu_tree(
cte_query = cte_query.filter(SysMenu.type.in_(type_filter))
if status_filter:
cte_query = cte_query.filter(SysMenu.status.in_(status_filter))
if user_menu_ids is not None:
cte_query = cte_query.filter(SysMenu.id.in_(user_menu_ids))
cte_query = cte_query.order_by(SysMenu.parent_id, SysMenu.sort).options(
noload(SysMenu.parent), noload(SysMenu.children)
)

Loading…
Cancel
Save