Reputation: 1
Is there any way to set a data cap on Firebase children?
E.g.,...
{
Customer1: {},
Customer2: {},
Customer3: {}
}
For my particular example, depending on a customer's payment model will dictate how much space they are allowed to use. Say for Customer1 and Customer2, I only want at most 25MB of space used. Any new data will either remove older data or not get appended at all.
Should I do something where for a certain Customer, I check the sizeof of the the WHOLE data set and prevent customers from adding in new data if it exceeds a certain amount?
It doesn't seem like an ideal solution to be honest...
Upvotes: 0
Views: 140
Reputation: 4978
After some trial and error i found out it is actually possible to have a cap on data within the firebase security rules. But only to a certain extend!
The limiting factor is that you can only check the value of a primitive type (string, number or bool). When a node has children you would have to check the value of each of that children, this implies you know what data you can expect.
Below is an example of the security rules needed to accomplish this. The rules are only for a primitive type or a node with a maximum of 3 (specified) primitive children.
"rules": {
".read": true,
".write": true,
"$key":{
//validate that the data has no children
".validate":"(!newData.hasChildren() &&
//and validate if it is a string within a certain length
(newData.isString() && newData.val().length < 10) ||
//or validate if it is a number within a certain range
(newData.isNumber() && (newData.val() < 10 && newData.val() > -10)) ||
//or validate if it is a bool
newData.isBoolean()) ||
//Or rince and repeat for all possible child nodes
newData.hasChildren()",
"childA":{
".validate":"(!newData.hasChildren() &&
(newData.isString() && newData.val().length < 10) ||
(newData.isNumber() && (newData.val() < 10 && newData.val() > -10)) ||
newData.isBoolean())"
},
"childB":{
".validate":"(!newData.hasChildren() &&
(newData.isString() && newData.val().length < 10) ||
(newData.isNumber() && (newData.val() < 10 && newData.val() > -10)) ||
newData.isBoolean())"
},
"childC":{
".validate":"(!newData.hasChildren() &&
(newData.isString() && newData.val().length < 10) ||
(newData.isNumber() && (newData.val() < 10 && newData.val() > -10)) ||
newData.isBoolean())"
},
//dismiss all child nodes you don't want
"$other": {".validate": false}
}
}
Some of the downsides about this sollution are:
Upvotes: 1
Reputation: 599686
This is one of those requirements that you can't implement in the client-side application as the users will be able to bypass them if you do.
Instead you should implement this server-side, which leaves:
There is no operator built-in Firebase Security Rules that gives the size of a node. You can determine the length of a string, but that's a bit little to go on.
So your best bet is to use server-side process, which is: a process that you control, which doesn't run on the client's device. With that server-side process you can calculate the node size in any way you see fit.
The process then writes the node size back into Firebase into a secured location (that only the process can write). The security rules can then check against this location and reject writes if the node is larger than the quota.
Upvotes: 0