skip to Main Content

Within firestore security rules, is there a way to get direct access to the value of a resource.data for a list query? More specifically, for array-contains. I’d like to use the value of the list query and do some transformations with it inside the rules before evaluating the result.

Example:

Let’s assume that admin1 is the currently loggedin user.

I have a list of resources with the following property:

someResource{
    sharedWithIds: ["client1", "client2", ..., "admin1", "admin2", ..., "admin1_client1", ...] //basically a manual index
}

And a query:

getDocs(query(collection, where("sharedWithIds", "array-contains", "admin1_client1"))

Security rules must only grant access if the current user is listed in sharedWithIds

So I was hoping I could do the following in the rules:

match /resources/{resourceId}{
    allow list: if request.auth.uid in resource.data.sharedWithIds.split(“_”)
}

Here I assume that resource.data.sharedWithIds equals to "admin1_client1", which is the value of the query. But it didn’t work – it just gives me false all the time.

In fact, the rule’s debug gives the following output for resource.data.sharedWithIds:

constraint_value {
  simple_constraints {
    comparator: LIST_CONTAINS
    value {
      string_value: "admin1_client1"
    }
  }
}

I wasn’t able to find any documentation on this structure, but apparently I can perform hasAny, but I can’t figure out how to get the underlying value of "admin1_client1".

Any suggestions? Or is it a dead end?

2

Answers


  1. Chosen as BEST ANSWER

    After digging through different questions and related comments on SO, it seems like it's not possible to get the value of the array-contains query in the rules. At least not now.

    In the rules for some queries we receive the query's value directly, like for ==. For other queries we only get some internal wrapper object that only exposes a specific method.

    That method only allows to test against the specific action related to the query - in case of array-contains we only have hasAny()

    While that allows to do the specific job defined in the doc, it seems like it enforces unnecessary limitations on what can be done in the rules. As opposite if we could get the value of the query itself, this would allow for more flexible rules.

    For example in case of array-contains, rules could expose the value that user provided in the query or an array like [value] - this would allow to test the query in the same way it works right now, plus it would allow for additional manipulations.

    The current approach of how the rules work unfortunately limits more complex scenarios.

    As a remark, while Frank's answer mentions that there is no way to manipulate the data, that wasn't really my question, so I'm posting my answer to complete it


  2. There is no way in Firestore security rules to manipulate the data.

    The best solution I can think of is to include the separate parts you want to check on the in sharedWithIds too, or add another array field with the split values for this purpose.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search