如何根据Graphene / Django上的用户类型限制模型上的字段访问?

时间:2018-03-03 12:53:48

标签: 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)

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

然后我想限制薪水的写/更新给不同类型的用户。

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

修改

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

2 个答案:

答案 0 :(得分:9)

QUERIES

假设你有

1)定义为

的查询
employees = graphene.List(EmployeeType)

2)查询的解析器,如

def resolve_employees(self, info, **kwargs):
    return Employee.objects.all()

3)对您的员工模型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_namelast_name创建任何其他解析器。

重要提示: graphene-python中没有标准的Decimal类型,所以你有一个我在这里忽略的不同问题。)


<小时/>

突变

Read the documentation first.但是没有做更新的示例。

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

1)创建一种方法,在Mutation方法

中设置员工
class MyMutations(graphene.ObjectType):
     set_employee = SetEmployee.Field()

2)为SetEmployee创建一个获取Employee对象并更新它的方法。某些用户会忽略薪水字段。请再次注意,我通过将字符串作为输入来忽略Decimal问题。

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)

答案 1 :(得分:2)

很棒的回应@MarkChackerian。但就个人而言,我认为在未经授权的访问中为字段返回空值可能不明确,因此我个人提出了类似于解决方法的异常:

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!')