I would like to know if it's possible to avoid the functions call depth limit of Firestore security rules for my following code.
What's counted as function? Just my own created or also something like size()?
function isValidItem(data, item) {
return
( // Person
data.items[item].keys().hasAll(['image','type','name','job','age','party','experience'])
&& data.items[item].image.size() >= 1 && data.items[item].image.size() <= 200
&& data.items[item].type.size() >= 5 && data.items[item].type.size() <= 10
&& data.items[item].name.size() >= 1 && data.items[item].name.size() <= 50
&& data.items[item].job.size() >= 1 && data.items[item].job.size() <= 50
&& data.items[item].party.size() >= 1 && data.items[item].party.size() <= 50
&& data.items[item].experience.size() >= 1 && data.items[item].experience.size() <= 50
&& data.items[item].age.matches('^[0-9]+$')
)
||
( // Party
data.items[item].keys().hasAll(['image','type','name','orientation','experience','promi'])
&& data.items[item].image.size() >= 1 && data.items[item].image.size() <= 200
&& data.items[item].type.size() >= 5 && data.items[item].type.size() <= 10
&& data.items[item].name.size() >= 1 && data.items[item].name.size() <= 50
&& data.items[item].orientation.size() >= 1 && data.items[item].orientation.size() <= 50
&& data.items[item].experience.size() >= 1 && data.items[item].experience.size() <= 50
&& data.items[item].promi.size() >= 1 && data.items[item].promi.size() <= 50
);
}
function itemsAreValid(data) {
return data.items.size() >= 1
&& data.items.size() <= 10
&& isValidItem(data, 0)
&& (data.items.size() < 2 || isValidItem(data, 1))
&& (data.items.size() < 3 || isValidItem(data, 2))
&& (data.items.size() < 4 || isValidItem(data, 3))
&& (data.items.size() < 5 || isValidItem(data, 4))
&& (data.items.size() < 6 || isValidItem(data, 5))
&& (data.items.size() < 7 || isValidItem(data, 6))
&& (data.items.size() < 8 || isValidItem(data, 7))
&& (data.items.size() < 9 || isValidItem(data, 8))
&& (data.items.size() < 10 || isValidItem(data, 9));
}
function isValidTitle(data) {
return data.title.size() >= 1
&& data.title.size() <= 200
}
function isAuthed() {
return request.auth.uid != null
&& request.auth.token.email_verified == true;
}
allow create, update:
if isAuthed()
&& request.resource.data.user == request.auth.uid
&& request.resource.data.status == "review"
&& isValidTitle(request.resource.data)
&& itemsAreValid(request.resource.data);
I checked this out with the Firebase security rules team, and we found that the limit you're exceeding here is almost certainly the total number of expressions allowed. This is documented to be 10,000 right now, but that number is actually incorrect. It should be documented as 1,000. That's why, when you pared down the rules some, it was able to start worked. You likely came in under the 1000 limit at that point.
What you can do to improve your situation is stop calling functions repeatedly unnecessarily. For example, instead of isValidItem(map, key) and then calling map[key] repeatedly, you could just write isValidItem(value)
Unfortunately, there is currently no log or debugging available for security rules, so you'll need to take a guess sometimes when things go wrong.
We're going to fix the documentation, and also discuss more internally.
Calling data() -> document reference every time.
The limit is document access, in this calling data() is the problem. You are referring document by calling data many time. To avoid this, you can pass data() into function and validate everything inside it.
Access call limits
There is a limit on document access calls per rule set evaluation:
10 for single-document requests and query requests.
20 for multi-document reads, transactions, and batched writes. The previous limit of 10 also applies to each operation.
For example, imagine you create a batched write request with 3 write operations and that your security rules use 2 document access calls to validate each write. In this case, each write uses 2 of its 10 access calls and the batched write request uses 6 of its 20 access calls.
Exceeding either limit results in a permission denied error. Some document access calls may be cached, and cached calls do not count towards the limits
https://firebase.google.com/docs/firestore/security/rules-conditions
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