Open mm-gmbd opened 8 years ago
See https://en.wikipedia.org/wiki/Three-valued_logic
Bolt (and Firebase) will fail any rule that dereferences a null value. You're correct - it would be nicer to support 3VL - but at some expense of blowing up some rules. It's something we can investigate, or perhaps make an option to the compiler.
You can fix it by writing compound expressions yourself.
@mckoss, thanks for the explanation, wasn't aware of three-valued logic. Learn something every day :)
As for the compound expressions, I presume you mean (in this case), checking the value of the the key before using it to dereference?
path /uniqueInformation/$uniqueDevice/information: {
read() = uniqueReadRules($uniqueDevice);
}
//Allows an owner of the device to read information, IF ANY ONLY IF the device they own is currently being represented by the unique device. Also allows admin to read information
function uniqueReadRules(uniqueDevice){
return (auth != null &&
root.users[auth.uid].userType == 'standard' &&
root.uniqueDevices[uniqueDevice] !== null && //ADDED THIS RULE
root.devices[root.uniqueDevices[uniqueDevice]].owner == auth.uid) ||
(
auth != null &&
root.users[auth.uid].userType == 'admin'
);
}
In this case, will it automatically fall past the next statement (that originally failed) and into the OR?
Yes. Our rules are "short circuiting":
a && b => if !a, then b never evaluated. a || b => if a, then b never evaluated.
Bolt preserves the ordering of expressions when generating expressions, so you can depend on the order of evaluation to use short-circuiting to avoid dereferencing null values.
If you example above, you might also need to add the check:
root.devices[root.uniqueDevices[uniqueDevice]] != null
before referencing the owner field.
This is kind of a pain to do, I know - which is one reason we've considering applying 3VL to allow you to use "undefined" values in expressions.
Apologies for the crappy title. Maybe after some thinking I'll come up with something more specific. Anyways, onto the question/issue.
I think this is really an issue for Firebase rules in general, but since I came across it while using Bolt, I figured I'd at least jot it down here to start. And again, onto the issue :)
I have a Firebase that includes users and devices, and users can be either type
admin
orstandard
. Anadmin
user can access data from all devices, whereas astandard
user can only access the devices that claim him/her as the owner (devices/$device/owner
).A small (but necessary) wrinkle in my data structure is that a single device can have multiple identities, or rather, one day, it's identifier could be "$device1" and the next day it could be "$device4" (although it can have multiple identifies, it can only be one identity at one time).
There is also a never-changing, always-unique identifier that represents that device, let's call it "$uniqueDevice1", and it has it's own tree, and it's value represents the current changeable identity of the device.
So, for example:
user1
ownsdevice1
user2
ownsdevice4
user0
isadmin
, and has access to all devicesdevice1
anddevice4
are actually both representations ofuniqueDevice1
uniqueDevice1
is currently being represented bydevice4
Here are my read rules for accessing
devices/$device/data
:You can see that, regardless of which "non-unique" device the "unique" device is representing,
user1
can accessdevice1/data
, anduser2
can accessdevice4/data
. Also, theadmin
can accessdata
from both devices.Now, here are my read rules for accessing
uniqueInformation/$uniqueDevice/information
:This is almost the exact same as
readRules
, but with the difference that the value passed toroot.devices[//here//]
is root.unqiueDevices[uniqueDevice], rather than just device.So, here is the issue. If the value of
uniqueDevices/$uniqueDevice
is not set in Firebase, the admin is rejected from reading/uniqueInformation/$uniqueDevice/information
, even though the rule is OR'd withroot.users[auth.uid].userType == 'admin
.I presume because this is the equivalent of the following:
And because null is passed into
root.devices
, then the rule totally bombs out. I'm pretty sure I'm correct on this, because if I simply arrange my rules so that theadmin
check comes first, then even if the value foruniqueDevices/$uniqueDevice
is null in Firebase, the admin can still readuniqueInformation/$uniqueDevice/information
.So, I guess the question is, in what cases do Firebase rules totally bomb out and ignore the rest of the rules, even if there is still AND'ing and OR'ing to be done?