我想知道对象级权限的正确位置。我正在使用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方法中检查这个特定的情况,但我觉得它不是正确的地方。我宁愿说这些检查的正确位置在序列化器的某个地方。
我错过了什么吗?任何人都可以分享一些关于如何正确管理的经验吗?