Amplifyで自動生成されたAppsyncリゾルバー(VTL)をカスタマイズする
こんにちは @kita3222 です👋
本記事は AWS AmplifyとAWS×フロントエンド Advent Calendar 2022、24日目の記事です。
はじめに
Amplifyはschema.graphql
の定義に基づいて、@model ディレクティブをつけたtypeについては全てリゾルバーを自動生成します。取得するデータをユーザーごとにフィルタリングする処理をバックエンド側で実施したい場合には、VTLをカスタマイズすることで実現できます。
今回は、こちらの記事でご紹介したLambda認証と組み合わせた場合の実装についてお話ししていきます。
Amplifyで生成されたリゾルバーを上書きする
Amplifyによって自動生成されたVTLはamplify/backend/api/<api-name>/build/resolvers
に定義されています。
この自動生成されたファイルの内容を上書きしていきます。今回は、先程作成したTodoモデルのレスポンスのVTLファイルを上書きしようと思います。
上書きしたいVTLファイルをコピペ
amplify/backend/api/<api-name>/build/resolvers
にあるQuery.listTodos.res.vtl
ファイルをコピーし、<project-dir>/amplify/backend/api/<api-name>/resolvers/
にペーストする。
VTLファイルを編集
VTLファイルを編集していきます。
VTLのプログラミングガイドに則って、listTodos
クエリーを実行した際に、ownerフィールドと認証用Lambdaから渡されたアカウントIDが一致するレコードにフィルタリングされるよう以下のように修正します。
## [Start] ResponseTemplate. **
- #if( $ctx.error )
- $util.error($ctx.error.message, $ctx.error.type)
- #else
- $util.toJson($ctx.result)
- #end
+ #set( $items = [] )
+ #foreach( $item in $ctx.result.items)
+ #if ($item["owner"] == $ctx.identity.resolverContext["accountID"])
+ $util.qr($items.add($item))
+ #end
+ #end
+ #set( $ctx.result.items = $items )
+ #if( $ctx.error )
+ $util.error($ctx.error.message, $ctx.error.type)
+ #else
+ $util.toJson($ctx.result)
+ #end
## [End] ResponseTemplate. **
認証用Lambdaのレスポンスを修正する
レスポンスの中にresolverContext
を追加し、リゾルバーに渡すアカウントIDを定義する。
export const handler = async (event) => {
const { authorizationToken } = event;
// authorizationTokenを使って認証を行う
// 外部認証システムで作成されたアカウントIDなど、アカウントごとに一意に発行される値を使用
const getMyAccountId = () => 'myAccountId';
const myAccountId = getMyAccountId();
// 認証に成功した場合は isAuthorized をtrueで返す
if (isAuthorized) {
// リゾルバーに渡すaccountIDを定義する
return {
isAuthorized: true,
ttlOverride: 300,
+ resolverContext: {
+ accountID: myAccountId
+ }
};
// 認証に失敗した場合は isAuthorized をfalseで返す
} else {
return {
isAuthorized: false,
ttlOverride: 0,
};
}
};
amplify push
を実行してデプロイします。
動作確認
DynamoDBのTodoテーブルに以下3つのレコードを用意しました。
idが3のレコードのみ、ownerが異なります。
id | name | owner |
---|---|---|
1 | test1 | 1234567890 |
2 | test2 | 1234567890 |
3 | test3 | 9999999999 |
そして、accountIDが123456789のユーザーがクエリーを実行すると以下のようになりました。
アカウントIDに一致するデータだけ取得するようフィルタリングされていました。
最後に
AmplifyでAppsyncのリゾルバ(VTL)のカスタマイズを行う方法をご紹介させていただきました。Amplifyでどうやるのかはわかっておりませんが、JavascriptでVTLを書く方法も最近だと出てきているようなのでそちらも今後は試していきたいと思います。
参考
Discussion