はい!firestore.rulesで嵌まった私が来ました。
以下のようなfirestore.rulesを書いたんですね。pagesコレクションがあってそのドキュメントにはそのドキュメントのオーナーを示すusers_refというusersコレクションへのリファレンスがあって、アクセスして来たユーザがオーナーかどうかチェックして真の時のみ読み書き出来る、というルールを書いたつもりなんですが、この書き方だとダメでした。「FirebaseError: Missing or insufficient permissions.」とエラーが出ます。
service cloud.firestore {
match /databases/{database}/documents {
match /pages/{pageId} {
allow read, write: matchUserReference(resource.data.users_ref, request.auth.uid)
}
}
function matchUserReference(ref, uid) {
return ref == /databases/$(database)/documents/users/$(uid)
}
}
で、以下のように書き直したら期待通りに動きました。
service cloud.firestore {
match /databases/{database}/documents {
match /pages/{pageId} {
allow read, write: matchUserReference(resource.data.users_ref, request.auth.uid)
}
function matchUserReference(ref, uid) {
return ref == /databases/$(database)/documents/users/$(uid)
}
}
}
変わったのはfunctionの位置です。matchUserReferenceの中の$(database)という記述は変数:databaseが無いと成立しないわけですが、私はこの一連の文字列 /databases/$(database)/documents をおまじないみたいに思っていてどこに書いてもいんだと思っていたんですが、この$(database)はmatchステートメントの{database}だったんですよ!ほげー!つまり
/databases/$(database)/documents/users/$(uid)
というパスの記述は、
match /databases/{database}/documents {
...
}
の中じゃないと「$(database)?なんのこっちゃ」ということになるのです。関数は何処に書いてもいいって言うから…。いやーちゃんと理解してないとダメですねー、という話でした。