Search code examples
firebase-realtime-databasefirebase-security

Firebase realtime DB rule based on data.child do not work


I like to retrieve the list of items only the ones its delete flag is false. but this setting does not work.

{
  "rules": {
    "items": {
      ".read": "data.child('isDelete').val() == false",
      "$uid": {
        ".write": "auth != null && !data.exists()"
      }
    }
  }
}

Here's a result from Rules playground request I tried.

Request details

{
  "auth": null,
  "resource": {
    "key": "value"
  },
  "path": "/items",
  "method": "get",
  "time": "2022-07-07T09:24:31.042Z"
}

Result details

Line 4 (/items)
read: "data.child('isDelete').val() == false"

The data structure

items
- 1xxxxxxxxxx
 title:"title text 1"
 createdAt:"2022-06-05T04:21:57.322Z"
 isDelete:false
- 2xxxxxxxxxxxxx
 title:"title text 2"
 createdAt:"2022-06-05T04:21:50.322Z"
 isDelete:true

What is wrong?


Solution

  • I think you may be missing that rules are not filters on their own. All the rules do is check for any incoming operation whether it is allowed, and in your try from the playground you are trying to read all of /items, rather than just the items with isDelete set to false, to that isn't allowed.

    There is no way to perform the necessary query from the playground, but in code you can get the items with this query:

    ref.orderByChild("isDelete").equalTo(false)
    

    Now the operation matches the condition in your rules, and is only trying to read data that it is allowed to, so the rules will allow the operation.


    Update: I forgot that query-based rules in the Realtime Database actually require that you write the rule as this:

    {
      "rules": {
        "items": {
          ".read": "query.orderByChild === 'isDelete' && query.equalTo === false",
          ...
    

    Now the query only tries to retrieve non-deleted data, and the security rules correctly validate this.