Files
server/users/permission.py
T

94 lines
3.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from typing import List
from django.core.cache import cache
from loguru import logger
from users.models import User, Menu # 替换为你的实际 app 名
def get_user_permissions(user_id: int) -> List[str]:
"""
获取用户所有按钮级权限标识(permission_code
利用 Django ORM 的多对多关系链式查询
"""
cache_key = f"user_permissions_{user_id}"
permissions = cache.get(cache_key)
logger.info(f"当前缓存的权限列表:{permissions}")
if permissions is None:
try:
# 链式查询:用户 → 角色 → 菜单(仅按钮类型)
permissions = list(
Menu.objects.filter(
roles__users__id=user_id, # 通过 roles__users 反向关联到用户
menu_type=2, # 2 = 按钮
status=True
)
.values_list('permission_code', flat=True)
.distinct()
)
logger.info(f"当前获取到的权限列表:{permissions}")
cache.set(cache_key, permissions, 3600) # 缓存1小时
except User.DoesNotExist:
return []
logger.info(f"当前用户的权限列表:{permissions}")
return permissions
def has_permission(user_id: int, permission_code: str) -> bool:
"""检查用户是否拥有指定权限"""
if not permission_code:
return True
return permission_code in get_user_permissions(user_id)
def clear_user_permissions_cache(user_id: int):
"""清除用户权限缓存(当角色或菜单变更时调用)"""
cache.delete(f"user_permissions_{user_id}")
# 批量清除缓存的辅助函数(可选)
def clear_all_users_permissions_cache():
"""清除所有用户权限缓存(谨慎使用)"""
# 实际项目中可通过信号或更精细的方式处理
cache.clear() # 或遍历已知用户ID
def build_menu_tree(menus):
"""高效构建菜单树(O(n) 时间复杂度)"""
# 1. 将菜单列表转为字典,key=id
menu_dict = {}
for menu in menus:
menu_dict[menu.id] = {
'id': menu.id,
'name': menu.name,
'code': menu.code,
'path': menu.path,
'component': menu.component,
'icon': menu.icon,
'order_num': menu.order_num,
'parent_id': menu.parent_id, # ✅ 只存 ID,避免对象引用
'permission_code': menu.permission_code,
'menu_type': menu.menu_type,
'children': [] # 初始化为空列表
}
# 2. 构建树结构
tree = []
for menu_id, node in menu_dict.items():
parent_id = node['parent_id']
if parent_id is None or parent_id not in menu_dict:
# 根节点(parent_id 为 None 或指向不存在的父节点)
tree.append(node)
else:
# 添加到父节点的 children
menu_dict[parent_id]['children'].append(node)
# 3. (可选)按 order_num 排序
def sort_children(nodes):
nodes.sort(key=lambda x: x['order_num'] or 0)
for node in nodes:
sort_children(node['children'])
sort_children(tree)
return tree