セキュリティ ルールの記述条件

このガイドはセキュリティ ルールの構造化ガイドに基づき、Cloud Firestore セキュリティ ルールに条件を追加する方法について説明します。Cloud Firestore セキュリティ ルールの基本については、スタートガイドをご覧ください。

Cloud Firestore セキュリティ ルールの主要な構成要素は条件です。条件とは、特定のオペレーションを許可するか拒否するかを決定するブール式です。セキュリティ ルールを使用して、ユーザー認証をチェックしたり、受信データを検証したり、データベースの他の部分にアクセスしたりするための条件を記述します。

認証

最も一般的なセキュリティ ルールのパターンの 1 つは、ユーザーの認証状態に基づいてアクセスを制御することです。たとえば、アプリにログインしているユーザーのみがデータの書き込みを許可されるようにすることができます。

service cloud.firestore {
  match /databases/{database}/documents {
    // Allow the user to access documents in the "cities" collection
    // only if they are authenticated.
    match /cities/{city} {
      allow read, write: if request.auth.uid != null;
    }
  }
}

別の一般的なパターンは、ユーザーが自分のデータのみを読み書きできるようにすることです。

service cloud.firestore {
  match /databases/{database}/documents {
    // Make sure the uid of the requesting user matches the 'author_id' field
    // of the document
    match /users/{user} {
      allow read, update, delete: if request.auth.uid == resource.data.author_id;
      allow create: if request.auth.uid != null;
    }
  }
}

Firebase Authentication を使用するアプリの場合、request.auth 変数には、データを要求しているクライアントの認証情報が含まれています。request.auth の詳細については、リファレンス ドキュメントをご覧ください。

データの検証

多くのアプリでは、アクセス制御情報をデータベース内のドキュメントのフィールドとして格納します。Cloud Firestore セキュリティ ルールでは、ドキュメント データに基づいて動的にアクセスを許可または拒否できます。

service cloud.firestore {
  match /databases/{database}/documents {
    // Allow the user to read data if the document has the 'visibility'
    // field set to 'public'
    match /cities/{city} {
      allow read: if resource.data.visibility == 'public';
    }
  }
}

resource 変数は要求されたドキュメントを参照し、resource.data はドキュメントに格納されているすべてのフィールドと値のマップです。resource 変数の詳細については、リファレンス ドキュメントをご覧ください。

データを書き込むときに、受信データと既存のデータを比較することができます。このケースで、ルールセットが保留中の書き込みを許可する場合は、request.resource 変数にはドキュメントの将来の状態が含められます。ドキュメント フィールドのサブセットのみを変更する update オペレーションの場合、request.resource 変数にはオペレーション後の保留中のドキュメントの状態が含まれます。request.resource のフィールド値をチェックすることで、望ましくない、または整合性のないデータの更新を防ぐことができます。

service cloud.firestore {
  match /databases/{database}/documents {
    // Make sure all cities have a positive population and
    // the name is not changed
    match /cities/{city} {
      allow update: if request.resource.data.population > 0
                    && request.resource.data.name == resource.data.name;
    }
  }
}

他のドキュメントへのアクセス

セキュリティ ルールでは、get() 関数と exists() 関数を使用して、データベース内の他のドキュメントに対する受信リクエストを評価できます。get() 関数と exists() 関数は、には、完全なドキュメント パスを指定します。変数を使用して get()exists() のためのパスを構築する場合は、$(variable) 構文を使用して明示的に変数をエスケープする必要があります。

以下に示す例では、database 変数が match ステートメント match /databases/{database}/documents によってキャプチャされ、次のパスの形成に使用されます。

service cloud.firestore {
  match /databases/{database}/documents {
    match /cities/{city} {
      // Make sure a 'users' document exists for the requesting user before
      // allowing any writes to the 'cities' collection
      allow create: if exists(/databases/$(database)/documents/users/$(request.auth.uid))

      // Allow the user to delete cities if their user document has the
      // 'admin' field set to 'true'
      allow delete: if get(/databases/$(database)/documents/users/$(request.auth.uid)).data.admin == true
    }
  }
}

書き込みの場合は、getAfter() 関数を使用すると、トランザクションまたは一括書き込みが完了した後の、トランザクションまたはバッチが commit される前の時点で、ドキュメントの状態にアクセスできます。get() と同様に、getAfter() 関数は完全なドキュメント パスを受け取ります。getAfter() を使用すると、トランザクションまたはバッチとしてまとめて実行する必要がある一連の書き込みを定義することができます。

カスタム関数

セキュリティ ルールの複雑化に伴い、一連の条件を関数としてラップし、ルールセット全体で再利用できるようにすることが必要になることがあります。セキュリティ ルールはカスタム関数をサポートしています。カスタム関数の構文は JavaScript に少し似ていますが、セキュリティ ルール関数はドメイン固有の言語で記述され、いくつかの重要な制限があります。

  • 関数には 1 つの return ステートメントのみを含めることができます。追加ロジックを含めることはできません。たとえば、中間変数を作成したり、ループを実行したり、外部サービスを呼び出したりすることはできません。
  • 関数は、定義されているスコープから、関数と変数に自動的にアクセスすることができます。たとえば、service cloud.firestore スコープ内で定義された関数は、resource 変数、および get()exists() などの組み込み関数にアクセスできます。
  • 関数は他の関数を呼び出すことはできますが、再帰呼び出しはできません。コールスタックの深さは合計 10 に制限されています。

関数は function キーワードで定義され、0 個以上の引数を使用します。たとえば、上に示した例で使用した 2 つのタイプの条件を 1 つの関数にまとめることができます。

service cloud.firestore {
  match /databases/{database}/documents {
    // True if the user is signed in or the requested data is 'public'
    function signedInOrPublic() {
      return request.auth.uid != null || resource.data.visibility == 'public';
    }

    match /cities/{city} {
      allow read, write: if signedInOrPublic();
    }

    match /users/{user} {
      allow read, write: if signedInOrPublic();
    }
  }
}

セキュリティ ルールで関数を使用すると、ルールが複雑化した場合に保守しやすくなります。デベロッパー定義関数の詳細については、リファレンス ドキュメントをご覧ください。

次のステップ

フィードバックを送信...

ご不明な点がありましたら、Google のサポートページをご覧ください。