98
55

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

もう間違えない! Cloud Firestore rulesのresource, request.resource, writeFields

Last updated at Posted at 2018-09-06

[2020/10 更新]
writeFieldsに関しては現在削除され使用不可能になっており、代わりにMapDiffを使う必要があります。
詳しくはCloud Firestoreのセキュリティルールにかつて存在したwriteFieldsを覚えていますか?を御覧ください


Cloud Firestoreのrulsを書く上でややこしい

  • resource 変数
  • request.resource 変数
  • writeFields 変数

のそれぞれの違いを説明しようと思います。これを見ればもう間違えることはなくなるはず。

TL;DR

  • resource: 現在DBに格納されているドキュメント
  • request.resource: 書き込みを行った場合に期待される将来のドキュメント(の状態)
  • writeFields: 書き込みを行う場合に、書き込もうとしているフィールドのkeyの一覧

それぞれの違い

resource

ドキュメントによると、

resource 変数は要求されたドキュメントを参照し、resource.data はドキュメントに格納されているすべてのフィールドと値のマップです。

とあるので、現在のドキュメントに格納されているフィールドと値のmapを参照できます。
rulesのそれぞれのオペレーションでは以下の通り。

  • read(get, list): 現在のDBに格納されているドキュメント
  • create: undefined
  • update: 現在のDBに格納されているドキュメント
  • delete: 現在のDBに格納されているドキュメント

request.resource

ルールセットが保留中の書き込みを許可する場合は、request.resource 変数にはドキュメントの将来の状態が含められます。ドキュメント フィールドのサブセットのみを変更する update オペレーションの場合、request.resource 変数にはオペレーション後の保留中のドキュメントの状態が含まれます。

つまり、書き込みのオペレーション(crate, update, delete)を実行した後の(保留)ドキュメント状態がmapとして格納される。なので

  • read(get, list): undefined(writeオペレーション時のみ存在するため)
  • create: 新規で書き込むドキュメントのフィールドと値のmap
  • update: 値の追加更新削除をした後の 将来の状態の フィールドと値のmap。
  • delete: undefined

となる。 update の場合は、追加更新削除後の 将来の状態 を表すので、あるオペレーションで既存のデータ {A, B}{C} を書き加えて更新する場合、 request.resource.data には {A, B, C} が含まれる。
一方で

writeFields

List of fields being written in a write request.

とあり、意訳すると、「書き込みリクエスト時に書き込まれるであろうフィールドのリスト」となる。

  • read(get, list): undefined
  • create: 書き込むフィールドのkey (request.resource.data.keys() と一致)
  • update: 今回更新追加削除するフィールドのkey (request.resource.data.keys()必ずしも一致しない 。update時に変更しようとしているフィールドのkeyのみ)
  • delete: undefined

表にしてみる

実際にそれぞれのオペレーションで、現在のフィールド、書き込むフィールドが与えられた時に、resource, request.resourcet, writeFields の値がどう変化するか表にまとめます。

read(get, list)

現在のフィールド 書き込むフィールド resource request.resource writeFields
{
  name: 'mike',
  age: 25
}
undefined {
  name: 'mike',
  age: 25
}
undefined undefined

create

現在のフィールド 書き込むフィールド resource request.resource writeFields
undefined {
  name: 'mike',
  age: 25
}
undefined {
  name: 'mike',
  age: 25
}
['name', 'age']

update

現在のフィールド 書き込むフィールド resource request.resource writeFields
{
  name: 'mike',
  age: 25
}
{
  company: 'Foobar Inc.'
}
{
  name: 'mike',
  age: 25
}
{
  name: 'mike',
  age: 25,
  company: 'Foobar Inc.'
}
['company']

delete

現在のフィールド 書き込むフィールド resource request.resource writeFields
{
  name: 'mike',
  age: 25
}
undefined {
  name: 'mike',
  age: 25
}
undefined undefined

参考

98
55
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
98
55

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?