Firestore rules: How to allow nested document read based on parent property

Viewed 2474

I have my firstore database with collections and documents structured like so:

  • Users -> Events -> Activities -> Streams

I want everyone to be able to read a document inside the Events collection and it's subcollection documment (activities + Streams) if the Events colleciton document has a property eg visibility to the string "public"

So if a document on Events collection has a field visibility to public any user should be able to read that document and it's subcollections.

So far I managed to make only the Document in the Events collection readable via:

   service cloud.firestore {
  match /databases/{database}/documents {
    // Make sure the uid of the requesting user matches name of the user
    // document. The wildcard expression {userId} makes the userId variable
    // available in rules.
    match /users/{userID} {
      allow read, update, delete: if request.auth.uid == userID;
      allow create: if request.auth.uid != null;
        match /events/{eventID} {
          allow read: if resource.data.visibility == 'public';
          allow read, write, create, update, delete: if request.auth.uid == userID;
          match /activities/{activitytID} {
            allow read, write, create, update, delete: if request.auth.uid == userID;
            match /streams/{streamID} {
              allow read, write, create, update, delete: if request.auth.uid == userID;
            }
          }
        }

    }
  }
}

How can I make when that visibility of one events document is public also the nested collections of activities and streams be also readable ?

1 Answers

I solved this via:

Adding a function to get the event data

 function eventData() {
            return get(/databases/$(database)/documents/users/$(userID)/events/$(eventID)).data
          }

Complete rules:

service cloud.firestore {
  match /databases/{database}/documents {
    // Make sure the uid of the requesting user matches name of the user
    // document. The wildcard expression {userId} makes the userId variable
    // available in rules.
    match /users/{userID} {
      allow read, update, delete: if request.auth.uid == userID;
      allow create: if request.auth.uid != null;
        match /events/{eventID} {
          allow read: if resource.data.visibility == 'public';
          allow read, write, create, update, delete: if request.auth.uid == userID;
          function eventData() {
            return get(/databases/$(database)/documents/users/$(userID)/events/$(eventID)).data
          }
          match /activities/{activityID} {
            allow read: if eventData().visibility == 'public'
            allow read, write, create, update, delete: if request.auth.uid == userID;
            match /streams/{streamID} {
              allow read: if eventData().visibility == 'public'
              allow read, write, create, update, delete: if request.auth.uid == userID;
            }
          }
        }

    }
  }
}
Related