繁体   English   中英

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

[英]Django REST Framework - Allow staff to access all endpoints

我正在构建一个 DRF API,我希望允许工作人员 ( is_staff == True ) 访问所有 REST 端点,同时仍然为每个 ViewSet 提供自定义权限检查。 理想情况下,这将是一个全局设置,但我不反对按 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逻辑,并将其添加到 ViewSet:

from rest_framework import permissions, viewsets

class SomeModelViewSet(viewsets.ModelViewSet):
    permission_classes = (permissions.IsAdminUser|SomeModelPermission,)

但是,这实际上并没有像我希望的那样强制执行权限,因为IsAdminUser继承自BasePermission ,其定义为:

class BasePermission(object):
    def has_permission(self, request, view):
        return True

    def has_object_permission(self, request, view, obj):
        return True

IsAdminUser并没有定义自己的has_object_permission ,所以在检查对象权限时总是返回True ,导致意外的对象访问。


有任何想法吗? 我希望有某种方法可以设置全局权限检查,当用户是工作人员时返回True ,否则遵循自定义权限。 但是阅读权限是如何确定的,我不确定这是可能的。

按位解:

如何创建自己的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)

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

from rest_framework import permissions, viewsets
from your_own_project.permissions import IsAdminUser

class SomeModelViewSet(viewsets.ModelViewSet):
    permission_classes = (IsAdminUser|SomeModelPermission,)


另一种解决方案:

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

所以最终的结果应该是这样的:

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)

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

管理员用户有一个权限类。 这是一个例子:

class deletecompletedreopenjobAPIView(RetrieveUpdateAPIView):
    queryset = Job.objects._all()
    serializer_class = JobCompletedDeleteStatusSerializer
    lookup_field = 'job_id'
    permission_classes = [IsOwnerOrReadOnly | **IsAdminUser**]
    authentication_classes = (authentication.TokenAuthentication,)

我的自定义 IsOwnerOrReadOnly 如下:

class IsOwnerOrReadOnly(BasePermission):
    def has_object_permission(self, request, view, obj):
        if request.method in SAFE_METHODS:
            return True
        return obj.user == request.user

即使在 Django Rest Framework

[英]I'm getting 'No Access-Control-Allow-Origin header is present on the requested resource' even with all configured in Django Rest Framework

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM