I have this Firebase DB which could be changed if necessary:

The JSON of that DB is:
{
  "groups": {
    "1": {
      "name": "G1",
      "points": {
        "1": {
            "name": "p1"
        }
      },
      "visits": {
        "1": {
            "name": "v1"
        }
      },
      "areas": {
        "1": {
            "name": "a1"
        }
      },
      "waypoints": {
        "1": {
            "name": "w1"
        }
      },
      "interests": {
        "1": {
            "name": "i1"
        }
      }
    },
    "2": {
      "name": "G2",
      "points": {
        "2": {
            "name": "p2"
        }
      },
      "visits": {
        "2": {
            "name": "v2"
        }
      },
      "areas": {
        "2": {
            "name": "a2"
        }
      },
      "waypoints": {
        "2": {
            "name": "w2"
        }
      },
      "interests": {
        "2": {
            "name": "i2"
        }
      }
    }
  },
  "users": {
    "qdRw1khg1ZO1s52YioYCdM4WrD02": {
      "firstName": "AAAA",
      "lastName": "BBB",
      "email": "[email protected]"     
    },
    "h3KYDXkPQrY246w6Y6NXIanVoNS2": {
      "firstName": "FF",
      "lastName": "RR",
      "email": "[email protected]"
    }
  },
  "userGroups": {
    "qdRw1khg1ZO1s52YioYCdM4WrD02": {
      "1": "admin",
      "2": "readwrite"
    },
    "h3KYDXkPQrY246w6Y6NXIanVoNS2": {
      "1": "admin",
      "2": "readonly"     
    }
  }
}
I want to define rules to accomplish the following:
I have:
"groups": {          
  "$groupId": {
    ".read": "root.child('userGroups').child(auth.uid).child($groupId).exists()",
    ".write": "! root.child('userGroups').child(auth.uid).child($groupId).exists() || 
                          (data.parent().val() === 'points' && root.child('userGroups').child(auth.uid).child($groupId).val() != 'readonly') ||
                        (data.parent().val() === 'visits' && root.child('userGroups').child(auth.uid).child($groupId).val() === 'readonly') ||
                        (data.parent().val() != 'points' && data.parent().val() != 'visits' && root.child('userGroups').child(auth.uid).child($groupId).val() === 'admin')"
  }
},
"users": {
  "$userId": {
    ".read": "auth != null",
    ".write": "auth != null && 
              $userId === auth.uid && 
              newData.val() != null"
  }
},
"userGroups": {
  "$userId": {
    ".read": "auth != null",
    ".write": "auth != null && 
               data.child(auth.uid).val() === 'admin' && 
               newData.val() != null"          
  }
}
But that does not work since
data.parent().val()
does not return the parent's name string. So I can't do
data.parent().val() != 'points'
How to solve this? The problem is writing data to groups according to the rules specified.
Firebaser here. Expect this answer to be updated as I go along.
My first step is to move the rules for the specific child nodes into that specific child node. That removes the parent() problem you've been having. First iteration is:
  "groups": {          
    "$groupId": {
      ".read": "root.child('userGroups').child(auth.uid).child($groupId).exists()",
      "points": {
        ".write": "root.child('userGroups').child(auth.uid).child($groupId).val() !== 'readonly'"
      }
    }
  },
This allows user h3KYDXkPQrY246w6Y6NXIanVoNS2 to write to /groups/1/points (of which the user is an admin), but not to /groups/2/points (to which the user only has readonly access).
A next step is to make the rule more generic. To do this I introduce a $child variable, which matches any node under the group:
  "groups": {          
    "$groupId": {
      ".read": "root.child('userGroups').child(auth.uid).child($groupId).exists()",
      "$child": {
        ".write": "root.child('userGroups').child(auth.uid).child($groupId).val() !== 'readonly'
                   || ($child !== 'points' && $child !== 'visits')"
      }
    }
This allows user h3KYDXkPQrY246w6Y6NXIanVoNS2 to write to /groups/2/name (which is writeable by any group member), but not to /groups/2/points (to which the user only has readonly access).
Update: apparently I inverted your logic above, so here's my final take:
  "groups": {          
    "$groupId": {
      ".read": "root.child('userGroups').child(auth.uid).child($groupId).exists()",
      ".write": "root.child('userGroups').child(auth.uid).child($groupId).val() == 'admin'",
      "$child": {
        ".write": "root.child('userGroups').child(auth.uid).child($groupId).val() === 'readwrite'
                   && ($child !== 'points' || $child !== 'visits')"
      }
    }
With this user h3KYDXkPQrY246w6Y6NXIanVoNS2:
/groups/1/name because they're admin of group 1/groups/2/points because they're admin of group 1/groups/2/name because they're not an admin of group 2/groups/2/points because they're a readwrite member of group 2If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With