Search code examples
firebasegoogle-cloud-platformgoogle-cloud-firestorefirebase-security

Firestore Data validation for number of parameters to be written


I've a HashMap which has 2 parameters which I want to add in Firestore Database.

    FirebaseFirestore mFirestore=FirebaseFirestore.getInstance();    
    Map<String,Object> userItemsMap=new HashMap<>();    
            userItemsMap.put("EmailAddress",user.getEmail());
            userItemsMap.put("CostPrice",thaliBO.getCostPrice()); 
 mFirestore.collection("Maharashtra/411057/"+user.getUid()).add(userItemsMap)
                    .addOnSuccessListener(new OnSuccessListener<DocumentReference>() {
                        @Override
                        public void onSuccess(DocumentReference documentReference) {
                            String str="hi";
                        }
                    }).addOnFailureListener(new OnFailureListener() {
                @Override
                public void onFailure(@NonNull Exception e) {
                    String str="hi";
                }
            });

I'm validating data using the Firestore rules as:

service cloud.firestore {
  match /databases/{database}/documents {
    match /{state}/{zip}/{uid}/{document=**} {  
allow write: if request.resource.data.CostPrice>0 &&
request.resource.data.EmailAddress.size()<30 
        }
      }
   }

I'm concerned for a situation where someone using reverse engineering add some more parameters to the userItemsMap like

userItemsMap.put("PhoneNUmber","123456789");

which will be stored in the firestore consuming unnecessary memory.

Is there any data validation rule in firestore which can prevent this?


Solution

  • You should use the resource variable as you are already doing.

    With the data property of the resource you get a rules.Map, i.e. a Map of the document data.

    The Map type has the keys() and size() methods , see https://firebase.google.com/docs/reference/rules/rules.Map.

    Then, you just have to check that:

    request.resource.data.size() == 2
    

    and

    that the keys are corresponding to EmailAddress and CostPrice. For that, you will use the hasOnly() method of the keys, since the keys() method returns a rules.List, see https://firebase.google.com/docs/reference/rules/rules.List. So do as follows:

    request.resource.data.keys().hasOnly(['EmailAddress', 'CostPrice']) == true