To illustrate my use case, consider a two-way relationship between users and groups. Users can belong to a group, and groups comprise a list of users.
{
"users": {
"alovelace": {
"name": "Ada Lovelace",
"groupId": "techpioneers",
},
"eclarke": {
"name": "Edmund M. Clarke"
},
// ...
},
"groups": {
"techpioneers": {
"name": "Historical Tech Pioneers",
"members": {
"alovelace": true,
"ghopper": true
}
},
// ...
}
}
To associate eclarke to a group, the client should update both paths (/users/eclarke/groupId and /groups/techpioneers/members/eclarke) in a single update so that there's no intermidiate invalid state.
To ensure this, I set the security rules for each path to reference each other:
{
"rules": {
"users": {
"$userId": {
"groupId": {
".validate": "newData.parent().parent().parent().child('groups').child(newData.val()).child('members').hasChild($userId)"
}
}
},
"groups": {
"$groupId": {
"members": {
"$memberId": {
".validate": "newData.parent().parent().parent().child('users').child($memberId).child('groupId').val() === $groupId"
}
}
}
}
}
}
I cannot use root here becaue I would be looking at old database state.
Is there a better way to do this? (without having to make multiple .parent() calls)