👋
Firebase Firestoreでのサブコレクションの Permission について
Firestore のサブコレクション周りの Permission 設定でちょっと引っかかったのでメモがてら説明します。
サブコレクションの条件と親の条件
下記のようなルールを設定している場合を考えます。
service cloud.firestore {
match /databases/{database}/documents {
match /parent/{parentId} {
allow read, write: if { 条件① };
match /{subCollection}/{subDoc} {
allow read, write: if { 条件② };
}
}
}
}
この時 subCollection の subDoc を取得するときの条件は
- 条件① と 条件② の両方が適用される
- 条件② のみ適用される
のどちらになるでしょうか。
正解は 条件②のみ適用される
が正しいです。
自分はネストされてるからいい感じに 「条件① と 条件② の両方が適用される」 ものと勘違いしてたのですが、これは間違いだったようです。
親のデータを見る必要がある時
この時、 parent のドキュメントには pid というデータがあって、これを request.auth.uid
が等しい時だけ read できるようにしたいとします。その時、下記のような Rule を設定することになります。
service cloud.firestore {
match /databases/{database}/documents {
match /parent/{parentId} {
allow read, write: if request.auth != null && resource.data.pid == request.auth.uid;
match /{subCollection}/{subDoc} {
allow read, write: if { ??? };
}
}
}
}
この時に、 サブコレクションのデータの読み書きについても 親データに pid == uid が成り立つ時としたい場合の指定の仕方はどうなるでしょうか。 先にも説明した通り親の条件を関係ないため、別途サブコレクション側でも指定する必要があります。
まず、下記の書き方はもちろん違います。サブコレクションのデータの pid を見ようとしてますが、 照らし合わせたいデータは parent の pid です。
service cloud.firestore {
match /databases/{database}/documents {
match /parent/{parentId} {
allow read, write: if request.auth != null && resource.data.pid == request.auth.uid;
match /{subCollection}/{subDoc} {
allow read, write: if request.auth != null && resource.data.pid == request.auth.uid;
}
}
}
}
結論としては get
を使うことで解決できます。
下記のように get(親のパス).data.pid
で取得してこれを uid と比較することができます。
service cloud.firestore {
match /databases/{database}/documents {
match /parent/{parentId} {
allow read, write: if request.auth != null && resource.data.pid == request.auth.uid;
match /{subCollection}/{subDoc} {
allow read, write: if request.auth != null && get(/databases/$(database)/documents/parent/$(parentId)).data.pid == request.auth.uid;
}
}
}
}
Discussion