How to create firestore security rule with nested get() calls?

Viewed 425

I have the following firestore database (simplified)

groups
  group1
    role=guest
  group2
    role=user
  group3
    role=moderator
users
  user1
    group=group1
  user2
    group=group2
items
  item1
  item2

Let's say I want to only allow users to read /items data. Here's my approach:

service cloud.firestore {
    match /databases/{database}/documents {

            function getUser(id) {
                return get(/databases/$(database)/documents/users/$(id)).data
            }

            function getGroup(id) {
                return get(/databases/$(database)/documents/groups/$(id)).data
            }

            function getRole(id) {
                return get(/databases/$(database)/documents/roles/$(id)).data
            }

            match /items/{document=**} {
                allow read: if getRole(getGroup(getUser(request.auth.id).group).role) == 'user'
            }

    }
}

But it doesn't seem to work. Looks like it is not possible to do nested calls in firestore rules. I tested getGroup() with hardcoded id and it works fine:

allow read: if getGroup('<userGroupId>') == 'user'

This also works:

allow read: if getUser(request.auth.uid).group == '<userGroupId>'

But it fails on this more complex rule:

allow read: if getGroup(getUser(request.auth.uid).group) == 'user'

Is it possible to make it work? Is there another way to do this if not?

0 Answers
Related