2

I was trying to write a rule that if the id of the document doesn't exist, then create a new document. My object is:

Message message = new Message(userId, title, messageBody, timestamp);

and I'm using WriteBatch to create a new document and updating the same:

mWriteBatch.set(mMessageRef.document(messageId), message);

mWriteBatch.update(mMessageRef.document(mIntentMessageId), // params...);

After browsing through the docs and this site I've found out that if I use create method, it only allows to write the data if it doesn't exist.

So I created a security rule like:

match /messages/{message} {
  allow read; 
  allow create: if isSignedIn();
  allow update, delete: if isSignedIn();
}

isSignedIn() is just a method contianing request.auth != null. This rule fails and overwrites the data. Now I tried:

match /messages/{message} {
  allow read; 
  allow create: if request.resource.id != message;
  allow update, delete: if isSignedIn();
}

This time also it overwrites the data instead of showing an error.

What am I doing wrong here? Any help is appreciated.

Update: As told by José David Aroesti in the comments, I have to change it to exists and remove update and delete to work properly and from the app it's reflecting what it's suppose to do. But then how would I update and delete a document?

For example, when I'm using the below rules in Simulator, both are being executed as expected but when I'm testing it from the device, I'm always able to create a document even if it exists:

allow create: if !exists(/databases/$(database)/documents/messages/$(message));

allow update: if get(/databases/$(database)/documents/messages/$(message)).data.timestamp
        < request.resource.data.timestamp;

Is it possible?

2
  • It should be impossible to overwrite if you have not specified write or update. Commented Sep 14, 2018 at 18:41
  • @creativecreatorormaybenot updated the question, I've also included update and delete. Commented Sep 15, 2018 at 1:33

1 Answer 1

7

You can use the exists() and get() built-in functions to verify if the document exists or to access the document so you can read its data.

In this case, an example would be:

match /messages/{message} {
    allow read; 
    allow create: if !exists(/databases/$(database)/documents/messages/$(request.resource.id));
}

And as @creativecreatorormaybenot suggested, you should not specify allow expressions for update and delete so the data cannot be overwritten.

Here is a link to the documentation:

https://firebase.google.com/docs/firestore/security/rules-conditions#access_other_documents

https://firebase.google.com/docs/reference/rules/rules.firestore

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you. Previously I was comparing with request.resource.id to get method. As suggested I removed update and delete and saw the difference. But now how am I going to update or delete a document? Any help?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.