0

I need to write rules for Cloud Firestore.

I want my rules to allow the creation of a new document in a collection:

newDoc(field1="value-1", field2="value-2", field3="other-miscellaneous-values")

only if no other document already exists in the collection with:

(field1 == "value-1") and (field2 == "value-2")

Though this is not very complicated, it seems still too complex to be found as an example in any tutorial that I found searching the net.

Beside, the user should be free to list and read all the documents in the collection if she/he wishes.

Here is what I have tried, but it does not work:

service cloud.firestore {
  function alreadyExists(document) {
              return exists((resource.data.field1==request.resource.data.field1)&&
                           (resource.data.field2==request.resource.data.field2))
  }

  match /databases/{database}/documents {
    match /My_Collection/{anything=**} {
      allow read;
      allow write: if !(alreadyExists(request.resource.data));
    }
  }
}

I hope someone can give me some advice to get it working.

Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
Michel
  • 10,303
  • 17
  • 82
  • 179

2 Answers2

1

This isn't possible with security rules, because rules are incapable of performing arbitrary queries. The only type of query that's supported is a simple get() if you know the path of the document to fetch.

What you can do instead is write some backend code (perhaps a Cloud Function) to enforce this check, and make the client go through that backend for all write operations against that collection. Or, you could write a Firestore trigger to check the document after it was created, and remove it after the fact, if it conflicts with other documents in the collection.

Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
  • I think I prefer the first option you suggest (Cloud Function). Do you have a good YouTube video (or a tutorial) to recommend to learn how to make that work? – Michel Nov 20 '19 at 18:09
  • No, but there is plenty of documentation for Cloud Functions. – Doug Stevenson Nov 20 '19 at 18:11
1

Security rules can only check if a document at a certain path exists (with exists). There is no way to check if a document with a certain value exists in rules.

My typical solution for your use-case would be to use the combination of fields that you want to be unique as the ID of the document. Since document IDs are by definition unique in a given collection, that ensures that your combination of keys is unique in that same collection.

If you already have an ID strategy that you can't change, consider adding a secondary collection to contain the unique combinations, as shown in my answer here: Prevent duplicate entries in Firestore rules not working.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • I chose your solution, because it is simple and fits my current needs. I hope there is no limit on the length of the ID though. I am also aware that Cloud Functions would certainly allow more sophisticated processing in more complex cases. – Michel Nov 21 '19 at 09:42