1
votes

I'm facing insufficient permissions for this firestore security check.

service cloud.firestore
{
  match /databases/{database}/documents
  {
    match /events/{eventID}
    {
      allow read:
        if get(/databases/$(database)/documents/events/$(eventID)/authorizations/$(request.auth.uid)).data.EVENT_READ == true;
    }
  }
}

the get document is hardcoded in the firestore database and the simulator returns true but for the actual query returns insufficient privileges.

I tested and moved the authorizations subcollection to the same level as users collection and it works. Am i missing out anything?

Additional testing: Reading the document directly does not result in insufficient privileges. I'm testing to see if it's an issue with listing but to my knowledge read should cover both get and list in firestore security rules.

Update: Listing seems to be the issue here. I tried to list the entire collection with only one document and it results in the insufficient privileges.

Works:

this.angularFirestore.collection('events').doc(eventID).valueChanges();

Doesn't work (updated):

this.angularFirestore.collection('events', query => query.where('admins', 'array-contains', auth.uid)).valueChanges()

My firestore database:

/events/event1_id
- field 1: some string
- field 2: some string
- admins: array of uid strings
    /authorizations/<uid>  #uid for $(request.auth.uid)
    - EVENT_READ: true

Update 2: Updated the doesn't work query string which I tried out. It is intriguing that if i move the /authorizations sub collection out to be the same level as /events collections, the query will not fail.

1
"but for the actual returns insufficient privileges" - please edit the question to show what exactly you're doing that doesn't work the way you expect. What query are you making that should be allowed? - Doug Stevenson

1 Answers

1
votes

Your first query works because it's accessing the events collection with a specific document. That specific document meets the rules criteria, because you've arranged for the get() to allow it.

Your second query doesn't work because it's attempting to get all of the documents in events collection. Your rule does not specifically allow that. It looks like you expect your rule to filter out the events that aren't allowed access based on the contents an unknown number of other documents. You need to be aware that security rules are not filters. Please click through to the documentation and read that section. The client must only request documents that are known to be readable according to rules. It can't depend on rules to filter documents that are not allowed.

If you want to be able to query for all events that the current user has access to, your current database structure will not work. You will need to put all the relevant information in the events collection itself. This means you should consider something like putting the UID of each user that's allowed to read the event in the document itself, then filter on that field. Or have some other collection that you can query in this way.