我对这个问题进行了一些研究,虽然还远未完成,但我想分享一下。
- 尽管amplify docs 说,有可能组合多种自动化类型,但他们没有明确指定,你不能将它们组合在一个请求中(我是,这对他们来说很明显,但对于新手来说却不是我)。
- 当您使用
amplify update api 配置 AppSync GraphQL API 时,您选择默认授权类型。 await API.graphql() 从您前面发出的所有后续请求都将使用此默认值,除非您明确指定像 await API.graphql(Object.assign(graphqlOperation(listTodos),{authMode: auth_mode})) 这样的不同类型,其中 auth_mode 可以采用以下值之一:"API_KEY", "AWS_IAM", "AMAZON_COGNITO_USER_POOLS" 和 "OPENID_CONNECT"。
- 在 Amplify 中有两种“真正的”公共授权类型 -
"API_KEY" 和 "AWS_IAM"。要激活其中任何一个(或两者),您应该执行以下操作:
type Todo @model
@auth(rules: [
{ allow: public },
{ allow: public, provider: iam},
])
{
id: ID!
name: String!
description: String
owner: String
editors: [String]
entity: String
}
-
{ allow: public } 代表"API_KEY",{ allow: public, provider: iam} - 代表"AWS_IAM"。
- 要让
"API_KEY" 正常工作,您应该配置 API KEY(例如 - 与 amplify update api)。对于"AWS_IAM",您应该配置 Cognito 并在 Cognito 身份池中启用未经身份验证的身份。
- 此后,任何没有事先用户登录的表单
await API.graphql(Object.assign(graphqlOperation(listTodos),{authMode: auth_mode})) 和auth_mode=API_KEY 或auth_mode=AWS_IAM 的请求都将成功(还有updateTodo、createTodo 和deleteTodo)。
- 在任何一种情况下,您都无法使用由用户启用的“开箱即用”的公共字段来实施您的工作流程,因为权限评估在在任何数据库信息可用之前完成。例如,IAM 授权使用由
amplify update api 为您生成的未经身份验证的角色策略。您可以在 IAM 服务的 AWS 控制台中看到它。
- 为了部分实现您的私有/公共工作流程,我建议使用所谓的动态组授权(我们假设“AMAZON_COGNITO_USER_POOLS”身份验证模式)。在这种情况下,您在 Cognito 用户池中实现“公共”组,并使任何用户成为该组的成员(您可以使用 post signUp hooks 自动执行此操作)。
- 你的@auth 可能是这样的
type Todo @model
@auth(rules: [
{ allow: owner },
{ allow: groups, groupsField: "groupsCanAccess", operations: [read] },
])
{
id: ID!
name: String!
description: String
owner: String
editors: [String]
entity: String
groupsCanAccess: [String]
}
- 当您的用户决定是时候公开了,她请求 updateTodo 并将
groupsCanAccess 设置为 public。如您所见,这是部分解决方案,因为要阅读待办事项,您的“公共”用户应该已注册。
- 为了部分实施您的员工组织工作流程,我可以建议下一个方法(我们再次假设“AMAZON_COGNITO_USER_POOLS”):
type User @model
@auth( rules: [
{ allow: owner },
{ allow: groups, groupsField: "groupsCanAccess", operations: [read] },
{allow: groups, groups: ["Admin"] }
]) {
id: ID!
owner: String! @auth(rules[{allow: groups, groups: ["Admin"] }])
groupsCanAccess:[String]
@auth(rules[{allow: owner},{allow: groups, groups: ["Admin"] }])
todo: [Todo] @connection(keyName: "byUser", fields: ["owner"])
type Todo @model
(queries: null)
@auth ({allow: owner, operations[delete]})
@key [(name: "byUser", fields: ["owner", "description"])
{
id: ID!
name: String!
description: String
owner: String! @auth(rules[{allow: owner}])
}
-
这里每个人都可以创建,更新和读取Todo,但是读取操作只能通过User(查询:null)进行,所以除了所有者之外没有人可以获取特定的id来更新特定的Todo。尽管有人可以猜到这个 id 的可能性很小,但这是这种方法的缺点。没有所有者(字段上的感叹号)就不可能创建 Todo,除了所有者之外没有人可以创建 Todo(除了所有者之外没有人可以更改所有者字段)。请注意,操作[delete] 很重要,因为没有它,任何人都无法通过用户查询 Todo({allow: owner} 相当于 {allow: owner, operations[create,update,read,delete]})。
-
所有者可以对用户执行任何操作,但她无法创建或删除用户,因为她无法更改受 perfield @auth 指令保护的所有者字段
-
管理员可以创建用户并将所有者设置为特定用户。
-
管理员和所有者可以更改 groupsCanAccess 字段。该数组中的每个元素都对应于某个组织。当管理员或所有者添加某个组织时,该组的每个成员都可以通过该用户访问该用户以及她的所有待办事项。缺点 - 所有者可以禁止管理员授予的访问权限。因为 Todos 不受更新保护 - 每个组成员都可以更改特定用户的 Todos。
-
将 Cognito 用户池用户添加到组的操作由管理员执行,超出了本文档的范围。缺点 - 每个 Cognito 池只有 300 个组。
-
最后 - 您当然可以选择手动调整 Amplify 自动生成的解析器。您可以使用“AWS_IAM”并通过分析您的 rezolver 映射模板中的 $context.identity.cognitoIdentityId 来组织所有者检查。如您所知 - 此 Cognito 身份池参数与用户池中的用户之间存在一对一的对应关系。当您需要存储公共和所有者的 Todos 时尤其方便(每个身份池 cognitoIdentityId 对应于未经身份验证的用户有一些唯一的)。