17

Can I use the equivalent of array_contains in Firebase Security Rules?

I have an Event class (corresponding to Event documents in the events collection). Each document has a subscribers list/array that contains the UIDs of all the users who should be able to query for this event:

{
    .
    "subscribers" : ["uidA", "uidB", "uidC"],
    .

}

More explicitly, a user should be able to run the query:

db().collection("events").whereArrayContains("subscribers", "uidC");

How do I write this security rule?

I tried:

match/events/{eventId} {
    allow list: if request.auth.uid in resource.data.subscribers;
}

and the simulator tells me that access would be denied.

Using functions like this also reports access denied:

function isSubscriber() {
    return resource.data.subscribers.includes(request.auth.uid);
}

match/events/{eventId} {
    allow list: if isSubscriber();
}
Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
markvgti
  • 4,321
  • 7
  • 40
  • 62
  • Did you try any of this outside the console emulator? It's been known to have some problems. – Doug Stevenson Oct 16 '18 at 05:57
  • 1
    It seems to me that the console can't accurately simulate a list type rule, since it only applies to queries, and you can't do queries in the simulator. Have you tried this with an actual query in a client app, not in the simulator? – Doug Stevenson Oct 16 '18 at 06:10
  • Haven't tried it outside the console. It doesn't show an error with the syntax, but since I haven't found a similar example in the docs, I don't know if it'll work. I'll give it a shot. – markvgti Oct 16 '18 at 06:36
  • You were right (thanks!), the rule `if request.auth.uid in resource.data.subscribers;` actually does work in practice. However, the `in` operator is undocumented (found it through another SO question). Anywhere I can report this? – markvgti Oct 16 '18 at 07:03
  • The `in` operator is documented, as are all list operations: https://firebase.google.com/docs/reference/rules/rules.List – Doug Stevenson Oct 16 '18 at 16:29
  • That's for Firebase. Are Firebase and Firestore Security Rules the same? – markvgti Oct 16 '18 at 17:22

1 Answers1

46

Thanks to the advice of @DougStevenson, I used the rule:

match/events/{eventId} {
    allow list: if request.auth.uid in resource.data.subscribers;
}

and then had my Android dev actually try a query from his device, and it worked!

Don't blindly trust the Firestore Security Rules' simulator, it can differ from reality!!! The code for the simulator is probably different than the code that is deployed for actually evaluating rules in production, so the results may differ slightly.

Firebase security rules documentation: https://firebase.google.com/docs/reference/rules/rules.List (apparently it also applies to Firestore).

markvgti
  • 4,321
  • 7
  • 40
  • 62
  • Please feel free to file a bug report when something like this happens: http://firebase.google.com/support/contact/bugs-features – Doug Stevenson Oct 16 '18 at 16:30