Cloud Firestore と Realtime Database の両方が依存するルール言語は、情報セキュリティとアクセス制御を管理するために特別に作成されたものです。このルール言語は強力で簡潔ですが、ルールが長く複雑になってくると、その動作でのエラーをデバッグする、なんらかの助けが必要になることがあります。
Firebase エミュレータにはルール カバレッジ レポートを生成する機能が組み込まれているので、エラーを再現すると、それぞれのサブ式の評価結果を正確に確認できます。また、従来の「ライン カバレッジ」手法のように、このレポートから各テストケースでルールが使用された頻度を把握することもできます。
レポートを生成する
一連のテストを実施した後、それぞれのセキュリティ ルールの評価が表示されたテスト カバレッジ レポートにアクセスできます。
レポートを取得するには、エミュレータの実行中に公開されたエンドポイントに対してクエリを実行します。ブラウザでの表示に適したバージョンを参照するには、次の URL を使用します。
Cloud Firestore
http://localhost:8080/emulator/v1/projects/<database_name>:ruleCoverage.html
Realtime Database
http://localhost:9000/.inspect/coverage?ns=<database_name>
これによりルールが式やサブ式に分割されます。それぞれの式の上にマウスカーソルを重ねて、評価回数や返された値などの詳細情報を確認できます。このデータの未加工の JSON バージョンを取得するには、クエリに次の URL を含めます。
Cloud Firestore
http://localhost:8080/emulator/v1/projects/<database_name>:ruleCoverage
Realtime Database
http://localhost:9000/.inspect/coverage.json?ns=<database_name>
サンプルルールをデバッグする
テストレポートを簡単に生成するには、GitHub で利用できる Cloud Firestore 用と Realtime Database 用のエミュレータ クイックスタートを使用します。これらのクイックスタートでは、エミュレータを適切にインストール、初期化する方法と、一連のサンプルルールからサンプルテストを生成する方法を説明しています。
Cloud Firestore を使用してユーザーがボタンをクリックした回数をカウントするアプリの例を考えてみましょう。このアプリでは次のルールを使用します。
Cloud Firestore
service cloud.firestore { match /databases/{database}/documents { match /counters/{counter} { allow read; allow write: if request.resource.data.value == resource.data.value +1; } } }
上記のルールでのエラーをデバッグするには、次のサンプル JavaScript テストを使用します。
const counter0 = db.collection("counters").doc("0");
await firebase.assertSucceeds(counter0.set({value: 0}));
エミュレータが生成したレポートを確認するには、次の URL にアクセスします。
http://localhost:8080/emulator/v1/projects/<database_name>:ruleCoverage.html
レポートには、次の未定義のエラーと null 値のエラーが示されています。
この例での問題は、ルールがドキュメントの作成とドキュメントの更新を区別していないことです。したがって、ドキュメントが存在しないと書き込みが許可されず、ドキュメントが存在しないために、ドキュメントを作成することもできません。「書き込み」をより具体的な 2 つのオペレーション(「作成」と「更新」)に区別すると、この問題は解決されます。
Cloud Firestore
service cloud.firestore { match /databases/{database}/documents { match /counters/{counter} { allow read; allow create: if request.resource.data.value == 0; allow update: if request.resource.data.value == resource.data.value +1; } } }
生成されたレポートには、各ルールが使用された頻度とルールから返された内容が示されます。