Firestore security rule: How to ensure uniqueness

2019-06-11 05:15发布

Can the below security rule ensure uniqueness of firstName, lastName, username, and email before creating a document in profiles collection?

match /profiles/{document=**} {
   allow create: if request.auth.uid != null
   && (request.resource.data.firstName is string && resource.data.firstName != request.resource.data.firstName)
   && (request.resource.data.lastName is string && resource.data.firstName != request.resource.data.firstName)
  && (request.resource.data.username is string && resource.data.username != request.resource.data.username)
  && (request.resource.data.email is string && resource.data.email != request.resource.data.email)
}

For example, below is the data in Firestore collection profiles

{
   "document1":{
      "firstName":"Jek",
      "lastName":"Choo",
      "email":"jeksomething@gmail.com",
      "username":"jek"
   },
   "document2":{
      "firstName":"Cara",
      "lastName":"Choo",
      "email":"babycara@gmail.com",
      "username":"cara"
   }
}

I want to create the below new document, and this create access should be denied

{
   "document3":{
      "firstName":"Jek",
      "lastName":"Choo",
      "email":"jeksomething@gmail.com",
      "username":"jek"
   }
}

And I want to create the below new document, this should be allowed.

{
   "document4":{
      "firstName":"example",
      "lastName":"com",
      "email":"test@example.com",
      "username":"example"
   }
}

In conclusion, can the above firestore security rule help to ensure field value uniqueness before a document is allowed to be created?

1条回答
Bombasti
2楼-- · 2019-06-11 06:06

It's important to understand what resource does with respect to rules that create new documents, which is the only rule you're showing here.

resource refers to "the (existing) document being written". This is in contrast with request.resource which describes the document that doesn't yet exist, that is about to exist, if the write succeeds.

To put it another way, in this section:

The resource variable refers to the requested document, and resource.data is a map of all of the fields and values stored in the document.

In the case of a create, there is no existing document being written. Therefore, you can assume that any matches against resource to fail. Therefore, this will not ensure uniqueness.

In fact, you can not ensure uniqueness of any given document field for a create, since it's not possible in security rules to query all documents in the collection for existence for that field.

The only form of uniqueness observed by Firestore is that of the id of a document within a collection. All fields of that document can not be constrained to be unique by security rules, and there are no indexes in Firestore that ensure uniqueness.

If you need a field to be unique, you should check after the document creation by using Cloud Function trigger, then delete the document if it doesn't satisfy the requirements.

查看更多
登录 后发表回答