添加动态权限控制

This commit is contained in:
xie7654
2025-07-02 21:54:13 +08:00
parent eace8a524d
commit 78b9f9e832
12 changed files with 186 additions and 24 deletions

View File

@@ -20,6 +20,38 @@ class CustomModelViewSet(viewsets.ModelViewSet):
# 是否支持软删除
enable_soft_delete = False
def get_required_permission(self):
# 约定system:menu:create
app_label = self.queryset.model._meta.app_label
model_name = self.queryset.model._meta.model_name
action = self.action # 'create', 'update', 'destroy', 'list', 'retrieve'
# 只对增删改查等操作做权限控制
action_map = {
'create': 'create',
'update': 'edit',
'partial_update': 'edit',
'destroy': 'delete',
'list': 'query',
'retrieve': 'query',
}
if action in action_map:
perm_action = action_map[action]
else:
perm_action = action # 如 sync、import、export
return f"{app_label}:{model_name}:{perm_action}"
def get_permissions(self):
permissions = super().get_permissions()
required_code = self.get_required_permission()
if required_code:
from utils.permissions import HasButtonPermission
perm = HasButtonPermission()
# 动态设置 required_permission
perm.required_permission = required_code
permissions.append(perm)
return permissions
def get_serializer_class(self):
"""根据当前动作获取序列化器类"""
return self.action_serializers.get(
@@ -27,13 +59,6 @@ class CustomModelViewSet(viewsets.ModelViewSet):
super().get_serializer_class()
)
def get_permissions(self):
"""根据当前动作获取权限类"""
permissions = self.action_permissions.get(
self.action,
self.permission_classes
)
return [permission() for permission in permissions]
def list(self, request, *args, **kwargs):
"""重写列表视图,支持软删除过滤"""

View File

@@ -1,8 +1,48 @@
from rest_framework import permissions
from rest_framework.permissions import BasePermission
from system.models import Menu
class IsSuperUserOrReadOnly(permissions.BasePermission):
class IsSuperUserOrReadOnly(BasePermission):
"""超级用户可读写,普通用户只读"""
def has_permission(self, request, view):
if request.method in permissions.SAFE_METHODS:
return True
return request.user and request.user.is_superuser
class HasButtonPermission(BasePermission):
"""
通用按钮权限校验
用法:在视图中设置 required_permission = 'xxx:xxx:xxx'
"""
def has_permission(self, request, view):
required_code = getattr(view, 'required_permission', None)
if not required_code:
# 可自动推断权限编码逻辑
app_label = view.queryset.model._meta.app_label
model_name = view.queryset.model._meta.model_name
action = getattr(view, 'action', None)
action_map = {
'create': 'create',
'update': 'edit',
'partial_update': 'edit',
'destroy': 'delete',
'list': 'query',
'retrieve': 'query',
}
if action in action_map:
required_code = f"{app_label}:{model_name}:{action_map[action]}"
if not required_code:
return True # 不需要按钮权限
user = request.user
if not user.is_authenticated or user.is_anonymous:
return False
if user.is_superuser:
return True
role_ids = user.role.values_list('id', flat=True)
return Menu.objects.filter(
type='button',
role__id__in=role_ids,
auth_code=required_code
).exists()