1. HOME
  2. ブログ
  3. IT技術
  4. テスト駆動で学ぶ Firestore セキュリティルール 【カスタム関数編:第3回】
test-dirven-firestore-security-rules-custom-function-3-organizing-rules

テスト駆動で学ぶ Firestore セキュリティルール 【カスタム関数編:第3回】

【第3回】テスト駆動で成績データコレクションのルールを実装する

前回の記事では、成績コレクション records のデータ追加ルールを実装すると共に、カスタム関数を利用したルールの整理について解説してみました。

今回は、成績コレクション records のデータ更新ルールの実装を進めると共に、引き続き、カスタム関数を利用したルールの整理について解説していきます。

前回の記事はこちら

前回の記事は、こちらをご参照ください。

Firestore 上のデータ更新ルールの実装について

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

admin ユーザの更新要件

  1. id の更新不可
  2. studentId の更新不可
  3. season の更新不可
  4. record の更新不可

teacher ユーザの更新要件

  1. 担任でないデータは更新不可
  2. 成績以外のフィールドは更新不可
  3. 対象シーズンが成績評価期間外の場合は更新不可

その他の更新要件

  1. student ユーザは更新不可
  2. 所定のフォーマットでないデータは更新不可

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

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

テストのコード

テストの概要

「admin ユーザの更新要件」テスト

beforeEach() 関数内で、各テスト前に admin ユーザで認証されたクライアントを取得しています。

「teacher ユーザの更新要件」テスト

adminユーザの更新要件 テストと同様に、teacher ユーザで認証されたクライアントを取得しています。

担任でないデータは更新不可 となるテストでは、データ更新前に、データベース上のデータの担任を、リクエストデータの担任とは異なる担任に変更

対象シーズンが成績評価期間外の場合は更新不可 となるテストでは、データ更新の前に、 seasons コレクションの対象となる、  season ドキュメントの成績評価期間フラグを「false」に変更しています。

「所定のフォーマットでないデータは更新不可」となる要件について

データ更新については、フォーマットチェックテストが複雑になるため、解説の便宜上、テストを作成していません。

リクエストデータのフォーマットは、データ追加の場合と同じフォーマットを要件としています。

フォーマットチェックには、前回の記事で定義した、フォーマットチェック用関数 isValidFormat() を使用。

他のテストの結果に、影響がないかどうかだけを確認します。

Firestore 上のデータ更新ルールを実装してみる

それでは、作成したテストに沿って、セキュリティルールを実装していきましょう。

セキュリティルールが少し長くなってきているので、ここでは、前回の記事で実装したルールとは分けて、データ更新のルールだけを実装していきます

そして、最後に、データ追加用のルールとデータ更新用のルールを統合したいと思います。

全ての update アクセスを許可するルールを設定

データ追加ルールの実装と同様、まずは、 records コレクションの update アクセスを全て許可し、「要件にあったデータの追加に成功」するテストを通します

その後、失敗したテストを順次、上から通していきます。

セキュリティルールの調整

以下のように、セキュリティルールを調整してください。

テストをスタート

ルールを調整したら、以下のコマンドを実行して、データ更新ルール用のテストをスタートしてください。

テスト結果

admin ユーザと teacher ユーザに対して、 要件にあったデータの更新に成功 するテストが成功しました。

続いて、失敗しているテストを上から順に通していきたいと思います。

「admin, teacher ユーザ以外は更新不可」となるルールを設定

ログインしていないユーザは更新不可studentユーザは更新不可 となるように、admin ユーザか teacher ユーザでない場合は、更新不可となるルールを追加します。

データ追加ルールの実装で定義した isAdmin() 関数と同様、新しく isTeacher() 関数を定義します。

以下のようにルールを調整してください。

ここで、 isTeacher() 関数では、データ追加ルールの実装の最後で定義したロールチェック用関数 isUserRole() を使用し、リクエストユーザが teacher ロールを持っているかどうかをチェックしています。

isAdmin() 関数と同様、 isTeacher() 関数にはログインチェックも含んでいます。

また、admin ユーザと teacher ユーザで要件が異なるため、以降のルール調整に備えて、ルールを admin ユーザと teacher ユーザで分けて記述しました。

テスト結果

ログインしていないユーザは更新不可studentユーザは更新不可 となるテストが通りました。

「admin ユーザの更新要件」をルールに設定

続いて、 adminユーザの更新要件 の更新不可テストを、まとめて通してしまいます。

以下のように、ルールを調整してください。

request.resource.data.some_field == resource.data.some_field のように記述することで、対象フィールドを変更不可とすることができます。

どのフィールドでも同様の記述となるので、重複を避けるために isNotUpdate() 関数を定義しています

テスト結果

adminユーザの更新要件 テストが全て通ったので、これで admin ユーザに対するルール設定は完了です。

「teacher ユーザの更新要件」をルールに設定

続いて、 teacherユーザの更新要件 テストを通して行きます。

担任でないデータは更新不可対象シーズンが成績評価期間外の場合は更新不可 となるよう、以下のようにルールを調整してください。

ここで、 isHomeroomTeacher() 関数により、リクエストユーザが対象となる成績データの担任であるかどうかを判定しています。

isEvaluationPeriod() 関数は、 seasons コレクションの対象となる season ドキュメントを参照して、成績評価期間フラグをチェックしています。

テスト結果

担任でないデータは更新不可 となるテストと、 対象シーズンが成績評価期間外の場合は更新不可 となるテストが通りました。

「成績以外のフィールドは更新不可」となるルールを設定

最後に、 成績以外のフィールドは更新不可 となるテストをまとめて通してしまいます。

先ほど定義した isNotUpdate() 関数を使って、以下のようにルールを調整してください。

テスト結果

全てのテストが通ったので、これで要件に沿ったデータ更新用のルールを実装することができました

カスタム関数でルールを整理

データ追加ルールの実装のときと同じように、今回もテスト環境を活かしてルールをもう少しだけ調整・整理したいと思います。

isNotUpdateImmutables() 関数を定義

record ドキュメントのフォーマット定義で変更不可としたフィールドは、当然ながら、admin ユーザと teacher ユーザの両方が更新不可となります。

このため、「allow式」中で、変更不可チェック用に追加した条件が重複しています。

これらのフィールドの不変チェックをひとまとめにして、 isNotUpdateImmutables() 関数を定義します。

リクエストデータのフォーマットチェック

また、リクエストデータのフォーマットは、データ追加の場合と同じフォーマットです。

そのため、データ追加ルールの実装時に定義した isValidFormat() 関数を使い、リクエストデータのフォーマットチェックを行います。

テストが複雑になるため、更新ルール用のテストでは、フォーマットチェックテストは行っていません。

ルールにフォーマットチェック項目を追加した後、テストの結果に影響がないかだけ確認したいと思います。

以下のようにルールを調整してください。

create アクセス、 update アクセスで共通して変更不可である idstudentIdseason フィールドの更新不可チェックを isNotUpdateImmutables() 関数にまとめました。

また、admin ユーザと teacher ユーザのルールに、リクエストデータのフォーマットチェック関数 isValidFormat() を追加しました。

テスト結果

テスト結果に変化はありません。問題なく、ルールを調整・整理することができました。

以上でデータ更新用ルールの実装は完了です。

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

ここまでのルールの統合とリグレッションテスト

最後に、今回実装したデータ更新用のルールと前回のデータ追加用のルールを統合します。

ここまでのセキュリティルールを統合すると、以下のようになります。

統合したセキュリティルール

まとまりを考慮して、カスタム関数の順序を一部調整しています。

全てのテストを実行

以下のコマンドを実行し、ここまでの全てのテストを実行してください。

テスト結果

全てのテストに成功していますので、ここまでのルールが問題なく実装できていることが確認できました!

第4回へつづく!

「カスタム関数編」第3回となるこの記事では、成績コレクション records のデータ更新用セキュリティルールを実装しつつ、カスタム関数を使ってルールを整理してみました!

次回は、成績コレクション records のデータ取得・削除用ルールの実装を進めます。

データ取得・削除用ルールの実装した後、作成した全てのテストを実行し、作成したセキュリティルールが「カスタム関数編」第1回に設定した要件に沿ったルールとなっているかを確認してみます。

次回もお楽しみに!

第4回の記事はこちら

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

書いた人はこんな人

広告メディア事業部
広告メディア事業部
「好きを仕事にするエンジニア集団」の(株)ライトコードです!

ライトコードは、福岡、東京、大阪の3拠点で事業展開するIT企業です。
現在は、国内を代表する大手IT企業を取引先にもち、ITシステムの受託事業が中心。
いずれも直取引で、月間PV数1億を超えるWebサービスのシステム開発・運営、インフラの構築・運用に携わっています。

システム開発依頼・お見積もり大歓迎!

また、現在「WEBエンジニア」「モバイルエンジニア」「営業」「WEBデザイナー」「WEBディレクター」を積極採用中です!
インターンや新卒採用も行っております。

以下よりご応募をお待ちしております!
https://rightcode.co.jp/recruit

関連記事

採用情報

\ あの有名サービスに参画!? /

バックエンドエンジニア

\ クリエイティブの最前線 /

フロントエンドエンジニア

\ 世界を変える…! /

Androidエンジニア

\ みんなが使うアプリを創る /

iOSエンジニア