1
votes

I have the following security rule set up in Firestore:

match /ads/{adId} {
 allow read: if true;
 allow write: if (request.auth.uid == request.resource.data.ownerId) ||
              (request.auth != null &&
               request.resource.data.size() == 1 &&
               request.resource.data.keys().hasAll(['markedFavoriteBy'])); 
}

The owner of the document has all write permissions but other users can only write in one field - which is called 'markedFavoriteBy'. It seems to work in the Firestore simulator but not in Xcode (with iPhone simulator). Important to note that the path does not go down to the document field - just to the document. I know that it is not possible to attach a security rule to a single field. However, with this workaround it should still work.

The iOS client code to update the field is the following:

let adRef  =  Firestore.firestore().collection("ads").document(ad.key!)
let value: FieldValue = ad.isFavorite ? FieldValue.arrayUnion([uid]) : FieldValue.arrayRemove([uid])
adRef.updateData([DatabaseKeys.markedFavoriteBy : value]) { (error) in
            if let error  = error {
                print(error.localizedDescription)
            }
        }

The error printed to the console is of course: "Missing or insufficient permissions."

I can't find an error in the code - is this a bug that is somehow related to the very recent iOS Firestore SDK update? the functions arrayUnion and arrayRemove have been added only in that recent update.

Sanity check: I have changed the write rule to allow write: if true; Result: The array 'markedFavoriteBy' can be changed without any problem.

thanks for any hints in the right direction.

1

1 Answers

0
votes

I'm not able to reproduce the entire scenario as I'm not sure of the actual contents of your database. However, what I suspect is the problem is that it doesn't grant permission because request.resource.data represents the new version of the entire document (which will be stored after the update is approved).

You probably want to use request.writeFields doc

Bear in mind that request.writeFields is not available in the simulator.