I have a function (and I've tested it without functions just to check if there isn't problem with reference or something):
function resourceIsValidSomething() {
return request.resource.data.something is string ...;
}
and then:
allow create: if request.auth != null && resourceIsValidSomething();
and
allow update: if request.auth != null && resourceIsValidSomething();
But I get this error message when testing the update rule:
Error: simulator.rules line [19], column [17]. Property resource is undefined on object.
According to the documentation, my rules should be correct.
What am I doing wrong?
Real example:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
function isGod() {
return get(/databases/$(database)/documents/employees/$(request.auth.uid)).data.role == 'god';
}
function allowedUser() {
return request.resource.data.assignedTo.uid == request.auth.uid || isGod();
}
match /stores/{storeId} {
allow read: if request.auth != null;
match /imeis/{imeiId} {
function resourceIsValidImei() {
return request.resource.data.imei is string &&
request.resource.data.imei.size() > 0 &&
request.resource.data.type is string &&
request.resource.data.type.size() > 0 &&
request.resource.data.dateAdded is timestamp &&
request.resource.data.createdBy.uid == request.auth.uid;
}
allow read: if request.auth != null;
allow create: if request.auth != null &&
isGod() && resourceIsValidImei();
allow update: if request.auth != null && allowedUser();
}
“Property resource is undefined on object”
You can't use a non-existent property in a Firebase rule expression.
For example, the following will raise a similar error.
read: if request.foobar == 'some value';
That's because foobar doesn't exist, and the rule will raise that it is undefined. The comparison with the 'some value' on the right-hand side never happens, and the rest of the rule expressions are not evaluated.
Objects like request implement the Map() interface.
https://firebase.google.com/docs/reference/rules/rules.Map
So you can rewrite your rule using the Map.get() method which doesn't raise an error and provides a default value for missing entries.
read: if request.get('foobar', null) == 'some value';
So now we're safely referring foobar in our rules.
I have a function (and I've tested it without functions just to check if there isn't problem with reference or something):
Not all requests in the rules yield a resource. If the document does not exist the resource property on request is never set. So attempting to read it yields the above error. You can resolve this problem by checking for null.
function resourceIsValidSomething() {
return request.get('resource', null) != null && request.resource.data.something;
}
You will probably still get a rule error like false for "get" & L10
That's because the request.get('resource', null) != null check is going to fail the rule. You can decide to allow access to documents that don't exist so that the query will complete.
The rule would look like this instead.
function resourceIsValidSomething() {
return request.get('resource', null) == null || request.resource.data.something;
}
So allow access to missing resources or only resources with data.something.
It's up to you to decide which approach works best for your use-case.
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