Firebase rejects update with PermissionDenied as expected but still the client listening to the node receives the data sent

Issue

I am listening to a node in the realtime db, and a MULTIPATH update is sent that should not pass security rules. Should pass the write rules but not the validate rules.

Checking the firebase console nothing gets written as expected. But the client listening to one of the nodes with onChildAdded receives the data sent.

Is it possible that nothing gets committed to the database but still onChildAdded is triggered on the client?

I thought this was not possible but maybe I am missing something about rules validation + multipath updates.

event received printed on the console:

event: Instance of ‘QueryEvent’ | event.snapshot: Instance of ‘DataSnapshot’ | event.snapshot.val: {c: true, m: e3, n: 1} [2021-08-31T18:14:33.230Z] @firebase/database: FirebaseError: PERMISSION_DENIED: Permission denied (PERMISSION_DENIED)

the data sent, I am doing a multipath update this way:

Map<String, dynamic> updateToSend = {};

updateToSend["status/c"] = move.c;
updateToSend["status/n"] = move.n;
updateToSend["moves/${move.n}/n"] = move.n;
updateToSend["moves/${move.n}/m"] = move.m;
updateToSend["moves/${move.n}/c"] = move.c;

await fb.database().ref('games/$gameID').update(updateToSend);

the listener:

final movesRef = fb.database().ref("/games/${gameId}/moves");
final streamMoves = movesRef.onChildAdded;

streamMoves.listen((event) {
  print(
      "event: $event | event.snapshot: ${event.snapshot} | val: ${event.snapshot.val()}");
  ...
}

Solution

On the client that performs a write operation, listeners for the affected paths fire immediately – before the data is even sent to the server. If the write gets rejected by the server, the SDK will actually fire reconciliation events to ensure the app can be put in the right state again.

So: if you also listen to the onChildRemoved stream, you will get an event there once the server has rejected the write operation. That allows you to then remove it from the UI again. There is no way to prevent getting the initial local events.

Answered By – Frank van Puffelen

Answer Checked By – Marilyn (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *