Patrick Riemer
Patrick Riemer

Reputation: 187

Firebase security rules for child items in arrays

I have the following data structure in my firebase:

{
    "groups" : {
        "-KEFQ7rTQscPX4hqn6ec" : {
          "createdBy" : "b5cd3a86-108e-4ef3-9ab8-8a1e4da7491c",
          "description" : "Test",
          "isPublic" : true,
          "title" : "T1"
        },
        "-KEFQao_Wd-Y-nLzIx2e" : {
          "createdBy" : "b5cd3a86-108e-4ef3-9ab8-8a1e4da7491c",
          "description" : "B",
          "isPublic" : false,
          "title" : "E"
        }
}

and am trying to achieve the following:

  1. Everybody can read all groups with "isPublic" == true
  2. Only logged in users can see the groups that they have created

My first approach is:

{
  "rules": {
    "groups": {
      ".read": true,
      "$id": {
        ".read": "data.child('isPublic').val() === true"
        }
      }
  }
}

This stackoverflow post explains why it doesn't work, but I couldn't figure out how I can make it work.

Edit 1:

This post has a solution for the public/private problem (my 1. question) but not for the second question.

Edit 2:

Thanks to @VonD for the working solution for the public/private problem.

With this solution the problem with public/private is solved. Considering that a private group has many members and the user ids of them would be stored in another array "members" - how would I only allow access to the group if I am a member?

"privateGroups": {
        "b5cd3a86-108e-4ef3-9ab8-8a1e4da7491c": {
            "-KEFQao_Wd-Y-nLzIx2e" : {
                "createdBy" : "b5cd3a86-108e-4ef3-9ab8-8a1e4da7491c",
                "description" : "B",
                "title" : "E",
                "members": [userId1, userId2, userId3...]
            }
        }
    }

Upvotes: 0

Views: 943

Answers (1)

VonD
VonD

Reputation: 5155

The required security rules cannot be implemented with your document structure : if you want to express that a given user can read some of the child documents of a given node, the user will only be able to access them with their full path, for example "groups/-KEFQao_Wd-Y-nLzIx2e", but he will not be able to retrieve a list of groups matching the given criteria (unless of course you maintain at a different path a list of the groups the user can access, which means you would duplicate all public groups ids for each user).

A document structure that would better fit firebase security rules would be :

{
    "publicGroups": {
        "-KEFQ7rTQscPX4hqn6ec" : {
            "createdBy" : "b5cd3a86-108e-4ef3-9ab8-8a1e4da7491c",
            "description" : "Test",
            "title" : "T1"
        }
    },
    "privateGroups": {
        "b5cd3a86-108e-4ef3-9ab8-8a1e4da7491c": {
            "-KEFQao_Wd-Y-nLzIx2e" : {
                "createdBy" : "b5cd3a86-108e-4ef3-9ab8-8a1e4da7491c",
                "description" : "B",
                "title" : "E"
            }
        }
    }
} 

Security rules would then be easy to implement:

{
    "publicGroups": {
        ".read": true
    },
    "privateGroups": {
        "$userId": {
            ".read": "auth.uid === $userId"
        }
    }
}

Hope it helps.

Upvotes: 3

Related Questions