Reputation: 3383
I'm using the Firebase Bolt Compiler to build my security rules and I've come across the following scenario:
I have some nested data that I want to post to Firebase in the following form:
data: {
a: //Number, must always be present
b: //Number, conditionally present (condition B)
c: //Number, conditionally present (condition C)
}
Conditions B and C are based on a piece of data, elsewhere is Firebase, and if met, I want the values included, but if not met, I want to values to be null
root.condition >= 5 //condition B
root.condition >= 10 //condition C
The following is my attempt, using Bolt, to construct these rules:
type ConditionB extends Number {
validate() = root.condition >= 5 ? this != null : this == null;
}
type ConditionC extends Number {
validate() = root.condition >= 10 ? this != null : this == null;
}
type Data {
a: Number,
b: ConditionB,
c: ContitionC
}
path /data is Data {
read() = true,
write() = true
}
Here is the following rules.json:
"rules": {
"data": {
".validate": "newData.hasChildren(['a', 'b', 'c']),
...
}
}
It can be seen that the .validate
rule enforces all children to be present in data
. So, how can I ensure that, based on my conditions, the .validate
rules for both data
and each of its children are correct?
Upvotes: 1
Views: 1027
Reputation: 7014
Since your type can be Null, you must extend Number | Null like so:
type ConditionB extends Number | Null {
validate() = root.condition >= 5 ? this != null : this == null;
}
type ConditionC extends Number | Null {
validate() = root.condition >= 10 ? this != null : this == null;
}
type Data {
a: Number,
b: ConditionB,
c: ConditionC
}
path /data is Data {
read() = true;
write() = true;
}
Which results in the following JSON rules file:
{
"rules": {
"data": {
".validate": "newData.hasChildren(['a'])",
"a": {
".validate": "newData.isNumber()"
},
"b": {
".validate": "(newData.isNumber() || newData.val() == null) && (newData.parent().parent().child('condition').val() >= 5 ? newData.val() != null : newData.val() == null)"
},
"c": {
".validate": "(newData.isNumber() || newData.val() == null) && (newData.parent().parent().child('condition').val() >= 10 ? newData.val() != null : newData.val() == null)"
},
"$other": {
".validate": "false"
},
".read": "true",
".write": "true"
}
}
}
Upvotes: 3