GraphQL-如何区分公共字段和私有字段? [英] GraphQL - How to distinguish Public from Private fields?

查看:195
本文介绍了GraphQL-如何区分公共字段和私有字段?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

上下文

我有一个GraphQL API和一个NodeJS&具有可容纳用户的MongoDB数据库的Angular应用程序。对于每个用户,都有一个包含公共信息的公共页面,例如 id username 。当用户登录后,会有一个私人配置文件页面,其中包含扩展信息,例如电子邮件

Context
I have a GraphQL API and a NodeJS & Angular application with a MongoDB database that holds users. For each user, there is a public page with public information like id and username. When a user is logged in, there is a private profile page with extended information like an email.

仅用于上下文中,我将 jsonwebtoken 访问控制来对用户进行身份验证和授权。该信息存储在每个GraphQL解析函数的上下文中,因此可以使用任何用于标识已登录用户的信息。

Just for context, I'm using jsonwebtoken with accesscontrol to authenticate and authorize a user. The information is stored on the Context of every GraphQL resolve function, so whatever is needed to identify a logged in user is available.

我有一个GraphQL查询,它可以检索公共用户是这样的:

I have a GraphQL query that retrieves a public user like so:

query getUserById($id: ID!) {
  getUserById(id: $id) {
    id,
    username
  }
}

我正在尝试考虑适当的实现以检索公共或私人用户。由于GraphQL是强类型的,因此在提出适当的解决方案时遇到了一些麻烦。

I am trying to think of the proper implementation to retrieve either a public or a private user. Since GraphQL is strong typed, I'm having some trouble coming up with a proper solution.

问题

如何我应该区分公共用户还是私人用户?

Question
How do I implement the distinction between a public and a private user?

注意事项

1。单独的查询

因此,一种选择是对公共字段和私有字段进行单独的查询:

1. Separate query
So one of the options is to have a seperate query for both public and private fields:

public查询

query getUserById($id: ID!) {
  getUserById(id: $id) {
    id,
    username
  }
}

私人查询

query getMe {
  getMe {
    id,
    username,
    email
  }
}

<强> 2。使用GraphQL接口

我遇到了这篇中型文章介绍了如何使用GraphQL接口基于 resolveType 函数返回不同的类型。所以我会这样:

2. Using GraphQL Interfaces
I came across this Medium article that explains how GraphQL Interfaces are used to return different Types based on a resolveType function. So I would go something like so:

query getUser($id: ID!) {
   getUser(id: $id) {
     ... on UserPrivate {
       id,
       username
     }
     ... on UserPublic {
       id,
       username,
       email
     }
   }
}

我还没有找到合适的解决方案,所以我不确定我到目前为止所考虑的任何一个。

I have not came across a proper solution and I'm unsure about either of the consideration I have so far.

任何帮助都非常感谢!

推荐答案

我认为您在这里缺少的是在GraphQL中您通常想创建这种深度连接的图结构。虽然 getUserById getMe 可以很好地用作入口点(而且我认为即使使用接口类型,它们仍然是一个好主意),您很有可能会在整个架构中出现用户类型。想象一下流行的博客文章示例:

I think what you are missing here is that in GraphQL you usually want to create this deeply connected graph structure. While getUserByIdand getMe work well as entry points (and I think they are still a great idea even with the interface type), you will most likely have user types coming up all over you schema. Imagine the popular blog post example:

type Post {
  id: ID!
  title: String!
  content: String!
  author: User!
}

在此处添加两个作者字段并不能很好地工作。同样,在您的示例中,您可能不知道配置文件页面是您自己的,除非您从后端得到响应(想想Twitter的配置文件)。

Adding two author fields here does not really work very well. Similarly in your example you might not know that the profile page is your own until you get a response from the backend (think about twitter profiles).

相反,我认为有两种方法可以考虑:

第一个是接口概念。您将拥有一个包含所有公共字段和私有和公共类型的具体实现的接口。这里的好处是:如果仅使用公共字段,则甚至不必使用类型匹配:

First one is the interface idea. You would have an interface that has all the common fields and concrete implementations for the private and public type. The nice thing here: If you only use the common fields you don't even have to use the type matching:

query getUser($id: ID!) {
   getUser(id: $id) {
     id
     username

     # if you need a private field you can branch off here
     ... on UserPrivate {
       email
     }
   }
}

当它变得更精细(人们共享他们想要向公众公开的内容,想象Facebook)或您有很多类型(UserMe,UserFriend,UserStranger)时,您可能希望将其视为可空值字段代替。如果您无权访问该字段,那么您将从API收到null。为了减少空检查的数量,您可以轻松地将字段捆绑为它们自己的类型(例如 Address )。

When it gets more finely grained (people share what they want to expose to the public, imagine Facebook) or you have a lot of types (UserMe, UserFriend, UserStranger) you might want to consider nullable fields instead. If you don't have access to the field you will receive null from the API. To reduce the amount of null checking you can easily bundle fields into their own types (e.g. Address).

摘要:

从API角度来看,返回可为空的字段要容易一些,因为它为您提供了很大的灵活性。与第一个相比,在不破坏更改的情况下发展第二个选项要容易得多。如果您使用静态类型(Typescript,Flow,Scala.js,Reason等),那么使用接口将更具表现力,并且在前端使用它肯定会更有趣。关键字:模式匹配。

From the API point it is a bit easier to return nullable fields because it gives you a lot of flexibility. It is much easier to evolve the second option without breaking changes than the first one. Using interfaces is more expressive and surely more fun to work with in the frontend if you work with static types (Typescript, Flow, Scala.js, Reason, etc.). Keyword: Pattern matching.

这篇关于GraphQL-如何区分公共字段和私有字段?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆