设置石墨烯中继节点和连接字段的权限

Posted

技术标签:

【中文标题】设置石墨烯中继节点和连接字段的权限【英文标题】:Set permissions on Graphene Relay Node and Connection fields 【发布时间】:2021-11-06 14:03:51 【问题描述】:

我如何要求对下面的tier 节点字段和allTiers 连接字段查询进行身份验证/授权?

# schema.py
class TierNode(DjangoObjectType):
    class Meta:
        model = Tier
        filter_fields = []
        interfaces = (graphene.relay.Node,)


class Query(graphene.ObjectType):
    tier = relay.Node.Field(TierNode)
    all_tiers = DjangoFilterConnectionField(TierNode)

【问题讨论】:

【参考方案1】:

您可以使用 auth 装饰器为这些字段定义解析器,如下所示:

from graphql_jwt.decorators import login_required

class Query(graphene.ObjectType):
    tier = relay.Node.Field(TierNode)
    all_tiers = DjangoFilterConnectionField(TierNode)


    @login_required
    def resolve_tier(root, info, **kwargs):
        # code for resolving here

这只是使用graphql_jwt 附带的login_decorator,但如果您定义它们,它也适用于您的自定义装饰器。

此外,这也适用于解析 TierNode 的字段时:

class TierNode(DjangoObjectType):
    class Meta:
        model = Tier
        filter_fields = []
        interfaces = (graphene.relay.Node,)

    some_property = graphene.Field("types.SomePropertyType")

    @login_required
    def resolve_some_property(root, info, **kwargs):
        # code for resolving here

【讨论】:

谢谢@jech-chua。定义解析器似乎适用于除 Node 和 Connection 字段之外的所有内容。也许这是一个石墨烯错误? 你遇到过什么问题?这就是我们在当前项目中保护端点/字段的方式。【参考方案2】:

您可以像这样定义授权或/和身份验证装饰器:

from functools import wraps

def authorize_required(role):
    def decorator(func):
        @wraps(func)
        def wrapper(instance, info, *args, **kwargs):
            current_user = info.context.user
            if not current_user.is_authenticated:
                raise Exception("Authentication credentials were not provided")
            if not authorize(instance, current_user, role):
                raise Exception(
                    f"current_user has no access to instance with required role="
                )
            return func(instance, info, *args, **kwargs)
        return wrapper
    return decorator

def authorize(instance, user, role) -> bool:
   # check if user can have access to instance
   # if there is requirement to have certain role

并在模式定义中使用它:

class TierNode(DjangoObjectType):
    class Meta:
        model = Tier
        filter_fields = []
        interfaces = (graphene.relay.Node,)


class Query(graphene.ObjectType):
    tier = relay.Node.Field(TierNode)
    all_tiers = DjangoFilterConnectionField(TierNode)
  
    @authorize_required('user')
    def resolve_tier(self, info, **args):
        # some resolve code

    @authorize_required('admin')
    def resolve_all_tiers(self, info, **args):
        # some resolve code

【讨论】:

以上是关于设置石墨烯中继节点和连接字段的权限的主要内容,如果未能解决你的问题,请参考以下文章

如何解决具有多对多关系的石墨烯 django 节点字段

使用石墨烯和 SQLalchemy 为 GraphQL 设置权限很热门

为中继自动生成 graphql 模式(石墨烯服务器)

在石墨烯中使用与多个解析器相同的连接

在没有中继的情况下使用带有graphene-django的子字段中的参数进行分页

石墨烯突变返回 400 - 不会正确传递 id 字段