【firebase】【firestore】arrayやmapにreferenceを入れてrulesで縛ってはいけない
というか、SubCollection使えよ、っていう話
nuxt.js + firebaseでPWAアプリを作成しようとしています。
機能の一つとして、友達登録的なことが出来るようにしたくて、firestoreのユーザデータの構造をこんな感じに考えていました。(超簡略)
users
- document: uid0
- name: "山田"
- friends (array)
- [0] users/uid1 (伊藤さんへのreference)
- [1] users/uid2 (富田さんへのreference)
- document: uid1
- name: "伊藤"
- friends
- [0] users/uid0
- [1] users/uid2
- document: uid2
- name: "富田"
- friends
- [0] users/uid0
- [1] users/uid1
友達登録すると、firendsに参照が増えていくイメージ。
functionsで、友達状態は相互関係になるように管理します。
(山田さんのfriendsに伊藤さんがいて、伊藤さんのfriendsに山田さんがいない、という状態にはならない)
セキュリティを考えて、rulesを設定します。
・ログイン者自身のusers、もしくはログイン者がfriendsに含まれるusersは取得できる
・書き込みはログイン者自身のusersだけ
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId} {
allow read: if request.auth.uid != null && (request.auth.uid == userId || /databases/$(database)/documents/users/$(request.auth.uid) in resource.data.friends);
allow write: if request.auth.uid != null && request.auth.uid == userId;
}
}
}
まぁこんなところかな。
「ログイン者がfriendsに含まれるusers」が取得できないと友達一覧とか作れないんでね。
この状態で、ユーザ2名までならうまく動いたんですよ。
上のデータ例でいうと、山田さんと伊藤さんの二人だけで友だちになってたら大丈夫。
ここに富田さんが山田さん・伊藤さん両方と友達登録して、3人全員友達ならそれもOK。
そこから、一人だけ友達状態を解除して、たとえば
山田さんと伊藤さんは友達。
山田さんと富田さんは友達。
伊藤さんと富田さんは友達じゃない。
みたいな状態で、伊藤さんでログインした瞬間に、エラー。
しかもrulesでエラー。なぜ、、、さっきまでうまく行ってたやん。
結論をいいますと、referenceを含むSnapshotを取得した瞬間、データとしてはその参照の先にある参照のデータまで取得してきちゃう様子。
つまり、
1.伊藤さんでログイン
2.自分のfriendsに含まれるreferenceである山田さんのusersを取得
3.山田さんのfriendsのreferenceも自動的に取得しようとする
4.富田さんのデータも取得しようとして、富田さんのfriendsには自分が含まれないから Missing or insufficient permissions.
ということになる。
ただ、参照の先に自分の参照があったら、延々再帰的にデータ取り続けて落ちそうだけど、そうはならない。
参照の先の参照の先の参照の先の・・・・というのが3段階くらいで止まる。
ということは、取得する深度が決まっている。ならば、深度を指定できるんじゃないかなぁ、、、と思うんですが、見つけられませんでした。
(誰か知ってたら教えてください)
なので、こういう構造を作りたかったら、friendsは素直にSubCollectionにしましょう。
それか、stringでuidを入れたarrayにするとか。
反省
この記事が気に入ったらサポートをしてみませんか?