前回はDynamoDBとAppSyncを作成しました。
今回は作成したAppSyncからアカウント情報を取得する処理をNext.jsに実装していきます。
前回の記事はこちらを参照してください。
AppSyncとNext.jsを接続する
作成したAppSyncとNext.jsを接続するにあたり、エンドポイントとAPIキーを確認します。
添付画像からコピーをすれば設定ファイルごと取得できます。
記載の情報をソースコードのconfigファイルに設定します。src/config/aws.js
にAPI設定を追加します。後にCognitoユーザープールに切り替えますが、一旦APIキーで動作確認します。
const config = {
Auth: {
Cognito: {
userPoolClientId:
process.env.NEXT_PUBLIC_COGNITO_USER_POOLS_WEB_CLIENT_ID,
userPoolId: process.env.NEXT_PUBLIC_USER_POOLS_ID,
},
},
API: {
GraphQL: {
endpoint: process.env.NEXT_PUBLIC_GRAPHQL_ENDPOINT,
region: process.env.NEXT_PUBLIC_AWS_REGION,
defaultAuthMode: "apiKey",
apiKey: process.env.NEXT_PUBLIC_APPSYNC_API_KEY,
},
},
};
export default config;
.env.localにも設定を追加します。
# AWS
## AWS Common
NEXT_PUBLIC_AWS_REGION=ap-northeast-1
## Cognito
NEXT_PUBLIC_COGNITO_USER_POOLS_WEB_CLIENT_ID=xxx
NEXT_PUBLIC_USER_POOLS_ID=ap-northeast-1_xxx
## AppSync(user)
NEXT_PUBLIC_GRAPHQL_ENDPOINT=https://xxx.appsync-api.ap-northeast-1.amazonaws.com/graphql
NEXT_PUBLIC_APPSYNC_API_KEY=xxx-xxx
続いてスキーマ定義をダウンロードします。スキーマとはGraphQL APIの仕様を表現するものです。
詳しい内容は別で記事にしたいと思いますが、クライアントからAppSyncAPIを呼び出すにあたり、amplify codegenを使用して、Next.jsで使えるAPIエンドポイントにアクセスできるライブラリーを作ります。
なお実行するにあたりaws-amplify/cli
とaws-amplify
が必要になるため、インストールしておきます。
npm install @aws-amplify/cli
npm install aws-amplify
インストール後に青枠に記載されているコマンドをコピーして実行します。
一度実行すればライブラリは作成されますが、AWSマネジメントコンソール側でスキーマ定義を修正した場合は赤枠のコマンドを実行して都度取り込むようにしてください。
コマンドを実行すると以下ファイルが生成されるはずです。
- .graphqlconfig.yml
- schema.json
- src/graphql/mutations.js
- src/graphql/queries.js
- src/graphql/subscription.js
AppSyncスキーマ定義を修正する
前回AppSyncを作成してAPI呼び出しできるようにしましたが、Next.jsからAPI呼び出しするにあたり、もう一つ作業が必要になります。それはAppSyncからグローバルセカンダリインデックス経由で情報を取得できるようにすることです。パーティションキーはアカウントIDですが、ログイン時にCognitoから取得できるのはuser_id(sub_is)のため、user_id経由でアカウント情報テーブルから値を取得する必要があります。
そのためにAppSyncのスキーマ定義を以下のように修正して「スキーマを保存」をクリックします。
getDnmCwkAccountForUserId(user_id: String!): DnmCwkAccount
その後リゾルバーから追加したQueryを探し、「アタッチ」をクリックします。
表示された画面に、下記画像のように項目を選択して「作成」をクリックします。
次に表示される画面で、リクエストマッピングテンプレートとレスポンスマッピングテンプレートをそれぞれ下記のように記載します。
リクエストマッピングテンプレートについて、パーティションキーで取得する場合はGetItemですが、グローバルセカンダリインデックスで取得する場合は、Queryになります。また使用するインデックス名を記載します。
レスポンスマッピングテンプレートについて、Queryでは単独取得ではなく一括取得となるため、取得した値の0番目のみ返却するように設定します。user_idはユニークキーであるため複数取得される場合は存在しないからです。
// リクエストマッピングテンプレート
{
"version" : "2017-02-28",
"operation" : "Query",
"query" : {
"expression" : "user_id = :user_id",
"expressionValues" : {
":user_id" : $util.dynamodb.toDynamoDBJson($ctx.args.user_id)
}
},
"index" : "user_id-index"
}
// レスポンスマッピングテンプレート
#if($ctx.result.items.size() > 0)
$util.toJson($ctx.result.items[0])
#else
null
#end
諸々入力したら「保存」をクリックします。
動作確認します。クエリタブから作成したクエリを実行して、値が返却されるかを確認します。
ちなみにcodegenで説明したようにスキーマを修正したので、下記を実行しておきます。
npx @aws-amplify/cli codegen
AppSyncAPI呼び出し処理を実装する
設定ファイルやGraphQLライブラリの準備が終わったところでいよいよAPI呼び出し処理を実装していきます。
前回作成したログイン処理内にAPI呼び出し処理を追加し、ログインしたアカウントの名前を取得したいと思います。src/contexts/authContext.jsx
を以下のように修正します。
import {Amplify} from "aws-amplify";
import config from "@/config/aws";
import React, {useContext, useState} from "react";
import {signIn, getCurrentUser} from "aws-amplify/auth";
import message from "@/config/message";
import {generateClient} from "aws-amplify/api";
import {getDnmCwkAccountForUserId} from "@/graphql/queries";
Amplify.configure(config, {ssr: true});
const AuthContext = React.createContext(undefined);
export const useAuth = () => {
return useContext(AuthContext);
}
const AuthProvider = ({children}) => {
const [account, setAccount] = useState(undefined);
// ログイン処理
const login = async (email, password) => {
try {
await signIn({username: email, password: password,});
const {userId} = await getCurrentUser();
const client = generateClient();
const result = await client.graphql({
query: getDnmCwkAccountForUserId,
variables: {
user_id: userId,
}
});
console.log(result["data"]["getDnmCwkAccountForUserId"]);
setAccount(result["data"]["getDnmCwkAccountForUserId"]);
return {isSuccessed: true, errorMessage: undefined, urlTo: "/"};
} catch (error) {
return {isSuccessed: false, errorMessage: message.M1001, urlTo: undefined,};
}
}
return (
<AuthContext.Provider value={{login, account}}>
{children}
</AuthContext.Provider>
);
};
export default AuthProvider;
signIn処理に成功した後にgetCurrentUserを呼び出すことでuser_id(sub_id)を取得します。
取得したuser_idを検索条件に設定し、getDnmCwkAccountForUserIdを呼び出すことでアカウント情報を取得できます。
ログイン画面で認証処理を実施してconsole.logを確認し、DynamoDBに登録したデータが出力されていることを確認しましょう。
最後に認証情報をAPIキーからCognitoユーザープールに変更します。
設定からプライマリ認可モードを編集します。
事前に作成しておいたCognitoユーザープールを選択します。
設定ファイルからAPIキーに関する設定を削除し、認証モードをCognitoユーザープールに変更します。src/config/aws.js
const config = {
Auth: {
Cognito: {
userPoolClientId:
process.env.NEXT_PUBLIC_COGNITO_USER_POOLS_WEB_CLIENT_ID,
userPoolId: process.env.NEXT_PUBLIC_USER_POOLS_ID,
},
},
API: {
GraphQL: {
endpoint: process.env.NEXT_PUBLIC_GRAPHQL_ENDPOINT,
region: process.env.NEXT_PUBLIC_AWS_REGION,
defaultAuthMode: "userPool",
},
},
};
export default config;
.env.local
からもprocess.env.NEXT_PUBLIC_APPSYNC_API_KEY
を削除しておきます。
最後にもう一度動作確認をして、ログインできればOKです。
コードは、以下のGitHubリポジトリで確認できます。
コメント