Search code examples
firebasegoogle-cloud-firestorefirebase-security

Firestore rule to view collection based on document value in another collection not workings as expected


I have a collection in my Firestore called 'Facilitators'. This holds additional information for authenticated users.

I would like to make a rule which states that they can read another collection called 'Kids' if a field in a document in the 'Facilitators' collection is marked as yes.

The documents in the facilitator collection use the authenticated users email as the document id, so I was hoping that the rule would check the document in that collection in which the document ID matches the user email, and then check if a specific field in that document is marked as 'yes'.

If it is marked as 'yes', I would like to give them the permission to read the collection called 'Kids'.

I hope this makes sense, this is the rule I currently have in to achieve this but it is not working as expected:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    
    match /Facilitators/{facilitators} {
        
      function kids() {
        return request.auth.email == resource.data.email && resource.data.BeAHero == "Yes";
      }
      
      function teens() {
        return request.auth.email == resource.data.email && resource.data.YouAreUnstoppable == "Yes";
      }
      
      match /Kids/{kids} {
      allow read: if kids();
      } 
      
      match /Teens/{teens} {
      allow read: if teens();
      } 
      
    }
    
    
  }
}


Solution

  • When you are reading a document in Kids collection, resource.data will contain data of the Kid document and not Facilitator. If you want to read a field from Facilitator document, then you would have to use get() function to read that document's data as shown below:

    function kids() {
      return get(/databases/$(database)/documents/Facilitators/$(request.auth.token.email)).data.BeAHero == "Yes";
    }
    

    Also, to get email of requesting user you must use request.auth.token.email and not just request.auth.email.