Swift Firestoreからデータ取得をする際にエラーになった
◯ エラー内容
Missing or insufficient permissions.
英語読めないけどエラーに permissions
って単語が入ってるのでセキュリティルールの設定が原因だろうとは思ったのですが、ルール設定についてがよく分からないのでとりあえず手探りしてみた。
◯ Firestoreのデータ構造
コレクション
- teams
ドキュメント
- xxx-xxx-xxx-xxx (teamId)
フィールド
- name
- ownerId
- sharedUserIds
◯ Firestoreからの取得コード
Firestore.firestore()
.collection("teams")
.getDocuments { snapshot, error in
}
◯ 試したセキュリティルール
試したこと1
条件なし
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /teams {
allow read, write: if true;
}
}
}
これはエラーになりました。
試したこと2
条件なし
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /teams/{teamId} {
allow read, write: if true;
}
}
}
これは成功しました。
なので試したこと1ではコレクションに対してセキュリティルールの設定をしているが、ドキュメントの取得をしようとしているので /teams
に対してセキュリティルールを設定しても意味がないということなのかなと思いました。
とりあえず /teams/{teamId}
へのセキュリティルールの設定で管理できることが分かったので実際にセキュリティルールを設定していきます。
試したこと3
ログインしていれば取得できるルール
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /teams/{teamId} {
allow read, write: if request.auth.uid != null;
}
}
}
これも成功した。
試したこと4
データを取得しようとしたユーザーの uid
が teamデータの ownerId
と同じ場合
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /teams/{teamId} {
allow read, write: if request.auth.uid == resource.data.ownerId;
}
}
}
これは失敗した。
は?って思ってログインしているユーザーの uid
と Firestoreに保存している ownerId
を確認したが一致している。
ということでFirestoreのドキュメントを調べてたらこちらに記載がありました。
https://firebase.google.com/docs/firestore/security/rules-conditions?hl=ja#rules_are_not_filters
◯ 上記のリンクの記事参照
db.collection("cities").get()
.then(function(querySnapshot) {
querySnapshot.forEach(function(doc) {
console.log(doc.id, " => ", doc.data());
});
});
db.collection("cities").where("visibility", "==", "public").get()
.then(function(querySnapshot) {
querySnapshot.forEach(function(doc) {
console.log(doc.id, " => ", doc.data());
});
});
参考コードにSwift言語での記載がなかったためweb系言語を載せていますが、
where("visibility", "==", "public")
のようにセキュリティルールに沿った条件のフィルターをかけて取得する必要がらしい。
セキュリティルールを設定すればアプリでフィルターをかけずにセキュリティルールの条件に合ったものだけが取得できるようになると思ってましたが違ったみたいです。
◯ 結論
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /teams/{teamId} {
allow read, write: if request.auth.uid == resource.data.ownerId;
}
}
}
上記のセキュリティルールで設定した場合は、
Firestore.firestore()
.collection("teams")
.whereField("ownerId", isEqualTo: userId)
.getDocuments { snapshot, error in
}
のように .whereField("ownerId", isEqualTo: userId)
を設定して、
フィールドの ownerId
がログインユーザーの userId
を持つドキュメントを取得するようにすると成功する。
◯ まとめ
初めて記事の投稿をしてFirestoreの理解度も低い状態のため、間違えた認識や分かりずらい内容になっているかもしれないですが自分用のメモを兼ねて書いてみました。