尝试使用AWS Amplify尝试GraphQL

接下来,我将继续使用AWS Amplify来部署React应用,并进行修正以创建一个ToDo应用程序。
基于官方教程,我将实现根据用户切换显示内容的功能。

后端实现

我們將配置Amplify的後端。

在管理用户界面中无法进行设置。

image.png

用Amplify CLI创建API。

所以,我打算放弃并利用Amplify CLI来实现GraphQL的API。
我们将使用上述的GraphQL API页面中提到的amplify add api命令来创建API。
我已经使用默认值回答了所有的问题。

amplify add api

? Please select from one of the below mentioned services: GraphQL
? Provide API name: amplifyreact
? Choose the default authorization type for the API API key
? Enter a description for the API key:
? After how many days from now the API key should expire (1-365): 7
? Do you want to configure advanced settings for the GraphQL API No, I am done.
? Do you have an annotated GraphQL schema? No
? Choose a schema template: Single object with fields (e.g., “Todo” with ID, name, description)

当API准备完成后,将询问您如下问题,请选择“Yes”作答。
(默认为“No”,即使选择“No”,只需打开amplify/backend/api/***/schema.graphql即可。)

? Do you want to edit the schema now? Yes

默认情况下,已定义了一个名为Todo的模式。 带有叹号的字段表示它们永远不会为null。 这次我们将直接使用它。

type Todo @model {
  id: ID!
  name: String!
  description: String
}

后面我会提到,由于这个@model指令的存在,DynamoDB的设置将会自动完成。

API的部署

在这种状态下,使用amplify push命令进行API的部署。

amplify push --y
image.png

前端的实施

我会将App.js按照下面的方式进行修改。

import React, { useState, useEffect } from 'react';
import './App.css';
import { API } from 'aws-amplify';
import { withAuthenticator, AmplifySignOut } from '@aws-amplify/ui-react';
import { listTodos } from './graphql/queries';
import { createTodo as createTodoMutation, deleteTodo as deleteTodoMutation } from './graphql/mutations';

const initialFormState = { name: '', description: '' }

function App() {
  const [todos, setTodos] = useState([]);
  const [formData, setFormData] = useState(initialFormState);

  useEffect(() => {
    fetchTodos();
  }, []);

  async function fetchTodos() {
    const apiData = await API.graphql({ query: listTodos });
    setTodos(apiData.data.listTodos.items);
  }

  async function createTodo() {
    if (!formData.name || !formData.description) return;
    await API.graphql({ query: createTodoMutation, variables: { input: formData } });
    setTodos([ ...todos, formData ]);
    setFormData(initialFormState);
  }

  async function deleteTodo({ id }) {
    const newTodosArray = todos.filter(todo => todo.id !== id);
    setTodos(newTodosArray);
    await API.graphql({ query: deleteTodoMutation, variables: { input: { id } }});
  }

  return (
    <div className="App">
      <h1>My Todos App</h1>
      <input
        onChange={e => setFormData({ ...formData, 'name': e.target.value})}
        placeholder="Todo name"
        value={formData.name}
      />
      <input
        onChange={e => setFormData({ ...formData, 'description': e.target.value})}
        placeholder="Todo description"
        value={formData.description}
      />
      <button onClick={createTodo}>Create Todo</button>
      <div style={{marginBottom: 30}}>
        {
          todos.map(todo => (
            <div key={todo.id || todo.name}>
              <h2>{todo.name}</h2>
              <p>{todo.description}</p>
              <button onClick={() => deleteTodo(todo)}>Delete Todo</button>
            </div>
          ))
        }
      </div>
      <AmplifySignOut />
    </div>
  );
}

export default withAuthenticator(App);
image.png

但是,只有当多个用户尝试登录时才会发现,尽管已经有了登录功能,但显示的内容却在所有用户之间保持一致。
基于上述应用程序,我希望能够根据每个用户将待办事项列表的内容分开。

按照每个用户将待办事项列表的内容分开。

在通常的ToDo应用中,应该显示签署用户的ToDo列表,并且只有签署的用户才能操作其内容。
实际上,要实现这一点通常需要进行授权功能的implement,可能会相当麻烦,但是在Amplify中,您可以轻松地实现它。

@auth指令

在GraphQL的模式中使用@auth指令,可以实现授权功能。

关于@auth,有官方文档可供查阅。
https://docs.amplify.aws/cli/graphql-transformer/auth

以下是对schema.graphql进行修改的方式。

- type Todo @model {
+ type Todo @model @auth(rules: [{ allow: owner }]){
  id: ID!
  name: String!
  description: String
}

image.png

看起来需要将验证方法设置为Cognito,可以通过amplify update api修改设置。

amplify update api

? Select from the options below Update auth settings
? Choose the default authorization type for the API Amazon Cognito User Pool
Use a Cognito user pool configured as a part of this project.
? Configure additional auth types? No
(node:14112) ExperimentalWarning: The fs.promises API is experimental
image.png
image.png

让我们来看一下DynamoDB中的数据。

查看添加到 DynamoDB 中的数据,除了在 schema.graphql 中所记录的内容之外,还添加了一个名为 owner 的项。

image.png

拥有者授权指定用户是否可以访问或操作对象。为此,每个对象将获取ownerField字段(如果未指定,默认情况下将添加拥有者),该字段存储所有权信息,并在解析器执行过程中通过多种方式进行验证。

image.png
广告
将在 10 秒后关闭
bannerAds