firebase / firebase-js-sdk

Firebase Javascript SDK
https://firebase.google.com/docs/web/setup
Other
4.83k stars 888 forks source link

Realtime database security rules error when comparing priority with >= #2939

Open Pustelto opened 4 years ago

Pustelto commented 4 years ago

[REQUIRED] Describe your environment

[REQUIRED] Describe the problem

When writing security rules for realtime database I use .getPriority() method to get a numeric value. I need to compare this value against some constant to see if it is equal or greater than that constant. However >= is not working properly in this case. And firebase rule will throw an permission denied in such a case.

In both cases below I'm 100% certain priority is 100 I get it printed in console but first rule is still failing.

Rule which should work but it does not:

"boards": {
  "$boardId: {
    ".write": "(!data.exists() && newData.child('owner').val() == auth.uid) || (data.exists() && root.child('boardsPermissions/' + $boardId + '/' + auth.uid).getPriority() >= 40)"
  }
}

Rule which is working:

"boards": {
  "$boardId: {
    ".write":  "(!data.exists() && newData.child('owner').val() == auth.uid) || (data.exists() && root.child('boardsPermissions/' + $boardId + '/' + auth.uid).getPriority() === 100)"
  }
}

Steps to reproduce:

If I try to use any other comparison operator than === in realtime database security rules with a numeric priority value, security rules will be evaluated to false and I can't write to DB.

What is odd is that after some longer time (few minutes) this rule will work and I can update the node. However this is not usable in production app and it does not make sense that the comparison fails even though the priority value is set to value which >= 40.

Relevant Code:

Type some boardId in the form in codesandbox below and submit it. This will create new node in DB and set priority to 100. Then try to submit the form again with the same Id and you will get permissions error. But based on security rules below user should be able to update the data.

https://codesandbox.io/s/snowy-hill-19cwt?file=/index.html

Security rules setup for database:

{
  "rules": {
    "boards": {
      "$boardId": {
        ".read": true,
        ".write": "!data.exists() || (data.exists() && root.child('boardsPermissions/' + $boardId).getPriority() >= 40)"
      }
    },
    "boardsPermissions":{
      "$boardId": {
        ".read": true,
        ".write": true
      }
    }
  }
}
google-oss-bot commented 4 years ago

I couldn't figure out how to label this issue, so I've labeled it for a human to triage. Hang tight.

katowulf commented 4 years ago

Also asked and discussed here. Please indicate when you cross post.

Pustelto commented 4 years ago

Sorry @katowulf, it has been sitting on SO for so long without any response that I forgot about it. Anyway in my project I use cloud functions to set priority as a number and in the example I set it directly as a number as well. So based on your information there shouldn't be a problem with the type conversion.

katowulf commented 4 years ago

It's working fine for me when I simplify the rules, so still seems likely to be string vs number or some other issue with the rules: https://stackblitz.com/edit/kato-github-firebase-js-sdk-2939