Python 如何根据Graphene/Django上的用户类型限制模型上的字段访问?
假设我有一个模型:Python 如何根据Graphene/Django上的用户类型限制模型上的字段访问?,python,django,graphene-python,Python,Django,Graphene Python,假设我有一个模型: class Employee(models.Model): first_name = models.CharField(max_length=40) last_name = models.CharField(max_length=60) salary = models.DecimalField(decimal_places=2) 我希望任何人都能够访问名字和姓氏,但只希望某些用户能够读取工资,因为这是机密数据 然后我想限制写/更新工资给一个甚至不同类
class Employee(models.Model):
first_name = models.CharField(max_length=40)
last_name = models.CharField(max_length=60)
salary = models.DecimalField(decimal_places=2)
我希望任何人都能够访问名字和姓氏,但只希望某些用户能够读取工资,因为这是机密数据
然后我想限制写/更新工资给一个甚至不同类型的用户
如何根据请求用户限制字段读/写/更新
编辑:
这在GraphQLAPI上下文中。我用的是石墨烯。我想在解析器函数中看到一个可伸缩的解决方案 询问
假设你有
可以查看工资和可以编辑工资
EmployeeType
,其值为salary
,具体取决于用户。差不多
from graphene_django.types import DjangoObjectType
from myapp.models import Employee
class EmployeeType(DjangoObjectType):
class Meta:
model = Employee
def resolve_salary(self, info):
if info.context.user.has_perm('myapp.can_view_salary'):
return self.salary
return None
重要的一点是,您正在为基于权限值切换的薪资创建一个自定义的resolve
函数。您不需要为first\u name
和last\u name
创建任何其他解析程序
突变 但是没有一个更新的例子 简而言之,以下是您可以采取的方法:
方法中设置员工
类别MyTranslations(graphene.ObjectType):
set_employee=SetEmployee.Field()
SetEmployee
创建一个方法,该方法获取并更新Employee对象。对于某些用户,薪资字段被忽略。再次注意,我将字符串作为输入,从而忽略了十进制问题
类别SetEmployee(石墨烯突变):
伟大的回应@MarkChackerian。然而,就我个人而言,我认为在未经授权的访问中为字段返回null值可能是不明确的,因此我个人从resolve方法中提出了一个异常,如下所示:
class UnauthorisedAccessError(GraphQLError):
def __init__(self, message, *args, **kwargs):
super(UnauthorisedAccessError, self).__init__(message, *args, **kwargs)
def resolve_salary(self, info):
if info.context.user.has_perm('myapp.can_view_salary'):
return self.salary
raise UnauthorisedAccessError(message='No permissions to see the salary!')
最好也是最简单的建议是,您需要创建一个组,然后添加自定义权限,并将特定成员包括到该组中。我想了解您如何访问来自reducer的请求,如何在带有未授权字段的查询中发送错误,以及如何在reducer中处理身份验证。问题更多的是认证的GraphQL集成,而不是Django端。当你说“reducer”时,你是指React/Redux意义上的“reducer”,还是指“resolver”?是的,是resolver,我的错。这个问题有两个部分,因为graphenepython实现需要单独的读(即查询)和写(即突变)功能,这取决于用例。如果用户正在编写自己的查询,那么最好引发一个异常,如您所示。但是,我认为更常见的用例是graphQL查询嵌入到javascript中,在这种情况下,使用一个graphQL查询来处理两类用户(具有访问权限的用户和没有访问权限的用户)更为实际。如果你提出一个例外,你不能有一个单一的查询同时适用于这两种用户。这似乎违反了我的直觉。通过定义像上面的
resolve\u salary()
这样的函数,我们实际上是在创建一个不允许用户查看的字段黑名单。将来在Employee
模型中添加一个新的特权字段,开发人员不可避免地忘记创建resolve\u newfield()
函数来限制其访问时,这可能会很麻烦。因此,忘记定义函数会造成安全漏洞。-有没有一种方法可以阻止所有字段,除非我们显式允许它(而不是显式阻止它)?@PKKid似乎有一些方法可以在源代码中显式限制字段,但据我所知,它们没有文档记录,并且它们不允许基于条件的访问谢谢。它没有正式的文档记录,但是bugs中的这个讨论讨论讨论了在查询中引用的唯一的_字段。光是讨论就让我对提前使用它感觉好一点。
class UnauthorisedAccessError(GraphQLError):
def __init__(self, message, *args, **kwargs):
super(UnauthorisedAccessError, self).__init__(message, *args, **kwargs)
def resolve_salary(self, info):
if info.context.user.has_perm('myapp.can_view_salary'):
return self.salary
raise UnauthorisedAccessError(message='No permissions to see the salary!')