5

So I want to write a security rule to disallow writes if a child node is different then it previously was. E.g. imagine a situation where you want a node to only be writable on creation but never thereafter. Given this requirement, the most obvious solution would seem to be to verify that the new data is equal to the old data.

Sadly, this does not work:

".write": "data.child('someNode').val() === newData.child('someNode').val()"

Nor a more sophisticated approach where I try to cast the object to a string:

".write": "!data.exists() || (data.child('someNode').val() + '') === (newData.child('someNode').val() + '')"

Any way this use case can be supported?

Important Note: The value at someNode has to be an object and can't simply be a string or other primitive. In the case of primitives, either of these methods work fine.

Scottmas
  • 1,082
  • 10
  • 22
  • 1
    Is this what you are looking for? http://stackoverflow.com/a/20787137/2124834 –  May 01 '15 at 21:39
  • I just tried this and it works fine for me. Is there already a `someNode` in your Firebase? Because if not, you're indeed missing a `!data.exists()` as in the answer that @Marein pointed to. – Frank van Puffelen May 01 '15 at 23:36
  • Ah, I now see your last remark. It would be really helpful if you actually include a sample of the data you're trying to validate. What would be even nicer is a snippet of code that reproduces the problem you're trying to solve. But in this case the answer would be the same: Firebase's security rules do not support comparing JSON fragments. You'll have to compare every leaf node in your rules to test for equality. – Frank van Puffelen May 01 '15 at 23:41
  • I left out the !data.exists() so as to not confuse the issue, but in this case it doesn't matter. – Scottmas May 02 '15 at 00:16

1 Answers1

5

Firebase's security rules do not support comparing JSON fragments. You'll have to compare every leaf node in your rules to test for equality.

E.g.

".validate": "
  data.child('someNode/username').val() == newData.child('someNode/username').val()
  && data.child('someNode/displayName').val() == newData.child('someNode/displayName').val()"
"
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • Sadness :( This was the answer I was afraid I'd hear. In my particular case I won't be able to check the leaf nodes because "someNode" is actually an object containing foreign key references, and is therefore dynamic. There's one or two other workarounds I can think of to solve my particular use case. – Scottmas May 02 '15 at 00:17
  • Yes. If you're having trouble making it work for you case, post a new question please. – Frank van Puffelen Sep 07 '20 at 14:02