rests框架中的自定义权限

问题描述 投票:0回答:1

我的应用程序需要 DRF 中的权限。

输入:

  • 未经身份验证的用户只能阅读出版物和图像

  • 经过身份验证的用户可以创建出版物并添加图像

  • 授权用户可以编辑和删除他们作为作者的出版物和图像

  • 管理员用户可以执行所有操作,但编辑内容

型号:

class Publication(models.Model):
    pub_text = models.TextField(null=True, blank=True)
    pub_date = models.DateTimeField(auto_now_add=True)
    pub_author = models.ForeignKey(User, on_delete=models.CASCADE)

class Image(models.Model):
    image = models.ImageField(upload_to='images', null=True)
    image_to_pub = models.ForeignKey(Publication, on_delete=models.CASCADE, null=True, related_name='images')

浏览次数:

class PublicationViewSet(viewsets.ModelViewSet):
    queryset = Publication.objects.all()
    serializer_class = PublicationSerializer
    permission_classes = [PublicPermission]


class ImageViewSet(viewsets.ModelViewSet):
    queryset = Image.objects.all()
    serializer_class = ImageSerializer
    permission_classes = [ImagePermission]

权限:

class ImagePermission(BasePermission):

    edit_methods = ['PUT', 'PATCH']

    def has_permission(self, request, view):
        if request.method in SAFE_METHODS:
            return True
        if request.user.is_authenticated:
            return True

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

        if request.user.is_superuser:
            return True

        if request.method in SAFE_METHODS:
            return True

        if request.user.id == Publication.objects.get(id=obj.image_to_pub_id).pub_author_id:
            return True

        if request.user.is_staff and request.method not in self.edit_methods:
            return True

        return False


class ImageAuthorPermission(BasePermission):
    def has_object_permission(self, request, view, obj):
        if request.user.id == Publication.objects.get(id=obj.image_to_pub_id).pub_author_id:
            return True
        return False

现在它的工作原理就像我上面描述的那样。但我不确定这是否是好的做法。

我的意思是班级。 SAFE_METHODS中有两次检查if方法。

如果我从 删除该签出,未经身份验证的用户没有只读权限。

如果我从 删除该签出,经过身份验证的用户没有编辑和删除权限。

我确信有更好的方法来自定义此权限。不是有吗

我还尝试检查当前用户是否对与用户作者的出版物相关的图像具有对象权限。这是可行的,但是是否有标准实践如何检查相关对象的权限?我尝试删除支票

if request.user.id == Publication.objects.get(id=obj.image_to_pub_id).pub_author_id:

中取出 并将 类合并到 列表中。使用&和|运营商,但没有获得成功。

python django django-rest-framework permissions
1个回答
0
投票

我看到了这部分并实现了它。

  1. 未经身份验证的用户只能阅读出版物和图像
  2. 经过身份验证的用户可以创建出版物并添加图像
  3. 授权用户可以编辑和删除他们作为作者的出版物和图像
  4. 管理员用户可以执行所有操作,但编辑内容

首先,SAFE_METHOD请求必须是只读的,并且只能对经过身份验证的用户进行创建等操作。

对于这部分,使用 DRF Permission 默认提供的 IsAuthenticatedOrReadOnly 类。

rest_framework.permission

class IsAuthenticatedOrReadOnly(BasePermission):
    """
    The request is authenticated as a user, or is a read-only request.
    """

    def has_permission(self, request, view):
        return bool(
            request.method in SAFE_METHODS or
            request.user and
            request.user.is_authenticated
        )

实现第3、4条,只有所有者可以修改和删除,管理员只能修改(“PUT”,“PATCH”)。

首先,我创建了 AdminObjectPermission 类来解决数字 4。

class AdminObjectPermission(BasePermission):
  
  def has_object_permission(self, request, view, obj):
    if bool(request.user and request.user.is_staff) and request.method in ["PUT", "PATCH"]:
      return True

从上面的代码可以看出,Client是admin用户,请求中使用的方法必须是“PATCH”或“PUT”

对于第 3 个,您可以将 request.user 与对象的用户连接起来。

from rest_framework.permissions import IsAuthenticatedOrReadOnly, BasePermission


class AdminObjectPermission(BasePermission):
  
  def has_object_permission(self, request, view, obj):
    if bool(request.user and request.user.is_staff) and request.method in ["PUT", "PATCH"]:
      return True


class PublicPermission(IsAuthenticatedOrReadOnly, AdminObjectPermission):
  
  def has_object_permission(self, request, view, obj):
    
    if super().has_object_permission(request, view, obj):
      return True 
    
    if request.user.id == obj.pub_author.id:
      return True
    
    return False


class ImagePermission(IsAuthenticatedOrReadOnly, AdminObjectPermission):
  
  def has_object_permission(self, request, view, obj):
    
    if super().has_object_permission(request, view, obj):
      return True

    if request.user.id == obj.image_to_pub.pub_author.id:
      return True
    
    return False

对于 Publication 对象,它通过 pub_author 字段与 User 关联。

if request.user.id == obj.pub_author.id

通过 pub_author 在连接的 Publication 对象上比较图像对象。

if request.user.id == obj.image_to_pub.pub_author.id

© www.soinside.com 2019 - 2024. All rights reserved.