Search code examples
firebasegoogle-cloud-firestorefirebase-security

Firestore security rules: evaluating incoming requests against other documents in the database


I am new to firestore and its security rules so apologies if this sounds stupid. I have 3 collections, data, roles and trainingRequests. In roles I am storing users id along with their name and role as shown in the image attached. What I wanted to do was to give access of read and write only if the role of the user is "external". So, for that purpose the rule I wrote is as follows:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
  
    match /trainingRequests/{tId} {
        allow read, write: if get(/databases/$(database)/documents/roles).data[request.auth.uid].role == "external"
    }
    
  }
}

But this is not working at all. So, I wanted to know what I am doing wrong and what's the right way to write the rule for this purpose. I know that custom claims is a better approach but I still want to try this out.

enter image description here


Solution

  • You need to pass a document path to the get() method.

    With

    get(/databases/$(database)/documents/roles)
    

    you are actually passing the roles collection path.


    The following should do the trick:

    rules_version = '2';
    service cloud.firestore {
      match /databases/{database}/documents {
      
        match /trainingRequests/{tId} {
            allow read, write: if get(/databases/$(database)/documents/roles/$(request.auth.uid)).data.role == "external"
        }
        
      }
    }
    

    The get() method returns a rules.firestore.Resource on which you call the data property which returns a map of the document data.

    You'll find more details and examples in the doc.