I’m trying to create security rules for the “Save data as transactions” blogging app example from the Firebase guide.
The user can increase or decrease the star count for a post, having his own UID being included or removed from the node at the same time.
I’ve written the following rules: (I removed the rules for the counter increase/decrease since they are out of the scope of the question)
“stars”: {
".read": true,
"$postId”: {
".write": "auth != null && (newData.child('users').child(auth.uid).exists() || data.child('users').child(auth.uid).exists())",
"users": {
"$userId": {
".validate": "$userId === auth.uid"
}
}
}
}
And an exemple of a stars node:
“stars”: {
“postId1”: {
starCount: 2,
"users": {
“userId1”: true,
“userId2”: true
}
}
}
The rules work fine for adding an user to the “users” node, but a problem arises when removing.
It’s possible for a mean-spirited user to remove any other user from the “users” node, just update it with a empty node. Or a node with all the users from before, minus one he chose to remove. The “.validate” rule ("$userId === auth.uid") does not work for a empty node being submited and I can't write a rule that checks if all the users that were in the database before the update are still there after.
The way I’d solve the problem if I wasn’t using transactions was to to move the “.write” rule to under “$userId”, limiting the uptate for only one user at a time and only with the same UID as the logged user.
Something like:
“stars”: {
".read": true,
"$postId”: {
"users": {
"$userId": {
".write": "auth != null && $userId === auth.uid"
}
}
}
"starCount": {
".write": true
}
But since I’m doing the database update using transactions I need the “.write” rule under the "$postId”, permitting the update of the “users” node and the “starCount” node at the same time. Something that would not be possible in my last exemple (no “.write” rule under "$postId”).
So it seem like a Catch-22. Or I use transactions but I’m not able to secure the starCount with rules, or I do it as a normal multi-update but loose the concurrency benefits for increasing the counter.
How can I correctly secure the “Save data as transactions” blogging app exemple?