AWS Amplify フレームワークの使い方Part10〜Storage編〜

# はじめに
AmplifyはS3を画像などのストレージとしての利用も簡単にできます。

# 設定の流れ
## amplifyにstorageを追加
いつものコマンドを叩いて、設定を開始します。

```console
$ amplify add storage
```
## サービスの選択
画像ファイルの保存に使用するため`Contetnt`を選択。

```console
? Please select from one of the below mentioned services Content (Images, audio, video, e
```
## 名前の設定
Storage管理におけるプロジェクト名とバケット名を設定。

```console
Please provide a friendly name for your resource that will be used to label this catego
ry in the project: <プロジェクト名>
? Please provide bucket name: <バケット名>
```
## 権限設定
認証ユーザーと未認証ユーザーのCRUD設定を行います。今回は認証ユーザーはCRUDがすべてでき、未認証ユーザーはreadだけできるように設定しています。

```console
? Who should have access: Auth and guest users
? What kind of access do you want for Authenticated users? create/update, read, delete
? What kind of access do you want for Guest users? read
```
## Push
さぁ、これで準備は完了です。

```console
$ amplify push
```

# 使い方
基本的な使い方はいたってシンプルなので簡単に解説していきます。
## 保存レベル
保存には3段階のレベルがあり、public・protected・privateの３パターンがあります。

- public  
全体に公開されます。
- protected  
自身とidentityIdを知っている人に公開されます。
- private  
全体には非公開で自身のみが取得できます。

## 
```javascript
import { Storage } from 'aws-amplify';
```
## Put
保存のレベルによって、Putの方法が若干変わります。返り値に、保存先のURLは含まれていません。

```javascript
// public
await Storage.put(
  'test.png', // ファイル名
  file // アップロードするファイル
)

// protected
await Storage.put('test.png', file, {
    level: 'protected', // レベルの宣言
    contentType: 'image/png' // file形式
  }
)

// private
await Storage.put('test.png', file, {
    level: 'private', // レベルの宣言
    contentType: 'image/png' // file形式
  }
)

```
## Get
基本的には以下のようになります。どこまでどのように権限が効いているのか明確に調べていません。次で解説しますが、このidentityIdが曲者でした。

```javascript
// public
const iconURL = await Storage.get('test.png')

// protected(自身のファイルにアクセス)
const iconURL = await Storage.get('test.png', { level: 'protected' })

// protected(他者のファイルにアクセス)
const iconURL = await Storage.get('test.png', {
    level: 'protected', 
    identityId: identityId // cognitoで管理されるユーザーIDに紐づく一意なID
  }
)

// private
const iconURL = await Storage.get('test.png', { level: 'private' })

```
## Remove
こちらも検証はしていませんが、基本的に以下のようになります。publicは他ユーザーがUPした画像もremoveできました。

```javascript
// public
const iconURL = await Storage. remove('test.png')

// protected
const iconURL = await Storage. remove('test.png', { level: 'protected' })

// private
const iconURL = await Storage. remove('test.png', { level: 'private' })
```
# ハマリポイント
以下はprotectedで画像ファイルを保存した場合のハマリポイントです。

## 一定時間が経つとファイルが取得できなくなる
getして取得したURLにはtokenがついており、一定時間が経つと画像ファイルを取得できなくなります。
このURLを保存しておけば、わざわざidentityIdなんて知らなくてもicon画像取得し放題だ！、と思ったもののしばらくすると取得できなくなるのでややハマりました。
これにより、identityIdと向き合うことになります。

## protectedの場合、identityIdがわからないと取得できない
identityIdは各ユーザーに振られているuserIdとは別のcognitoさんが管理しているIDです。(ソーシャルログインをしてユーザープールにデータが作成されない人や未承認ユーザーを管理するためのもの？的なイメージ)
そんなあまり身近ではないidentityIdを使わずに、簡単に取得できる方法はないか？、と各方面で議論されているようですが、現状はまだ未実装のようです。
ただ、githubのissueでだいぶ議論されているようなので、そのうちひっそりと実装されている可能性はあるので、要チェックです。

## identityIdをどうやって取得したらいいかわからない
これハマりました。全然調べても出てこないんです。見つけたら案外簡単でした。

```javascript
const currentCredentials = await Auth.currentCredentials()
const identityId = currentCredentials.identityId
```

## Restrict access by? (2021/5/26追記)

2つのグループに属しているとき、優先順位下位のグループにアクセス権限が合っても優先順位上位グループに権限がないとアクセスできない。


# おわりに
サクッと実装できたと思っていたら、全然そんなことなくて時間がかかりましたが、わかったらなんてことのない内容です。これ以上の掘り下げは行っていませんが、公式ドキュメントを見る限りでは、まだまだ細かい機能があるようですので、引き続き調査していければと思います。

# 参考
[AWS Amplify入門① / Storageについての解説](https://omuriceman.hatenablog.com/entry/amplify1) 
[Storage(公式ドキュメント)](https://aws-amplify.github.io/docs/js/storage) 

# 関連記事
[AWS amplify フレームワークの使い方Part1〜Auth設定編〜](https://qiita.com/too/items/fc961283dcbef3aafdeb)
[AWS Amplify フレームワークの使い方Part2〜Auth実践編〜](https://qiita.com/too/items/54992bb871fc1a2ab101)
[AWS Amplify フレームワークの使い方Part3〜API設定編〜](https://qiita.com/too/items/c0ce14d16772b9f71223)
[AWS Amplify フレームワークの使い方Part4〜API実践編〜](https://qiita.com/too/items/f9078803ea394c35df7d)
[AWS Amplify フレームワークの使い方Part5〜GraphQL Transform @model編〜](https://qiita.com/too/items/ab6b313da9f9e34be4a7)
[AWS Amplify フレームワークの使い方Part6〜GraphQL Transform @auth編〜]
(https://qiita.com/too/items/fae2879ea36f00c3ae10)
[AWS Amplify フレームワークの使い方Part7〜GraphQL Transform @key編〜]
(https://qiita.com/too/items/cb1dfb4f44536a3e9855)
[AWS Amplify フレームワークの使い方Part8〜GraphQL Transform @connection編〜](https://qiita.com/too/items/c77f1e5487d2497b5061)
[AWS Amplify フレームワークの使い方Part9〜Function 基礎編〜](https://qiita.com/too/items/d2732b3ec625011f4567)
[AWS Amplify フレームワークの使い方Part11〜Function 権限管理編〜](https://qiita.com/too/items/b34cbfd7e96a01e33f23)
[AWS Amplify フレームワークの使い方Part12〜ENV編〜](https://qiita.com/too/items/5c1e28cf95fc6229547e)
[AWS Amplify フレームワークの使い方Part13〜Auth 設定更新編〜]
(https://qiita.com/too/items/52f35860bcb5bdf5e667)
[AWS Amplify フレームワークの使い方Part14〜Lambda レイヤー編〜]
(https://qiita.com/too/items/54de781085bd9a3a66d0)