firebasefirebase-realtime-databasefirebase-security

How to deny all writes to Realtime Database based on data within it?


In the Realtime Database, if we want to block all writes to an entire Realtime Database database based on some boolean contained therein, what is the proper way to do it?

Let's say in Realtime Database, we want to have a bool "downForMaint"

'config'/'downForMaint': false

And our existing rules look like this:

{
  "rules": {
    ".read": false,
    ".write": false, // <-------------- want some simple rule here.

    "Xnode": {
      ...
    },

    "Ynode": {
      ...
    }
  }
}

I am to understand from reading docs, that in Realtime Database rules (presumably Firestore rules also) that generally we are not defining what not to allow, only what to allow, and that:

So, then it seems I can't do this with write rules other than tacking on a "&& if" to every existing write rule.

So then, can it be done with validation at the root like this?

{
  "rules": {
    ".read": false,
    ".write": false,
    ".validate": "root.child('config/downForMaint').val() != true"

    "Xnode": {
      ...
    },

    "Ynode": {
      ...
    }
  }
}

Solution

  • I gave it a quick try and the trick with .validate indeed works.

    Data structure I used:

    "79734825": {
      "downForMaintenance": true,
      "data": {
        "test": "hello world"
      }
    }
    

    And the rules for this section of the database:

    "79734825": {
      ".write": false,
      ".validate": "data.child('downForMaintenance').val() != true",
      "data": {
        ".write": true
      }
    },
    

    And the code for writing:

    var ref = firebase.database().ref("79734825/data");
    
    setInterval(() => {
      ref.child('test').set(""+Date.now());
    }, 2000);
    

    Test bed: https://stackblitz.com/edit/rtdb-compat-rules-or

    If it works for your use-case, then "frowned upon" and "misuse/hacky" are just somebody else's opinion. I think it looks fine and doubt it causes a lot of performance concern. That said: I usually repeat such conditions in every .write clause, because I prefer it that way. You don't have to share my preferences though.