Timeline機能: Back-end

フォロー機能が実装できたので、次はユーザー固有のタイムラインをハンドリングするGraphQL APIを実装していきましょう。

Timeline APIの作成

Timelineテーブルを作成し、特定のユーザーがフォローしているユーザーのポストにアクセスできるようにしましょう。 ./amplify/backend/api/BoyakiGql/schema.graphqlに次のコードを追加します。

type Timeline 
	@model(
    mutations: {create: "createTimeline", delete: null, update: null}
    timestamps: null
  )
	@auth(rules: [
    {allow: owner, ownerField: "userId", provider: userPools, operations:[read, create]},
    {allow: private, provider: iam ,operations:[create]},
	])
	@key(fields: ["userId", "timestamp"])
{
	userId: ID!
	timestamp: Int!
	postId: ID!
	post: Post @connection(fields: ["postId"])
}

ポイントを見ていきましょう。

  • @model
    • mutations:...では必要のないudpate、delete用APIを作らない設定をします
    • timestamps:...では、デフォルトで自動的に付与されるupdatedAt``createdAtの属性を作らない設定をします。代わりにAWS Timestamp属性のtimestampを用います。
  • @auth
    • {allow: owner...では、OwnerであるユーザーのみがTimelineのQuery/Subscriptionを実行できるよう設定しています。
      • Subscriptionを行うためにはread``create、この2つの権限が必要です
    • {allow: private...では、後ほど作成するAWS Lambda関数がTimeline APIのMutationを実行できるようにIAM認証によるアクセスを許可しています
  • @key
    • あるユーザーがTimelineを閲覧するときには、userIdが自分のUsernameと一致するアイテムを時系列順でフェッチすることになります
    • userIdがPartition Key(PK)、timestampをSort Key(SK)とすることで、自身のTimelineを時系列順にフェッチすることが可能です
  • @connection
    • Timeline APIの役割は、あるユーザーのPostを、そのフォロワーのTimelineに複製することで、各ユーザー固有のTimelineを実現することでした
    • 複製する際に、まるごとPostのフィールドをTimelineのフィールドに複製することも可能ですが、例えば"いいね"や、“返信"機能を実装する際に、フィールドをアップデートすべき箇所がPostとTimelineにまたがってしまうと大変です
    • @connectionを使用することで、AWS AppSyncがQueryを処理する際に、複数のDynamoDB Tableにまたがるデータを結合してくれるようになります
    • fieldsでは、Post TableのPrimary Keyを指定しています。Timeline TableのpostIdフィールドにPostのidを格納しています。PostはidフィールドがPrimary Keyでしたので、postIdだけを渡してやれば、一意にアイテムが識別できます

GraphQL APIの認証方法にIAMを追加

Timeline APIのMutationを実行してTimelineアイテムを作成するのはAWS Lambda関数の役割です。 Lambda関数がAWS AppSyncのAPIコールを行う最も簡単な認証方法は、AWS IAMのIAM Roleを利用することです。 3.2.で$ amplify add apiによりGraphQL APIを作成した際には、Amazon Cognito User Poolsのみを認証方法として設定していました。 ここではさらにAWS IAMを認証方法として追加します。

$ amplify update apiをターミナルで実行し、次のように質問に答えていきましょう。

amplify update api
  • Please select from one of the below mentioned services: GraphQL
  • Select from the options below: Update auth settings
  • Choose the default authorization type for the API Amazon Cognito User Pool
  • Configure additional auth types? Yes
  • Choose the additional authorization types you want to configure for the API IAM

Choose the additional authorization types...の項目は複数選択式となります。 IAMまでカーソルで移動後、__スペースキー__を押すことでIAMが選択でき、Enterキーを押すことで選択が確定し次の項目に移ります。 スペースキーで選択ができていることを確認してください。

このように、Amplifyでは一度作成したリソースを変更するために$ amplify udpateコマンドを利用することができます。ただし、AuthカテゴリでプロビジョニングするAmazon CognitoのIDとしてどのフィールドを指定するか?といった設定など、一部後から変更できないものがあることに注意してください。

Amplify Mockingによる動作確認

$ amplify mock apiを実行して、Timeline APIが期待通り動くかを確認しましょう。

Amplify Mocking(手元での動作確認)には20002番ポートが利用可能である必要があり、一部の Cloud IDE では利用できないことがあります。 該当するCloud IDEをご利用の方は本手順は実施せず、雰囲気を味わっていただけますと幸いです。

amplify mock api

すでにAmplify GraphQL Explorerをブラウザで開かれている方は、変更を読み込むためページの更新をお願いします。

createTimeline

まずはTimelineアイテムを作成してみます。

  1. 左のペインにあるlistPostsをクリックし、items直下にあるidownertimestampにチェックをつけます
  2. ▶︎をクリックしてGraphQLのQueryを実行すると、右側のペインにPost一覧が表示されるので、うち一つのidtimestampをメモしておきます。(Postが一つも存在しない場合は、3.2.の手順に従いPostを新規に作成します)
  3. 左下のADD NEW Queryと書いてある場所をクリックし、Mutationを選択したのち+をクリックします
  4. 左のペインにあるcreateTimelineをクリックし、次図のようにチェックボックスやフィールド埋めてみましょう
  5. このとき、先ほどメモしたPostのidtimestampを使用します
  6. userIdtest_followerにしておきます
  7. createTimelineを実行できるのはIAM認証のユーザーのみです。画面上部のUse: User Poolをクリックし、Use: IAMに変更しましょう
  8. ▶︎をクリックしてGraphQLのMutationを実行します

listTimelines

次に作成したTimelineアイテムのリストを表示してみます。

  1. 左のペインにあるlistTimelinesをクリックし、次図のようにチェックボックスやフィールド埋めてみましょう
  2. listTimelinesを実行できるのはCognito User Pools認証された、TimelineuserIdフィールドと同じUsernameをもつユーザーのみです
  3. 画面上部のUpdate Authをクリックし、Cognito User Poolに変更します
  4. さらにUsernametest_followerにかえGenerate Tokenをクリックします
  5. ▶︎をクリックしてGraphQLのQueryを実行します
  6. 右側のペインに結果が表示されます。先ほど作成したTimelineが表示されていることを確認してください
  7. @connectionにより、postIdに紐づくPostがpostフィールドに展開されています

作成したTimelineが表示されない場合、Update Authを押してUsernameを確認し、listTimelinesuserId引数に渡している値と一致しているか確認してください。TimelineはOwnerにしかreadが許されていないため、他のユーザーのクレデンシャルでQueryを発行しても取得ができません。