Nic*_*cky 6 access-control node.js role-based-access-control graphql graphql-js
上下文
我有一个 GraphQL API 和一个 NodeJS & Angular 应用程序,其中包含一个包含用户的 MongoDB 数据库。对于每个用户,都有一个包含公共信息的公共页面,例如id
和username
。当用户登录时,会有一个包含扩展信息的私人资料页面,例如email
.
仅就上下文而言,我使用jsonwebtoken和accesscontrol来对用户进行身份验证和授权。该信息存储在每个 GraphQL 解析函数的上下文中,因此可以使用识别登录用户所需的任何信息。
我有一个 GraphQL 查询,它检索公共用户,如下所示:
query getUserById($id: ID!) {
getUserById(id: $id) {
id,
username
}
}
Run Code Online (Sandbox Code Playgroud)
我正在尝试考虑检索公共用户或私人用户的正确实现。由于 GraphQL 是强类型的,我在想出合适的解决方案时遇到了一些麻烦。
问题
如何区分公共用户和私人用户?
注意事项
1. 单独查询
因此,选项之一是对公共和私有字段进行单独查询:
公开查询
query getUserById($id: ID!) {
getUserById(id: $id) {
id,
username
}
}
Run Code Online (Sandbox Code Playgroud)
私人查询
query getMe {
getMe {
id,
username,
email
}
}
Run Code Online (Sandbox Code Playgroud)
2. 使用 GraphQL 接口
我看到了这篇 Medium 文章,它解释了如何使用 GraphQL 接口根据resolveType
函数返回不同的类型。所以我会这样做:
query getUser($id: ID!) {
getUser(id: $id) {
... on UserPrivate {
id,
username
}
... on UserPublic {
id,
username,
email
}
}
}
Run Code Online (Sandbox Code Playgroud)
我还没有遇到合适的解决方案,我不确定到目前为止我所考虑的任何一个。
任何帮助深表感谢!
我认为您在这里缺少的是在 GraphQL 中您通常想要创建这种深度连接的图结构。虽然getUserById
和getMe
作为入口点工作得很好(我认为即使使用接口类型它们仍然是一个好主意),您很可能会在您的架构中出现用户类型。想象一下流行的博客文章示例:
type Post {
id: ID!
title: String!
content: String!
author: User!
}
Run Code Online (Sandbox Code Playgroud)
在这里添加两个作者字段并不能很好地工作。同样,在您的示例中,您可能不知道个人资料页面是您自己的,直到您收到后端的响应(想想推特个人资料)。
相反,我认为有两种方法可以考虑:
第一个是界面理念。您将拥有一个接口,其中包含私有和公共类型的所有公共字段和具体实现。这里的好处是:如果您只使用公共字段,您甚至不必使用类型匹配:
query getUser($id: ID!) {
getUser(id: $id) {
id
username
# if you need a private field you can branch off here
... on UserPrivate {
email
}
}
}
Run Code Online (Sandbox Code Playgroud)
当它变得更细粒度(人们分享他们想要向公众公开的内容,想象一下 Facebook)或者您有很多类型(UserMe、UserFriend、UserStranger)时,您可能需要考虑可空字段。如果您无权访问该字段,您将收到来自 API 的 null。为了减少空检查的数量,您可以轻松地将字段捆绑到它们自己的类型中(例如Address
)。
概括:
从 API 的角度来看,返回可空字段要容易一些,因为它为您提供了很大的灵活性。与第一个选项相比,在不破坏更改的情况下演化第二个选项要容易得多。如果您使用静态类型(Typescript、Flow、Scala.js、Reason 等),那么在前端使用接口会更具表现力,而且肯定会更有趣。关键字:模式匹配。
归档时间: |
|
查看次数: |
2635 次 |
最近记录: |