Perhaps I'm tackling this problem too much from an SQL kind of perspective, but I'm having troubles understanding how to properly restrict which children should be allowed to populate a node.
Say that I want to keep a record of products with arbitrary names. Each product must contain a price
, but nothing else is allowed.
My naive approach was to add a .validate
rule to the products requiring newData to contain a price
child, explicitly granting write access to the price
node and then removing all access an $other
node (somewhat like a default clause in a switch statement):
{
"rules": {
"$product": {
".read": true,
".write": true,
".validate": "newData.hasChildren(['price'])",
"price": {
".write": true,
".validate": "newData.isNumber()"
},
"$other": {
".read.": false,
".write": false,
}
}
}
}
This does not work. Adding a new product with {"price": 1234, "foo": "bar"}
will still be accepted. If I however add a (I did that wrong, somehow.)".validate": false
rule to $other
, nothing is accepted instead (e.g. {"price": 1234}
is not allowed).
Is there some way to implement something similar to what I'm trying to do here? If not, what is the proper way of restricting a data structure in Firebase? Should I do it at all? What stops the user from filling my database with trash if I don't?
You're falling into a few common Firebase security pits here. The most common one is that permission cascades down: once you've granted read or write permission on a certain level in the tree, you cannot take that permission away at a lower level.
That means that these rules are ineffectual (since you've granted read/write one level higher already):
"$other": {
".read.": false,
".write": false,
}
To solve the problem you must realize that .validate
rules are different: data is only considered valid when all validation rules are met. So you can reject the $other
data with a validation rules:
{
"rules": {
"$product": {
".read": true,
".write": true,
".validate": "newData.hasChildren(['price'])",
"price": {
".validate": "newData.isNumber()"
},
"$other": {
".validate": false
}
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With