LoginSignup
2
3

More than 3 years have passed since last update.

Firestoreに保存されたデータを端末によって分ける方法

Posted at

はじめに

タイトルにも書いてある通り、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に保存されたデータの安全性が保たれます。

おわりに

最後のメソッドのコードはちゃんと動きますが、もしかすると
もっと良い書き方があるかもしれません。

詳しい方はコメントでアドバイスして頂けると有り難いです。

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3