3

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 Answer 1

3

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;
            }
          }
        }

    }
  }
}
Sign up to request clarification or add additional context in comments.

7 Comments

Worked for me. I read that the get() will cost you a read each time. Do you still use this method or is there a better way in the new security rules?
Nope stil using this atm
Just to be clear to others here: You dont get charged for get stuff when done on the DB via a rule
@JimmyKane No, you definitely do in Firestore. Read firebase.google.com/docs/firestore/security/rules-conditions : "Using these functions executes a read operation in your database, which means you will be billed for reading documents even if your rules reject the request. See Cloud Firestore Pricing for more specific billing information."
@JimmyKane: that answer relates to Firebase Realtime Database. Firestore does charge for a get() in a security rule.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.