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

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

问题描述

背景
我有一个 GraphQL API 和一个 NodeJS &带有保存用户的 MongoDB 数据库的 Angular 应用程序.对于每个用户,都有一个公共页面,其中包含诸如 idusername 之类的公共信息.当用户登录时,会出现一个带有扩展信息的私人资料页面,例如 email.

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.

只是为了上下文,我使用 jsonwebtokenaccesscontrol 对用户进行身份验证和授权.该信息存储在每个 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:

公开查询

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

私人查询

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

2.使用 GraphQL 接口
我遇到了 这篇 Medium 文章,它解释了 GraphQL Interfaces用于根据 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 中你通常想要创建这种深度连接的图结构.虽然 getUserByIdgetMe 作为入口点工作得很好(我认为即使使用界面类型它们仍然是一个好主意),你很可能会出现所有用户类型在你的架构上.想象一下流行的博客文章示例:

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!
}

在这里添加两个作者字段并不能很好地工作.同样,在您的示例中,您可能不知道个人资料页面是您自己的,直到您收到后端的回复(想想推特个人资料).

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天全站免登陆