1

I have the following function

  Future<void> _updateDocument(String path, {Map<String, dynamic> data}) async {
    final Map<String, dynamic> stampedData = {'updatedAt': FieldValue.serverTimestamp()};
    if (data != null) stampedData.addAll(data);
    try {
      print('Updating document : $path with $stampedData');
      final DocumentReference documentReference = _fireStore.document(path);
      await documentReference.updateData(stampedData);
    } on PlatformException catch (error) {
      throw UserFriendlyException('Operation Failed', error.message);
    }
  }

Which updates a certain document. But I keep getting the following error

Write failed at groups/YUUjiGgQ6De4IMshWmRF: Status{code=PERMISSION_DENIED, description=Missing or insufficient permissions., cause=null}

Because I have the following rule

incomingData().keys().hasOnly(['updatedAt', 'displayName']) == true

So I tested how many keys there actually are and it turns out there are 5 keys

function isValidGroupRename(){
    return incomingData().keys().hasAll(['updatedAt', 'displayName']) == true &&
             incomingData().keys().size() < 6
}

Because this functions passes the test but < 5 does not. When I look at the data object right before the I call the update, so this line print('Updating document : $path with $stampedData'); it tells me that I only update 2 values

Updating document : groups/YUUjiGgQ6De4IMshWmRF with {updatedAt: FieldValue(Instance of 'MethodChannelFieldValue'), displayName: jjjjjgi}

So does FieldValue.serverTimestamp() add on fields? And if so what are those fields so I can check for them.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
anonymous-dev
  • 2,897
  • 9
  • 48
  • 112
  • 1
    By the time it hits your security rules, `FieldValue.serverTimestamp()` has been converted into a normal `Date and time` value. No extra data is written. – Frank van Puffelen May 20 '20 at 14:13
  • @FrankvanPuffelen is there any way I could debug why there are 5 keys instead of 2 / what those keys are – anonymous-dev May 20 '20 at 14:20
  • I have no idea what `incomingData()` is in your rules. A common mistake however is expecting that `request.resource` only contains the data that is written from the client. It actually contains the data as it will exist after the operation completes (if successful). So if there are 5 fields in the doc, and you're updating 2 of them: `request.resource` will contain 5 fields, 2 of which are updated. – Frank van Puffelen May 20 '20 at 14:45
  • Aah yes that's it. Thanks! – anonymous-dev May 20 '20 at 15:50

1 Answers1

1

By the time it hits your security rules, FieldValue.serverTimestamp() has been converted into a normal Date and time value. No extra data is written.

A common mistake however is expecting that request.resource only contains the data that is written from the client. It actually contains the data as it will exist after the operation completes (if successful).

So if there are 5 fields in the doc, and you're updating 2 of them: request.resource will contain 5 fields, 2 of which are updated.

Also see:

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807