2019年9月21日土曜日

Firebase Auth、Cloud Firestoreのセキュリティルールについてメモ

下記の動画の内容について、自分の理解のメモ。

このドキュメントからリンクされていた動画です。
Cloud Firestore セキュリティ ルールを使ってみる | Firebase


{database} →任意のdatabase名にmatchし、matchしたdatabase名を database という変数に格納する
{restOfPath=**} →これ以下のパスにあるすべてのドキュメント・コレクション

Cloud Firestoreでは、上の階層で指定されたルールは下の階層に引き継がれない
(Realtime Databaseの場合と異なる)

service cloud.firestore {
  match databases/{database}/document {
    // restaurantID = The ID of the restaurant doc
    match /restaurants/{restaurantID} {
      // restaurantID = The ID of the restaurant doc
      // reviewID = The ID of the review doc
      allow write: if reviewID == "review_234"
    }
  }
}

アクションは5種類
read

  • get
  • list

write

  • create
  • delete
  • update

request オブジェクトは「authオブジェクト」と「resourceオブジェクト」から成る

  • request.auth にユーザーの認証情報
  • request.resource.data にこのリクエストで渡すデータの内容

が入っている感じ

こんな感じで、ルールにはresourceオブジェクトのバリデーションっぽいものも書くことができる

service cloud.firestore {
  match /databases/{database}/documents {
    match /restaurants/{restaurantID} {
      match /reviews/{reviewID} {
        // score の値が数値の時のみcreateを許可する
        allow create: if request.resource.data.score is number &&
          // かつ、resource の reviewrID が 現在のユーザーのIDと一致する場合のみcreateを許可する
          request.resource.data.reviewerID == request.auth.uid;
      }
    }
  }
}
  • request.resource.data →リクエストで渡すデータの内容
  • resource.data →DBに既に保存されているデータの内容

を指す。

service cloud.firestore {
  match /databases/{database}/documents {
    match /restaurants/{restaurantID} {
      match /reviews/{reviewID} {
        // createのルール
        allow create: if request.resource.data.score is number &&
          request.resource.data.reviewerID == request.auth.uid;

        // updateのルール
        allow update: if request.resource.data.score is number &&
          request.resource.data.reviewerID == request.auth.uid &&
          // リクエストのscoreの値と、既にDBに保存されているscoreの値が同じ時のみupdateを許可する(=scoreの値を変更できないようにする)
          request.resource.data.score == resource.data.score;
      }
    }
  }
}

query で複数のデータのリスト(コレクション)を取得する場合、
ルールで「state が published なデータのみreadを許可する」となっていると、
「全部のデータを取得」のクエリはpermission denied error になる。(たとえ今あるデータがすべてstate == published だったとしても)
「state が publishedの全データを取得」というクエリなら成功する。

自動でstate == published のデータだけフィルターして返してくれたりはしない。
※1件だけを指定して取得するリクエストの場合は、データの内容をチェックしてルールに合致するか見て返す・返さないを判断してくれる。

function の形で再利用できるようにして整理することもできる。

0 件のコメント:

コメントを投稿