Firebase Database Rules for groups

前端 未结 2 760
盖世英雄少女心
盖世英雄少女心 2021-01-01 05:56

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

The JSON of that DB is:

{
  \"groups\": {
    \"1\": {
      \"name\": \"G1\",
         


        
相关标签:
2条回答
  • 2021-01-01 06:13

    What if you try nested rules for the "points" and "visits" levels:

    "groups": {          
      "$groupId": {
        ".read": "root.child('userGroups').child(auth.uid).child($groupId).exists()",
        ".write": "root.child('userGroups').child(auth.uid).child($groupId).val() == 'admin'",
        "points": {
          ".write": "root.child('userGroups').child(auth.uid).child($groupId).val() != 'readonly'"
        },
        "visits": {
          ".write": "root.child('userGroups').child(auth.uid).child($groupId).val() != 'readonly'"
        }
      }
    },
    "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"          
      }
    }
    
    0 讨论(0)
  • 2021-01-01 06:16

    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:

    • Can write to /groups/1/name because they're admin of group 1
    • Can write to /groups/2/points because they're admin of group 1
    • Can't write to /groups/2/name because they're not an admin of group 2
    • Can write to /groups/2/points because they're a readwrite member of group 2
    0 讨论(0)
提交回复
热议问题