【Firestore rules】get関数などの制限が緩和されたので調査してみた

Saturday, June 23, 2018

Announcing the Firestore Security Rules Simulator!のアナウンスで、Firestoreのルールでget()``exists()``getAfter()の呼び出し回数が大幅に増加したようなので実際に試してみた。

事の発端

これ

検証してみる

実際に使われるルールとは程遠いが、以下のように適当にpostモデルを11個ほど生成して、それぞれのドキュメントが取得できてnullではないというルールを愚直に書いた

service cloud.firestore {
  match /databases/{database}/documents {    
    function getPost(postID) {
      return get(/databases/$(database)/documents/post/$(postID));
    }

    match /post/{postID} {
      allow create: if getPost('post_id_1').data != null
                    && getPost('post_id_2').data != null
                    && getPost('post_id_3').data != null
                    && getPost('post_id_4').data != null
                    && getPost('post_id_5').data != null
                    && getPost('post_id_6').data != null
                    && getPost('post_id_7').data != null
                    && getPost('post_id_8').data != null
                    && getPost('post_id_9').data != null
                    && getPost('post_id_10').data != null
                    && getPost('post_id_11').data != null;
    }
  }
}

これで、client側からpostモデルを作成しようとすると、

  • get()が10回まで→ 成功
  • get()が11回を超える→ 失敗

となった。

同一pathのドキュメントを11回取得した場合は?

service cloud.firestore {
  match /databases/{database}/documents {    
    function getPost(postID) {
      return get(/databases/$(database)/documents/post/$(postID))
    }

    match /post/{postID} {
      allow create: if getPost('post_id_1').data != null
                    && getPost('post_id_1').data != null
                    && getPost('post_id_1').data != null
                    && getPost('post_id_1').data != null
                    && getPost('post_id_1').data != null
                    && getPost('post_id_1').data != null
                    && getPost('post_id_1').data != null
                    && getPost('post_id_1').data != null
                    && getPost('post_id_1').data != null
                    && getPost('post_id_1').data != null
                    && getPost('post_id_1').data != null;
    }
  }
}

ドキュメントにも書いてあるが、

同じドキュメントに対する複数のリクエストは、個別のリクエストとしてカウントされません。

ということなので、この場合は問題ない。

get()exists() を混ぜて11回呼び出す

service cloud.firestore {
  match /databases/{database}/documents {
    function getPost(postID) {
      return get(/databases/$(database)/documents/post/$(postID))
    }
    
    function existsPost(postID) {
      return exists(/databases/$(database)/documents/post/$(postID))
    }
    
    match /post/{postID} {
      allow create: if getPost('post_id_1').data != null
                    && getPost('post_id_2').data != null
                    && getPost('post_id_3').data != null
                    && getPost('post_id_4').data != null
                    && getPost('post_id_5').data != null
                    && existsPost('post_id_6')
                    && existsPost('post_id_7')
                    && existsPost('post_id_8')
                    && existsPost('post_id_9')
                    && existsPost('post_id_10')
                    && existsPost('post_id_11');
    }
  }
}

これだと書き込みエラーになる。どうやら単体で10回までというよりは、
get() exists() getAfter()合計で10回までのようだ。

ルールシミュレータだと

異なるpathのドキュメントに対してget()を11回呼び出しても成功となったのでまだ動作が不穏な感じではある 🤔

まとめ

今まで単体呼び出し3回、合計5回だったのが10回に緩和されたので、今までよりget() exists() getAfter()の呼び出し回数に怯えることはなくなった。

TechFirebaseCloud FirestoreSecurity RuleTips

TypeScriptで指定回数forEachやmapを回す

CloudStorageのルールでファイルの上書きを禁止する