How to validate Firestore LIST request in Firestore Security Rules when query filter includes array value?

Viewed 40

I have Firestore project setup with standard ACL permissions.

The user collection has docs with roles array [ ...roles ] that defines which roles that user is in

user.roles = [ role1, role2 ... ]

Each document in other collections contains an ACL array that contains a list of roles allowed to access that document

doc.acl = [ role2, role3, ... ]

Because Firestore rules are not filters, we must pass a list of the users roles to the query when requesting docs in a collection. No problem ....

db
  .collection('docs')
  .where('acl', 'array-contains-any', user.roles) // user.roles = ['role1', 'role2']

Based on this, I should get a result-set that includes only docs that the user is allowed to read.

However, enforcing the security seems to be not possible!

In theory, I should be able to setup a rule like this:

function userHasPermission () {
  // here we should check the contents of the *where* query filter, accessible at *resource.data*
  let filter = debug(resource.data.acl);
  // ... but now we have a problem, see below
}

match /docs/{id} {
  allow list: if userHasPermission();
}

In #userHasPermission, we must get the value of the resource.data.acl and if we look at the debug statement, we see the following:

map_value {
  fields {
    key: "acl"
    value {
      constraint_value {
        simple_constraints {
          comparator: LIST_CONTAINS
          value {
            string_value: "role1"
          }
        }
      }
    }
  }
}

I can see a map_value. So from this map I can see my key acl.

But if I look deeper into this object, I can see that value of the resource.data.acl is NOT an array, it's a constraint_value of type simple_constraints ... therefore I cannot use the IN keyword, or the LIST methods hasAny and hasAll. And worse, only the first role I passed shows as visible in the debugging statement.

Also it seems not possible to extract the value from the simple_constrains/constraint_value.

Furthermore, only the FIRST value in my array shows up in the constraint!

So it appears that simple ACL strategies are NOT in fact possible with Firestore Security Rules.

Can anyone share an approach that works or a workaround or comment further? There just seems to be no way to extract the LIST (array) from the value sent in the query and therefore I cannot validate the LIST query and therefore cannot implement BASIC ACL permissions!

PS - from the emulator console, here is what shows up in resource tab on the right side: (* pls ignore the fact that in this screen the query key is _accounts and not acl)

enter image description here

0 Answers
Related