iOSエンジニアのつぶやき

毎朝8:30に iOS 関連の技術について1つぶやいています。まれに釣りについてつぶやく可能性があります。

【Firestore】特定のフィールドのみ書き込めるようにする

先日に引き続き今日も Firestore のセキュリティルール について書いていきたいと思います👀

今回はタイトルの通り、Firestore のドキュメントに書き込めるフィールドのバリデーションを行っていきたいと思います。

それではやっていく

ということで、「こんな時はこうする!」的なことをつらつらと書いてみます。

指定したフィールド以外書き込めないようにしたい!

    match /hoge/{hogeId} {
      allow create: if request.resource.data.keys().hasOnly(['name', 'age', 'createdAt', 'updatedAt']);
    }

hasOnly() メソッドは、リスト内のすべての要素が引数リスト内の要素に存在するかどうかを Boolean で返します。

Interface: List  |  Firebase

特定のフィールドを必須にしたい!

    match /hoge/{hogeId} {
      allow create: if request.resource.data.keys().hasAll(['name', 'age']);
    }

hasAll() メソッドは、リスト内に引数リスト内の要素がすべて存在するかどうかを Boolean で返します。

Interface: List  |  Firebase

あるフィールドの値の型を指定したい!

    match /hoge/{hogeId} {
      allow create: if request.resource.data.name is string;
    }

ちなみに dataname がない場合はリクエスト全体が失敗してしまうので、フィールドが data に含まれない可能性ある場合は Mapget() メソッドを使ってデフォルト値を設置してあげます。ちなみにこの get() メソッドはあくまで Mapインスタンスメソッドであり、セキュリティルール標準メソッドの get() とは異なります。

Interface: Map  |  Firebase

    match /hoge/{hogeId} {
      allow create: if request.resource.data.get('name', 'default') is string;
    }

セキュリティルール言語については下記を参照してください。

firebase.google.com

指定したフィールド以外更新できないようにしたい!

    match /hoge/{hogeId} {
      allow update: if request.resource.data.diff(resource.data).affectedKeys().hasOnly(['name']);
    }

こちらに関しては公式ドキュメントにも詳しく記載されているのでリンクを載せておきます✍️

特定のフィールドへのアクセスを制御する  |  Firestore  |  Google Cloud

関数を定義

今回紹介したバリデーションの内、ある程度使用頻度の多くなりそうなものは関数に切り出しておくと便利です。

    // Create の際に必須項目とオプショナル項目を指定する
    function verifyCreateFields(required, optional) {
      let allAllowedFields = required.concat(optional);
      return request.resource.data.keys().hasAll(required) &&
        request.resource.data.keys().hasOnly(allAllowedFields);
    }

    // Update の際に更新できるフィールドを限定する
    function verifyUpdateFields(fields) {
      return request.resource.data.diff(resource.data).affectedKeys().hasOnly(fields);
    }

    // Create の際にドキュメント内の Map データの必須項目とオプショナル項目を指定する
    function verifyAnyCreateFields(data, required, optional) {
      let allAllowedFields = required.concat(optional);
      return data.keys().hasAll(required) && data.keys().hasOnly(allAllowedFields);
    }

    // Update の際にドキュメント内の Map データの更新できるフィールドを限定する
    function verifyAnyUpdateFields(data, previousData, fields) {
      return data.diff(previousData).affectedKeys().hasOnly(fields);
    }

という感じで本日も以上になります🍺

参考

その他の記事

yamato8010.hatenablog.com

yamato8010.hatenablog.com

yamato8010.hatenablog.com