3

I have a program performing a batch write on firestore to a collection.

I am trying to write the document only if is doesn't exists in the collection and skip without modifying anything if it does.

the security rule is as below:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /collection/{id} {
      allow create,delete: if request.auth.uid != null;
    }
  }
} 

While testing on the test tool, it working as expected. I am only allowed to create and delete documents in this collection. However when running from the program, the batch write is able to modify the document field (stamp in this case) if is already exists.

The code is as follows:

var batch = firestore.batch();
var docRef= firestore.collection("collection").doc(data.id);

batch.set(
    docRef,{
        id: data.id,
        stamp: new Date(),
    },
);

What am I missing, or doing wrong?

Tarounen
  • 1,119
  • 3
  • 14
  • 25
  • 2
    Where do you run this code? If this is using the regular JavaScript client it should not be possible to update the document. If it's run with the Node.js Admin SDK, it is running with elevated privileges that bypass the security rules. – Frank van Puffelen Jun 22 '20 at 14:49
  • i added firebase-admin to my Node.js project. I didn't thought of that.. Thanks – Tarounen Jun 22 '20 at 14:53

2 Answers2

2

You can check if the document exists first and then write only if it doesnt

docRef.get().then(doc => {
    if (!doc.exists) {
        batch.set(docRef, {
            id: data.id,
            stamp: new Date(),
        });
    }
});
Abito Prakash
  • 4,368
  • 2
  • 13
  • 26
  • wouldn't this add to much overhead? I will have a list of more than 500 documents. Getting each doc to perform the check will increase the processing time and also unnecessary reads operation to firestore? – Tarounen Jun 22 '20 at 11:26
1

From your comments it seems you're running this code in a Node.js environment using the Admin SDK. When you use the Admin SDK it accesses Firebase with elevated, administrative privileges and bypasses the security rules that you've specified.

With that knowledge it seems that the behavior you have is working as intended.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • Thank you removing the admin-sdk and using an authenticated user is now applying the security rules. However i am stuck with a whole new problem, if the rule is trigger in the middle of a batch, the program just stops ... could there be a way to continue the batch in case this happens? – Tarounen Jun 22 '20 at 17:36
  • On the new problem: that is precisely what a batch operation is meant to do, a write operation that commits or aborts atomically. If you don't want that, you should just use separate writes. If you do those on parallel, that will also be faster than using a batch: https://stackoverflow.com/questions/58897274/what-is-the-fastest-way-to-write-a-lot-of-documents-to-firestore – Frank van Puffelen Jun 22 '20 at 20:14
  • Yes, sorry i was too concentrated on trying to find another way. Thanks for the second link, i thought batch was faster. .. will give it a try. – Tarounen Jun 22 '20 at 20:26