My rules look like this:
{
"rules": {
"userShaders": {
"$uid": {
"shaders": {
".write": "auth.uid === $uid",
".read": "auth.uid === $uid || data.child('public').val() == true"
}
}
}
}
}
My data looks like this:
userShaders
8v4N3yLlXAU1cpRiaDj5kkDQaKn1
shaders
myShaderName
attr_1: ""
attr_2: ""
public: false
I am not logged in as this user and am attempting to query their data. I expect to succesfully get back 0 records because they have none marked as public
.
However, I'm getting a permission denied error.
My query looks like this:
val shaderRef = db
.getReference("userShaders/${uid}/shaders")
.orderByChild("public")
.equalTo(true);
shaderRef.get().addOnSuccessListener {
// do something with the data
}
To summarize, I am trying to query for only public data, while simultaneously making a rule that non-public data is impossible to fetch by other users. I want to write a query such that I may receive 0 or many records back, but never a permission denied error.
The most important thing to realize is that Firebase security rules don't filer data. Instead they merely check that you're only requesting data you are authorized for.
Your code already queries only for the public data, so you need to validate that query in your rules with something like:
"shaders": {
".read": "query.orderByChild === 'public' &&
query.equalTo === true"
}
Even with that you will still need separate read operations for the shared that this user created and all public shaders, as there's no way to express that OR condition in a single query.