Django-REST框架允许员工访问所有端点

2024-06-23 03:37:19 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在构建一个drfapi,我希望允许职员(is_staff == True)访问所有REST端点,同时仍然为每个ViewSet提供自定义权限检查。理想情况下,这将是一个全局设置,但我不反对按视图集设置。在

以下是我尝试过的方法:


选项1:检查每个自定义权限

from rest_framework import permissions

class SomeModelPermission(permissions.BasePermission):
    def has_permission(self, request, view):
        if request.user.is_staff:
            return True

        # other logic

    def has_object_permission(self, request, view, obj):
        if request.user.is_staff:
            return True

        # other logic

这是可行的,但我不想重复这么多代码。在


选项2:按位运算符

我尝试从上面的自定义权限中删除is_staff逻辑,并将其添加到视图集中:

^{pr2}$

但是,这实际上并不像我所希望的那样强制实施权限,因为IsAdminUser继承了BasePermission,其定义为:

^{3}$

IsAdminUser没有定义自己的has_object_permission,因此在检查对象权限时,它总是返回True,从而导致意外的对象访问。在


有什么想法吗?我希望有某种方法可以设置一个全局权限检查,当用户是职员时,它将返回True,否则将遵从自定义权限。但通读how permissions are determined,我不确定这是否可能。在


Tags: 方法selftrue权限permissionsisrequestdef
1条回答
网友
1楼 · 发布于 2024-06-23 03:37:19

按位解:

创建您自己的IsAdminUser,它也定义了has_object_permission,如何?你可以继承现有的:

from rest_framework.permissions import IsAdminUser as BaseIsAdminUser

class IsAdminUser(BaseIsAdminUser):
    def has_object_permission(self, request, view, obj):
        # Just reuse the same logic as `has_permission`...
        return self.has_permission(request, view)

然后,可以使用位运算符执行上面尝试的操作:

^{pr2}$

另一种解决方案:

在某些方面有点“老套”,但您可以尝试动态创建自己的权限类型。在

所以最终的结果是:

class SomeModelViewSet(viewsets.ModelViewSet):
    permission_classes = skip_for_staff((SomeModelPermission, SomeOtherPermission, ...))

实施过程类似于:

class StaffAllowedMixin:
    def has_permission(self, request, view):
        if request.user.is_staff:
            return True
        return super().has_permission(request, view)

    def has_object_permission(self, request, view, obj):
        if request.user.is_staff:
            return True
        return super().has_object_permission(request, view, obj)


def skip_for_staff(permission_classes):
    # You can probably also use a comprehension here, but for clarity:
    staff_allowed_classes = []
    for permission_class in permissions(
       staff_allowed_classes.append(
           # Create a new type (class) with name StaffAllowed<...>
           type(f"StaffAllowed{permission_class}",
                # Inherit from the mixin above, and from the original class
                (StaffAllowedMixin, permission_class),
                # empty dictionary means you don't want to override any attributes
                {})
           )
    return tuple(staff_allowed_classes)

本质上,对于每个权限类,您将创建一个新类,该类具有优先权,并检查用户是否为员工。 但是您可以在使用权限的情况下动态地执行此操作,而不必为每个权限预先定义权限。在

相关问题 更多 >

    热门问题