Firestore Security Rules: How to create a rule that checks a list of objects?

Viewed 128

Imagine a field called specialtyList which is a list of specialties that stores the specialties of a doctor, each doctor is a user of the App

doctors is the collection

doctorId is the documentID and the ID used on Firebase Authentication

The document contains the specialtyList field, which is a list of objects, like:

/doctors/{doctorId}

{
   fullName: "...",
   specialtyList: [
      {
         specialtyId: 1,
         isApproved: false
      },
      {
         specialtyId: 2,
         isApproved: false
      },
      {
         specialtyId: 3,
         isApproved: false
      }
   ]
}

A doctor can add his specialty in the list, but he can't change the isApproved value to true, only users with the "approvalManager" role on Firebase Authentication can do that, so the rules would be something like

match /doctors/{doctorId} {
      allow read: if request.auth.token.approvalManager == true ||
          request.auth.uid == doctorId;
    
      //problem:
      allow write: if request.auth.token.approvalManager == true || (
          request.auth.uid == doctorId &&
          request.resource.data.diff(resource.data)
                .changedKeys().hasAny([ "specialtyList" ]) == false
      );
}

the problem with my solution is that the doctor wouldn't be able to add a specialty even if he correctly sets the isApproved value to false

So my question is, how can I create a security rule where:

  • The doctor can add a object in specialtyList

  • The doctor cannot add a object with the isApproved value being true

Thanks!

1 Answers

Here is your write rule:

allow write: if request.auth.token.approvalManager == true || (
          request.auth.uid == doctorId &&
          (request.resource.data.specialtyList[0].isApproved == false)
      );

This rule is good if the doctor update only one specialty per change, since the index in the array is hardcoded to zero.

BTW, to add an object, you need to use the set function with the option of merge so it only update the specialtyList and not overwrite it.

Related