1. HOME
  2. ブログ
  3. IT技術
  4. テスト駆動で学ぶ Firestore セキュリティルール 【データ比較編 / 前編】

テスト駆動で学ぶ Firestore セキュリティルール 【データ比較編 / 前編】

テスト駆動で書籍コレクションのルールを実装する

この記事では、前編・後編の二回に分けて、Firestore セキュリティルール中でのデータ比較について解説していきます。

書店のネットショッピングサービスを想定し、Firestore 上の書籍コレクションのルール実装を例に、解説を進めていきます。

前回のデータ検証編では、主にリクエストデータやデータベース上のデータの参照について解説しました。

今回の記事では、より具体的に、データの数値比較やデータ型のチェックについて解説していきます。

データ検証編の記事はこちら

簡単な流れ

「データ比較編」では、以下のような流れで解説を進めていきます。

データ比較編:前編

  1. 書籍コレクションの要件を設定
  2. テスト環境の準備
  3. テストデータの作成
  4. Firestore 上のデータ追加ルールの実装と解説

データ比較編:後編

  1. Firestore 上のデータ更新ルールの実装と解説
  2. Firestore 上のデータ取得ルールの実装と解説
  3. 全体テストで要件の最終チェック
  4. まとめ

今回は、前編パートの、「実装目標(要件)の設定からデータ追加ルールの実装まで」を解説していきます。

書籍コレクションの実装目標

書籍コレクション books を想定し、以下の要件を目標に実装を進めていきます。

書籍データ追加・更新の要件

  1. データ追加・更新をリクエストしたユーザが商品管理者でない場合は追加・更新不可
  2. データのサイズが「9」でない場合は追加・更新不可
  3. タイトルが string 型でない場合は追加・更新不可
  4. 書籍詳細が string 型でない場合は追加・更新不可
  5. 出版日が timestamp 型でない場合は追加・更新不可
  6. 価格が int 型で「0」以上でない場合は追加・更新不可
  7. 在庫が int 型で「0」以上でない場合は追加・更新不可
  8. 状態が new, used のいずれかでない場合は追加・更新不可

商品管理者に対する要件

ここで、商品管理者がデータ更新することを想定し、商品管理者に対する要件を以下のように補足します。

▼データ追加では、「リクエストデータの商品管理者にリクエストユーザが存在する」ものとします。

▼データ更新では、「データベース上のデータの商品管理者にリクエストユーザが存在する」ことを要件とします。

データの取得要件

  1. 下書きデータの取得不可
  2. 在庫が「5」以下の書籍は取得不可

在庫が「5」以下の場合は、店頭販売のみを行うと仮定し、取得不可としています。

前準備 ~ テスト環境 ~

初めに、テスト環境を準備します。

テスト環境のセットアップ

以下のコマンドを実行して、テスト環境をセットアップしてください。

なお、今回の記事のコードは、以下のリポジトリにまとめてあります。

【GitHub】
rightcode/firestore-security-rules-test_data-compare

npm パッケージのインストール

以下のコマンドを実行して、必要となる npm パッケージをインストールしてください。

Firebase CLI ツールのインストール

まだ、Firebase CLI ツールをインストールしていない場合は、以下のコマンドを実行してインストールします。

Firestore エミュレータを起動

そして、コマンドを実行して、Firestore エミュレータを起動してください。

以上で、テスト環境の準備は完了です!

テスト環境のセットアップの解説

なお、テスト環境のセットアップについて、より詳細な内容は、以下の記事をお読みください!

コードをチェックアウトする

今回の記事で解説するコードを確認する場合は、以下のコマンドより「master ブランチ」をチェックアウトしてください。

「master ブランチ」に実装済みのコードを設置してあります。

※注意※
コードの調整などにより、この記事の内容とは、記述が一部異なる場合があります。

前準備 ~ テストデータ ~

テストを作成する前に、まず、テストデータ用のコードを用意します。

tests/data.ts ファイルを作成して、以下のように記述してください。

テストデータのコード

テストデータの概要

adminUser

テストで対象となる、書籍データの商品管理者の1人として定義。

データの追加・更新が可能なユーザとして使用します。

initialData

初期データ。

データ追加テストでのデータ追加と、更新・取得テスト前の初期データの準備に使用します。

validUpdateData

更新テスト用データ。

要件に沿ったデータで、データの更新に使用します。

Firestore 上のデータ追加ルールの実装

データ追加の要件

データ追加ルールのテストを作成する前に、まずは、データ追加の要件を再確認します。

  1. データ追加をリクエストしたユーザが商品管理者でない場合は追加不可
  2. データのサイズが「9」でない場合は追加不可
  3. タイトルが string 型でない場合は追加不可
  4. 書籍詳細が string 型でない場合は追加不可
  5. 出版日が timestamp 型でない場合は追加不可
  6. 価格が int 型で「0」以上でない場合は追加不可
  7. 在庫が int 型で「0」以上でない場合は追加不可
  8. 状態が new, used のいずれかでない場合は追加不可

ここで、一番上の商品管理者に関する要件については、「リクエストデータの商品管理者にリクエストユーザが存在する」ことが要件となります。

テストの作成

上記の要件に沿って、テストを作成します。

tests/data.add.test.ts ファイルを追加して、以下のようにコードを記述してください。

テストのコード

テストの概要

「データ追加をリクエストしたユーザが商品管理者でない場合は追加不可」となるテスト

商品管理者に含まれないユーザとして、 non_admin_user で認証したクライアントを取得しています。

「データのサイズが「9」でない場合は追加不可」となるテスト

リクエストデータのサイズを変更するため、初期データに author フィールドを追加しています。

型のチェックテスト

各テストのデータ追加リクエストの前に、初期データを調整して、不適切な型の値を設定しています。

ルールの実装

データ追加ルール用のテストが完成したので、このテストに沿ってセキュリティルールを実装していきます。

テスト駆動のスタイルに従い、まずはテストを実行してみて、テストが失敗することを確認します

全ての create アクセスを許可するセキュリティルールを設定

今回は、少しだけルールの実装を進めて、 create アクセスを全て許可するところからスタートします。

books コレクションの create アクセスを全て許可し、「要件にあったデータの追加に成功」するテストだけを通します。

その上で、失敗した追加不可テストを上から順に通しながらルールを実装していきます

tests/firestore.rules を追加して、以下のように記述してください。

テストをスタート

ファイルを追加したら、以下のコマンドを実行して、テストをスタートしてください。

テスト結果

テスト結果は、以下のようになります。(テスト結果の冒頭のみを抜粋)

「要件にあったデータの追加に成功」するテストだけが通りました

前述の通り、失敗した追加不可テストを上から順に通して行きます

リスト型データ中の指定値の有無を条件に使用する

「データ追加をリクエストしたユーザが、商品管理者でない場合は追加不可」となるよう、以下のルールを設定してください。

ここで、 request.auth.uid in request.resource.data.adminUsers の条件により、リクエストデータの商品管理者リストの中に、リクエストユーザが含まれるかをチェックしています。

リスト型のデータに、 in 演算子を使用することで、そのリストに指定の値が存在するかをチェックできます。

テスト結果

ルールの変更により、テストが再度実行され、以下のような結果が表示されます!

データの要素数の比較結果を条件に使用する

次に、「データのサイズが「9」でない場合は追加不可」となるテストを通すため、以下のようにルールを追加してください。

request.resource.data.size() == 9 の条件により、リクエストデータの要素の数が「9」である場合のみ、追加アクセスを許可しています。

マップ型やリスト型のデータには、 size() メソッドが用意されており、データの要素数を参照することができます。

テスト結果

「データのサイズが9でない場合は追加不可」となるテストが通りました。

データ型や数値の比較結果を条件に使用する

最後に、「残っているテスト」と「型と値のチェックテスト」をまとめて通してしまいます。

以下のように、ルールを調整しましょう!

ここで、 is 演算子により、各フィールドの型を指定しています。

例えば、 releaseDate フィールドは、 request.resource.data.releaseDate is timestamp の条件により、タイムスタンプ型のみが許可されています。

int 型などの数値型は、 >=< などの演算子を使って、数値の比較ができます

例えば、 request.resource.data.price >= 0 の条件によって、 price フィールドは、「0」以上でない場合はデータを追加できません。

先ほど説明した in 演算子を使って、 request.resource.data.condition in ["new","used"] の条件により、 condition フィールドの値は "new" か  "used" に制限しています。

テスト結果

全てのテストが通りました!

以上で、書籍データ追加用のルールは、実装完了です!

最後に、次のテストとの競合を避けるため、テストを終了してください。

後編へつづく!

今回の記事では、「実装目標(要件)の設定」から「データ追加ルールの実装」までを、テスト駆動のスタイルで解説してみました。

後編では、前編の内容を復習しつつ、前編と同様に、テスト駆動スタイルで Firestore 上のデータ更新と取得のルールを実装していきます。

(株)ライトコードは、WEB・アプリ・ゲーム開発に強い、「好きを仕事にするエンジニア集団」です。
システム開発依頼・お見積もりはこちらまでお願いします。
また、技術が大好きなエンジニアを積極採用中です!詳しくはこちらをご覧ください。

※現在、多数のお問合せを頂いており、返信に、多少お時間を頂く場合がございます。

後編はこちら

こちらの記事もオススメ!

ライトコードよりお知らせ

にゃんこ師匠にゃんこ師匠
システム開発のご相談やご依頼はこちら
ミツオカミツオカ
ライトコードの採用募集はこちら
にゃんこ師匠にゃんこ師匠
社長と一杯飲みながらお話してみたい方はこちら
ミツオカミツオカ
フリーランスエンジニア様の募集はこちら
にゃんこ師匠にゃんこ師匠
その他、お問い合わせはこちら
ミツオカミツオカ
   
お気軽にお問い合わせください!せっかくなので、別の記事もぜひ読んでいって下さいね!

一緒に働いてくれる仲間を募集しております!

ライトコードでは、仲間を募集しております!

当社のモットーは「好きなことを仕事にするエンジニア集団」「エンジニアによるエンジニアのための会社」。エンジニアであるあなたの「やってみたいこと」を全力で応援する会社です。

また、ライトコードは現在、急成長中!だからこそ、あなたにお任せしたいやりがいのあるお仕事は沢山あります。「コアメンバー」として活躍してくれる、あなたからのご応募をお待ちしております!

なお、ご応募の前に、「話しだけ聞いてみたい」「社内の雰囲気を知りたい」という方はこちらをご覧ください。

ライトコードでは一緒に働いていただける方を募集しております!

採用情報はこちら

書いた人はこんな人

ライトコードメディア編集部
ライトコードメディア編集部
「好きなことを仕事にするエンジニア集団」の(株)ライトコードのメディア編集部が書いている記事です。

関連記事