TypeScript & React & Firebase で何かつくってみる9 Firestore

既に使っているが, はっきりいって コレクションとドキュメントの違いもあいまいなまま使っていた Firestore.
rules を使ってみたくなったので もう少しちゃんと調べることにする.

Firestore データ構成

ざっと以下のように理解した.

・ Firestore における データベース とは コレクションの連想配列である.
コレクション とは ドキュメント の連想配列 である.
ドキュメント とは コレクションの連想配列 + フィールドの連想配列である.
フィールド とは JSON で表現できるような汎用データ構造である.

C++ で書くとこんな感じだろうか. 

using Database = std::map<std::string, Collection>;
using Collection = std::map<std::string, Document>;
struct Document
{
	std::map<std::string, Collection> subCollections;
	std::map<std::string, Field> fields;
};
using Field = Json;

「そこは TypeScript で例えろよ」とツッコまれそうだが, まだ慣れてないためやむを得ない.

コレクションがドキュメントを持ち, ドキュメントがコレクションを持つため, このデータ構造は再帰的な階層構造になる.
各要素は名前を持つため, '/' 区切りで連結すれば 一意な パス表現 をつくることができる.

フォルダとファイルで例える記事もあったが, ファイルシステムのパスは

   {フォルダ名}/{フォルダ名}/{フォルダ名}/{ファイル名}

なのに対し, firestore は

   {コレクション名}/{ドキュメント名}/{コレクション名}/{ドキュメント名}

なので 少し感覚が異なる. 
要素数が偶数ならドキュメントへのパス, 奇数ならコレクションへのパスである.

「要素2種類もいる?」 という気もするが, きっと何か意味があるのだろう.

アプリ修正

ルールを試す前に, アプリを少し変更する.

今までは deck と hand という 2つの の間をカードが移動してきた.  しかし 2つだけだとルールによる許可や禁止の違いを出しにくいため, 山を一つ増やす.

画像1

hand をやめて ユーザーっぽく alice bob にする. なんかセキュリティ教本に出てきそうな名前だがそこは重要ではない.

実装は旧コードの焼き増しなので割愛する.


Firestore rules

以下のサイトが初歩から経験上の知見まで書かれていてすばらしい. おそらくこれから何度も参照することになるだろう.

これらを参考に開発アプリにルールを適用してみる.

前回 actions を使って山を更新する方式にしたため, この actions に対してルールを設定する.  まずは単純なルールから 動作確認 する. 

ローカルのアプリプロジェクト内にある ./firestore.rules を編集する.

rules_version = '2';
service cloud.firestore {
 match /databases/{database}/documents {
   match /fields/{deckId} {
     allow read, write: if request.time < timestamp.date(2020, 5, 23);
   }
   match /actions/{actionId} {
     allow read;
     allow write: if request.resource.data.from == 'fields/deck';
   }
 }
}

ルールの適用は以下のコマンドだ.

$ npx firebase deploy --only firestore:rules

ルール "match /actions/{actionId}" で 「deck から X への移動」 のみが許可されることを確認する.
「一枚引く」ことはできるが「一枚戻す」はできない.

さらに alice にだけ 「一枚戻す」を許可する場合は以下のように書ける.

match /actions/{actionId} {
 allow read;
 allow write: if request.resource.data.from in ['fields/alice', 'fields/deck'];
}

in {配列} という書き方で 配列内のどれかに一致していれば true という意味になる.  これで bob だけが 「1枚戻す」に失敗することを確認する.

ここまでは問題ない.

長くなったので続きは明日.

この記事が気に入ったらサポートをしてみませんか?