#はじめに
タイトルにも書いてある通り、Firestoreに保存されたデータを端末によって分ける方法です。
導入方法などは割愛します。
Firestore独自の用語が沢山出てくるのでよく分からない方は、こちらを読んでみて下さい。
Cloud Firestoreについてまとめる
後はセキュリティルールについても。
Firestoreのセキュリティルールとは
まあ、自分のQiitaの記事を紹介しているのになんですが、やはり公式ドキュメントが一番良きです。
Cloud Firestore | Firebase
#書こうと思った理由
現在、開発しているアプリにて、お気に入り登録機能を追加しようと考えており
Firestoreで、そのデータを管理しようと思ったのが事の発端です。
データの読み書きはすんなり出来たものの、そのデータをユーザーの端末によって分けるというのがどうしても出来ませんでした。
どうにかメンターに相談したり自分なりに試行錯誤したのち、どうにか出来たので備忘録としてまとめようと思いました。
#やり方
###1.Firebase Authenticationの導入
まずは、Firebase Authenticationをアプリに導入して下さい。
そして今回はメールアドレス/パスワード
を使用したユーザー認証を導入したていで書きます。
(他の認証方法をあまり使ったことがない...)
導入して実際にAuthアカウントを作成すると、それぞれのユーザーに対してuid
というユーザーIDが付与されます。
これはユーザーによってバラバラであり、重複していません。
このuid
を使ってFirestoreに保存されたデータを端末ごとに分けていきます。
###2.FirestoreのドキュメントIDをuidで登録する
FirestoreのドキュメントIDは通常、追加と同時にランダムなID
が付与されます。
なのでこのドキュメントIDを先ほどのuid
で登録することによってユーザーごとにデータを分けることが出来ます。
例えば、食べ物の名前をFirestoreに保存しようとします。
// Firestoreにデータを追加するメソッド
func addFoodData(userId: String, foodName: String, complition: ((Error?) -> Void)? = nil) {
Firestore.Firestore().collection("users").document(userId).collection("food").addDocument(data: [
"Name": foodName
]) { (error) in
if let error = error {
complition?(error)
return
}
}
}
メソッドのuserId
引数から、uid
を取得できるようにして
.document(userId)
からFirestoreのドキュメントIDをuid
で登録しました。
これでFirestoreにデータを保存するたびに、uid(ドキュメントID)からユーザーを分けることができ、端末ごとにデータを分けることができます
。
上記のコードが保存されたら、こんな感じでFirestoreにて管理されます↓
🗂・・・コレクション、サブコレクション
📄・・・ドキュメント
ユーザーAのuid・・・123
ユーザーBのuid・・・456
・ユーザーAの場合
🗂users
📄123
🗂food
📄自動生成したID
Name: "Apple"
・ユーザーBの場合
🗂users
📄456
🗂food
📄自動生成したID
Name: "Sushi"
#ただこの方法でもいいが・・・
Firestoreのセキュリティルールを書くときに少しだけ問題があります。
まずは公式が推奨しているセキュリティルールを見てください。
安全でないルールを修正する | Firebase
見ていただけると分かるようにFirebase Authenticationと連携したセキュリティルールは、認証済みユーザーが存在していてFirestoreに保存してあるuidとAuthアカウントのuidが一致していればデータの読み書きを許す
という感じだと思います。
認証済みユーザーが存在していて
の部分は、Firebase Authenticationを導入していればOKですがFirestoreに保存してあるuidとAuthアカウントのuidが一致していれば
の部分は現状、満たせていません。
なぜなら、あくまで今までの方法はドキュメントIDをuid
で登録しているだけでFirestoreにデータとして保存している訳ではないから
です。
#ではどうすればいいのか?
解決方法は簡単で、Firestoreにuid
を保存すれば解決します。
先ほどのFirestoreにデータを追加するメソッド
を少しだけ改修しましょう。
// Firestoreにデータを追加するメソッド
func addFoodData(userId: String, foodName: String, complition: ((Error?) -> Void)? = nil) {
// uidをここで保存する
Firestore.Firestore().collection("users").document(userId).setData([
"userId": userId
]) { (error) in
if let error = error {
complition?(error)
return
}
}
Firestore.Firestore().collection("users").document(userId).collection("food").addDocument(data: [
"Name": foodName
]) { (error) in
if let error = error {
complition?(error)
return
}
}
}
上記のコードがFirestoreに保存されたら、こんな感じ↓
🗂・・・コレクション、サブコレクション
📄・・・ドキュメント
ユーザーAのuid・・・123
ユーザーBのuid・・・456
・ユーザーAの場合
🗂users
📄123
userId: 123
🗂food
📄自動生成したID
Name: "Apple"
・ユーザーBの場合
🗂users
📄456
userId: 456
🗂food
📄自動生成したID
Name: "Sushi"
これでやっと、セキュリティルール内でAuthアカウントのuid
とFirestoreに保存したuserId
を比較することができますね。
セキュリティルールも設定していきましょう。
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
function isAuth(userId) {
return request.auth != null && userId == request.auth.uid;
}
match /users/{userId}/food/{document} {
allow write, read: if isAuth(userId);
}
}
}
これで、Firestoreに保存されたデータの安全性が保たれます。
#おわりに
最後のメソッドのコードはちゃんと動きますが、もしかすると
もっと良い書き方があるかもしれません。
詳しい方はコメントでアドバイスして頂けると有り難いです。