对象级权限

时间:2014-05-09 16:40:24

标签: django django-rest-framework

我想知道对象级权限的正确位置。我正在使用django-guardian和post_save hook:

def post_save(self, obj, created=False):
    assign_perm('view_media', self.request.user, obj)
    assign_perm('delete_media', self.request.user, obj)

这适用于简单对象,但链接对象会出现问题。我们来看这个例子:

模型

class FirstModel(models.Model):
    id = models.AutoField(primary_key=True, name='id', db_column='id')
    name = models.CharField(max_length=255, blank=True, null=True)

    class Meta:
        app_label = 'choices'

        permissions = (
            ('view_firstmodel', 'Can view firstmodel'),
            ('update_firstmodel', 'Can update firstmodel')
        )


class SecondModel(models.Model):
    id = models.AutoField(primary_key=True, name='id', db_column='id')
    name = models.CharField(max_length=255, blank=True, null=True)
    parent_firstmodel = models.ForeignKey(FirstModel, related_name='secondmodel_objects')

    class Meta:
        app_label = 'choices'

        permissions = (
            ('view_secondmodel', 'Can view secondmodel'),
            ('update_secondmodel', 'Can update secondmodel')
        )

串行器

class SecondModelSerializer(serializers.ModelSerializer):

    parent_firstmodel = serializers.PrimaryKeyRelatedField()

    class Meta:
        model = SecondModel
        fields = ('id', 'name', 'parent_firstmodel')


class FirstModelSerializer(serializers.ModelSerializer):

    secondmodel_objects = SecondModelSerializer(many=True, allow_add_remove=True)

    class Meta:
        model = FirstModel
        fields = ('id', 'name', 'secondmodel_objects')

视图

class FirstModelList(ListCreateAPIView):
    serializer_class = FirstModelSerializer
    model = FirstModel

    def post_save(self, obj, created=False):
        assign_perm('view_firstmodel', self.request.user, obj)
        assign_perm('update_firstmodel', self.request.user, obj)
        assign_perm('delete_firstmodel', self.request.user, obj)

    def get_queryset(self):
        return get_objects_for_user(self.request.user, 'view_firstmodel', klass=FirstModel)

class FirstModelDetail(RetrieveDestroyAPIView):
    serializer_class = FirstModelSerializer
    model = FirstModel

    def get_queryset(self):

        if self.request.method == 'GET':
            required_permission = 'view_firstmodel'
        elif self.request.method == 'PATCH':
            required_permission = 'update_firstmodel'
        elif self.request.method == 'DELETE':
            required_permission = 'delete_firstmodel'

        return get_objects_for_user(self.request.user, required_permission, klass=FirstModel)

class SecondModelList(ListCreateAPIView):
    serializer_class = SecondModelSerializer
    model = SecondModel

    def post_save(self, obj, created=False):
        assign_perm('view_secondmodel', self.request.user, obj)
        assign_perm('update_secondmodel', self.request.user, obj)
        assign_perm('delete_secondmodel', self.request.user, obj)

    def get_queryset(self):
        return get_objects_for_user(self.request.user, 'view_secondmodel', klass=SecondModel)


class SecondModelDetail(RetrieveDestroyAPIView):
    serializer_class = SecondModelSerializer
    model = SecondModel

    def get_queryset(self):

        if self.request.method == 'GET':
            required_permission = 'view_secondmodel'
        elif self.request.method == 'PATCH':
            required_permission = 'update_secondmodel'
        elif self.request.method == 'DELETE':
            required_permission = 'delete_secondmodel'

        return get_objects_for_user(self.request.user, required_permission, klass=SecondModel)

实际上,在第二个模型中没有检查 parent_firstmodel 字段是否引用了用户拥有权限的对象(比如查看权限)。

假设我们有2个用户,每个用户创建一个 firstmodel 对象:

{
   id: 1,
   name: "user1 object firstmodel",
   secondmodel_objects: []
}

{
   id: 2,
   name: "user2 object firstmodel",
   secondmodel_objects: []
}

现在,用户2可以很好地创建一个像这样的第二个模型对象:

{
    name: "user2 object secondmodel",
    parent_firstmodel: 1
}

所以基本上他把东西附加到一个他没有权限的对象上。当然我可以在post方法中检查这个特定的情况,但我觉得它不是正确的地方。我宁愿说这些检查的正确位置在序列化器的某个地方。

我错过了什么吗?任何人都可以分享一些关于如何正确管理的经验吗?

0 个答案:

没有答案