0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Swift Firestore Missing or insufficient permissions.

Posted at

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の理解度も低い状態のため、間違えた認識や分かりずらい内容になっているかもしれないですが自分用のメモを兼ねて書いてみました。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?