Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Firestore security rules: Using hasOnly on a request to check if only a specific field is updated

I'm setting up my Firestore security rules, but run against one issue wherein I want to limit updating only one specific field within a document by using the hasOnly function. The problem is that I keep getting 'denied' results using the simulator. I'm surely doing something simple wrong... I'm trying to prevent that somebody could update other fields in the document than update_requested_time, but allow them to update this particular field.

When using the example from the Firestore documentation on hasOnly() — ['a', 'b'].hasOnly(['b', 'a']) == true — the rule returns true. But when using my own it does not, by that I assume I'm getting something wrong in the part of request.resource.data.keys().

The specific rule targeting fields in a specific scenario:

match /scenarios/{scenario} {
      allow read: if true;
      allow update: if request.auth.uid != null
        && request.resource.data.keys().hasOnly(['update_requested_time']) == true;

The simulator request I'm sending (update with authentication):

{"__name__":"/databases/(default)/documents/scenarios/test1","data":{"update_requested_time":"2019-02-05T11:00:00.000Z"}}

My complete rules:

service cloud.firestore {
  match /databases/{database}/documents {
    match /scenarios/{scenario} {
      allow read: if true;
      allow update: if request.auth.uid != null
        && request.resource.data.keys().hasOnly(['update_requested_time']) == true;
      match /comments/{comment} {
        allow read: if true;
        allow create: if request.auth.uid != null;
        allow delete,update: if request.auth.uid != null && request.auth.uid == resource.data.user;
      }
      match /outputs/{tile} {
        allow read: if true;
      }
      match /mutations/{tile} {
        allow read: if true;
        allow create,update: if request.auth.uid != null;
      }
    }
    match /users/{user} {
      allow read: if true;
      allow update: if request.auth.uid != null && request.auth.uid == user;
    }
  }
}

screenshot of firestore rules + simulator

like image 998
Fabian Hijlkema Avatar asked Dec 01 '25 05:12

Fabian Hijlkema


1 Answers

Looks like the right way to do this now is

request.resource.data.diff(resource.data).affectedKeys().hasOnly(["update_requested_time"])

Found from this conversation

like image 181
j0j Avatar answered Dec 05 '25 00:12

j0j



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!