Search code examples
firebasegoogle-cloud-firestorefirebase-security

Firestore Security Rules Error: Property id is undefined on object when using get() function


Error: Error: simulator.rules line [13], column [27]. Property id is undefined on object.

Security Rules:

    rules_version = '2';
    service cloud.firestore {
      match /databases/{database}/documents {
    
        function isBusinessOwner() {
          let businessDocId = get(/databases/$(database)/documents/users/$(request.auth.uid)).data.managedBusinesses[0].id;
          let businessTeamUserId = get(/databases/$(database)/documents/businesses/$(businessDocId)).data.team[0].id;
          return request.auth.uid == businessTeamUserId;
        }

    match /businesses/{businessDocId} {
      allow read, write: if true;

      // Sub-collection:
      match /businessCustomerQueue/{queuedCustomerDocId} {
        allow read, write: if isBusinessOwner();
      }
   }
    
      }
    }

Code explanation:

  1. users/$(request.auth.uid)).data.managedBusinesses[0].id: User document contains a managedBusinesses array field which it's first index [0] is a Firestore reference type. Then trying to access the id property on that reference type.
  2. businesses/$(businessDocId)).data.team[0].id: Business document contains a team array field which it's first index [0] is a Firestore reference type. Then trying to access the id property on that reference type.

The first get() function call failed in the isBusinessOwner() function call.

The Rules Playground get() function call relevant portion of the data that was returned is:

"managedBusinesses": [
"/databases/%28default%29/documents/businesses/TMCVfCRemRlaUdQjumrn"
]

The first element of the managedBusinesses array appears to be a string, however, the error message is stating it's an object and the actual field data type in Firestore is a reference type to a document.

Why am I getting undefined when trying to access the id property on this reference type in Firebase security rules.

Thank you.


Solution

  • Working Solution:

    function isBusinessOwner() {
      let businessDocPath =  get(/databases/$(database)/documents/users/$(request.auth.uid)).data.managedBusinesses[0];
      let businessOwnerDocPath = get(/$(businessDocPath)).data.team[0];
      return /databases/$(database)/documents/users/$(request.auth.uid) == businessOwnerDocPath;
    }
    

    When dealing with Reference types in Firestore Security Rules, the reference type is simply a string type and has no properties to access. Therefore, you need to compare a path such as /databases/$(database)/documents/users/$(request.auth.uid) to the reference type. This operation is ultimately a string comparison.