1

I am trying to set rules in Firestore to allow a user access to a document only if a property in the document has a value contained in a list of strings. The list of strings is contained in the additional claims of the Firebase token generated by our python backend.

service cloud.firestore {
  match /databases/{database}/documents {
    match /myList/{itemId} {
        allow read: if resource.data.location_id in request.auth.token.locations
    }
  }
}

However, performing a query still returns all documents instead of only the ones where location_id is in the list we put in additional claims. I am not sure if this is related to the bug mentioned in this post or if I have the syntax wrong in my Firestore rules.

My firestore structure looks like myList/{itemId}/(item properties here, including location_id property which looks like location_id: "7")

Here is the documentation I am referencing to try to implement this rule.

Also, according to documentation,

There are two operations for reads and queries in Cloud Firestore: get and list. These correspond to the get() and where().get() (query), methods in the client libraries. For your convenience, the read operation allows both of these.

so specifying read should cover both these cases. I also used https://jwt.io/ to decode my firebase token to ensure the claims are being added correctly and it indeed shows inside my token

"claims": {
    "locations": [
      "6"
    ]
  },

Edit: I have tried hard coding a single value like follows but I can't even get that to work, and it is still returning all documents.

service cloud.firestore {
  match /databases/{database}/documents {
    match /myList/{itemId} {
        allow read: if resource.data.location_id == '6'
    }
  }
}
wizloc
  • 2,202
  • 4
  • 28
  • 54

1 Answers1

0

The short answer is that in ['foo', 'bar'] is results in an implicit OR of conditions, which isn't currently supported as a query constraint.

At present you'll have to write a rule that makes this OR explicit:

// works fine for single gets
allow get: if resource.data.itemId in ['foo', 'bar']
// need to expand this for queries
allow list: if resource.data.itemId == 'foo' || resource.data.itemId == 'bar'
Mike McDonald
  • 15,609
  • 2
  • 46
  • 49
  • so `service cloud.firestore { match /databases/{database}/documents { match /myList/{itemId} { allow get: if resource.data.itemId in ['7'] allow list: if resource.data.itemId == '7' || resource.data.itemId == '7' } } }`? – wizloc Nov 02 '17 at 13:04
  • If you only have a single item, you don't need to do `in ['7']` you can just use `== '7'`. Note that you'll want to ensure that you want `'7'` (the string) vs `7` (the number). – Mike McDonald Nov 04 '17 at 15:49