Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Collection Group permissions for Firestore

I have these rules:

match /suuntoAppAccessTokens/{userName} {
      allow create: if request.auth.uid != null && request.auth.token.firebase.sign_in_provider != 'anonymous';
      match /tokens/{userID} {
        allow read, write, create, update, delete: if request.auth.uid == userID && request.auth.token.firebase.sign_in_provider != 'anonymous';
      }
    }

match /{path=**}/tokens/{userID} {
            allow read, write, create, update, delete: if request.auth.uid == userID;
    }

That means that for the path /suuntoAppAccessTokens/dimitrioskanellopoulos/tokens/{userID} the current user should have access.

However, when I query the collection group like so:

return this.afs.collectionGroup('tokens').snapshotChanges();

I get a permission error.

Getting directly the document under tokes/{userID} works as expected.

What can I do so that the current user can run a collectionGroup query and get the items he is permitted to get based on my rules?

like image 903
Jimmy Kane Avatar asked May 26 '19 12:05

Jimmy Kane


People also ask

What is Collection group firestore?

A Collection Group Query allows you to join all the collections that share a similar name, in this case comments , and query across them uniformly. app.js. import * as firebase from 'firebase/app'; const db = firebase. firestore(); const query = db.

How many documents can a collection hold firestore?

10 for single-document requests and query requests. 20 for multi-document reads, transactions, and batched writes. The previous limit of 10 also applies to each operation.

How do I get a collection list on firestore?

js admin clients have listCollections() on Firestore to get that list. Or, if you're looking for subcollections nested under a document, use DocumentReference. listCollections(). If you want to get a list on any platform, you should maintain that list yourself in a known collection inside a known document id.

What is a Subcollection in firestore?

A subcollection is a collection associated with a specific document. Note: You can query across subcollections with the same collection ID by using Collection Group Queries. You can create a subcollection called messages for every room document in your rooms collection: collections_bookmark rooms. class roomA.


1 Answers

Your rule is expecting that the security rule will filter all the documents from all of the tokens collection so that only the current user's documents will be read. This is not possible with security rules. Security rules are not filters. From the documentation:

When writing queries to retrieve documents, keep in mind that security rules are not filters—queries are all or nothing. To save you time and resources, Cloud Firestore evaluates a query against its potential result set instead of the actual field values for all of your documents. If a query could potentially return documents that the client does not have permission to read, the entire request fails.

You will need to change your query to that the client is only requesting documents that are fully expected to be readable by the current user. Unfortunately, it's not possible for me tell if this is possible with your current schema. The ID of the document {userId} can't be used in a collection group query to filter the documents. So, both you must ensure that both of the following criteria are met:

  • You will need some field in the document that you can filter on to get this job done.
  • You will need to adjust your security rule to match exactly what the client is asking for.

I suggest storing the uid of the user in the document with the token, the same as {userId} in the rule. You can query it like this:

collectionGroup('tokens').where("uid", "==", uid)

Be sure that the client passes in the uid correctly

Also, you will need to make sure that the rule is granting access by the exact same criteria:

match /{path=**}/tokens/{userID} {
  allow read, write, create, update, delete:
    if request.auth.uid == resource.data.uid;
}

This will only allow access to the document if its uid field is the same as the auth uid, which is exactly what the client is asking for.

like image 53
Doug Stevenson Avatar answered Oct 30 '22 14:10

Doug Stevenson