Cloud FirestoreはNoSQLでスキーマレスなので、任意のフィールドに対して任意の値を入れることができるのだが
セキュリティルール的には、書き込み時にどのフィールドにどの型の値が入るのかしっかりチェックしたほうが良いのでその方法を。

is演算子を使う

is 演算子を使うことでvalueが何の型かチェックできるようになる

文字列

is string で判定する

allow create: if request.resource.data.name is string;

数値

数値はint float number と、3パターンある

// ageがint型(整数値)以外だと拒否される
allow create: if request.resource.data.age is int; 

// distanceがfloat型(浮動小数点数)以外だと拒否される
allow create: if request.resource.data.distance is float; 

// numが数値以外だと拒否される
allow create: if request.resource.data.num is number;

注意なのは、floatの場合、 1.0 は許可されるが、 1 だと拒否されるので注意。
完全に整数値でないとならない場合はint、そうでなければnumberを使っておくのが吉

真偽値

is bool で判定できる。

allow create: if request.resource.data.flag is bool;

たまにSwift(iOS)の感覚でいるとnumberでも判定できるんじゃね?って思ってしまうが、numberで判定することはできない。

日付

is timestamp で判定できる

allow create: if request.resource.data.publishedAt is timestamp;

geo

is latlng で判定できる

allow create: if request.resource.data.point is latlng;

配列

is list で判定できる

allow create: if request.resource.data.members is list;

ただし、配列内の各要素の型が何であるかまでは判定できない。

連想配列(Object)

is map で判定できる

allow create: if request.resource.data.userInfo is map;

ただし、連想配列のkeyやvalueの型が何であるかまでは判定できない。

参照(Reference)

is path で判定できる

allow create: if request.resource.data.userRef is path;

※このブログを書いた現在、このルール文のシミュレートはうまくいかない。

型チェックがうまくいかないときのチェックポイント

型チェックが正しそうなのにうまく判定されない…というときは、

  • 型名を間違えていないか
  • 型名はlower caseになっているか(Int とか String ではだめ)

あたりを見てみると良い。
ちなみに、ルールシミュレータで型を間違えて記述すると、不明なエラーを吐いて、以下の文章が表示される

An unsupported type identifier was used with the ‘is’ operator. Received XXX. Expected one of bool,constraint,duration,float,int,latlng,list,number,map,string,timestamp,path

constraints ってなんだろ。

まとめ

is演算子で事前に書き込む値の型をチェックすることで、書き込み時に想定と異なる値の書き込みがされないように防ぐことができる。
一方で、現状はList,Mapに関してはValueの型を縛ることができないし、forEach的な感じで配列内を走査して1つ1つチェックすることもできないのでその辺りは運用でカバーするしかない。