16

假设我有一个模型:

class Employee(models.Model):
    first_name = models.CharField(max_length=40)
    last_name = models.CharField(max_length=60)
    salary = models.DecimalField(decimal_places=2)

我希望任何人都能够访问 first_name 和 last_name 但只希望某些用户能够读取薪水,因为这是机密数据。

然后我想将薪水的写入/更新限制为甚至不同类型的用户。

如何根据请求用户限制字​​段读/写/更新?

编辑:

这是在 GraphQL API 上下文中。我正在使用石墨烯。我希望在解析器功能中看到可扩展的解决方案。

4

2 回答 2

20

查询

假设你有

  1. 定义如下的查询
    employees = graphene.List(EmployeeType)
  1. 查询的解析器,例如
    def resolve_employees(self, info, **kwargs):
        return Employee.objects.all()

  1. 您的 Employee 模型的权限称为can_view_salarycan_edit_salary

然后你需要定义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_name和创建任何其他解析器last_name




突变

首先阅读文档。 但是没有进行更新的示例。

简而言之,您可以采用以下方法:

  1. 创建一个方法以在您的Mutation方法中设置员工
class MyMutations(graphene.ObjectType):
     set_employee = SetEmployee.Field()
  1. 创建一个SetEmployee获取 Employee 对象并更新它的方法。对于某些用户,薪水字段会被忽略。
class SetEmployee(graphene.Mutation):
    
    class Arguments:
        id = graphene.ID()
        first_name = graphene.String()
        last_name = graphene.String()
        salary = graphene.String()
    
    employee = graphene.Field(lambda: EmployeeType)
    
    
    @classmethod
    def mutate(cls, root, info, **args):
        employee_id = args.get('employee_id')
        
        # Fetch the employee object by id
        employee = Employee.objects.get(id=employee_id)
        first_name = args.get('first_name')
        last_name = args.get('last_name')
        salary = args.get('salary')
        
        # Update the employee fields from the mutation inputs
        if first_name:
            employee.first_name = first_name
        if last_name:
            employee.last_name = last_name
        if salary and info.context.user.has_perm('myapp.can_edit_salary'):
            employee.salary = salary
        employee.save()
        return SetEmployee(employee=employee)

注意:最初编写此答案时,Graphene Django 中没有可用的 Decimal 字段——我通过将字符串作为输入来避免这个问题。

于 2018-03-14T16:33:24.643 回答
3

很好的回应@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!')
于 2018-04-23T13:56:15.907 回答