I have defined a realtime database rule as follows:
{
"rules": {
".read": false,
".write": false,
"devices": {
".read": "auth.uid != null && query.orderByChild == 'ownerUid' && query.equalTo == auth.uid",
"$device": {
".read": "data.child('ownerUid').val() == auth.uid",
"nickname": {
".write": "data.parent().child('ownerUid').val() == auth.uid",
".validate": "newData.isString() && newData.val().length < 30"
},
"ownerUid": {
".validate": "root.hasChild('users/' + newData.val())"
},
... additional fields here
}
}
}
}
In my web application, using reactfire
and firebase
npm modules, I have queried for a device as follows:
const devicesRef = useDatabase()
.ref(`devices`)
.orderByChild('ownerUid')
.equalTo(user.uid);
const { data: devices, status } = useDatabaseListData<Device>(devicesRef, { idField: 'id' });
This appears to work, but if I look in the network tab, I can see all of the data come back, not just the data that is supposed to come back. The data returned to my code is the data that I would expect.
Note in the screenshot below that all data comes back, even data that does not have ownerUid defined.
I am using the example from the documentation almost exactly: https://firebase.google.com/docs/database/security/rules-conditions#query-based_rules
Am I doing something wrong? or is this a bug in Firebase?
I discovered the solution after upgrading my firebase client version and getting some new errors from it. It turns out the issue was that I was missing an index on ownerUid
.
The new rules look like this:
{
"rules": {
".read": false,
".write": false,
"devices": {
".indexOn": ["ownerUid"],
".read": "auth.uid != null && query.orderByChild == 'ownerUid' && query.equalTo == auth.uid",
"$device": {
".read": "data.child('ownerUid').val() == auth.uid",
"nickname": {
".write": "data.parent().child('ownerUid').val() == auth.uid",
".validate": "newData.isString() && newData.val().length < 30"
},
"ownerUid": {
".validate": "root.hasChild('users/' + newData.val())"
},
... additional fields here
}
}
}
}