skip to Main Content

My rules look like this:

{
  "rules": {
    "userShaders": {
      "$uid": {
        "shaders": {
          ".write": "auth.uid === $uid",
          ".read": "auth.uid === $uid || data.child('public').val() == true"
        }        
      }
    }
  }
}

My data looks like this:

userShaders
  8v4N3yLlXAU1cpRiaDj5kkDQaKn1
    shaders
      myShaderName
        attr_1: ""
        attr_2: ""
        public: false

I am not logged in as this user and am attempting to query their data. I expect to succesfully get back 0 records because they have none marked as public.

However, I’m getting a permission denied error.

My query looks like this:

val shaderRef = db
 .getReference("userShaders/${uid}/shaders")
 .orderByChild("public")
 .equalTo(true);

shaderRef.get().addOnSuccessListener {
 // do something with the data
}

To summarize, I am trying to query for only public data, while simultaneously making a rule that non-public data is impossible to fetch by other users. I want to write a query such that I may receive 0 or many records back, but never a permission denied error.

2

Answers


  1. Chosen as BEST ANSWER

    Well, I ended up just separating my data into separate public and private sections in Firebase like this:

        "userShaders": {
          "$uid": {
            "shaders": {
              "public": {
                ".write": "auth.uid === $uid",
                ".read": "true"            
              },
              "private": {
                ".write": "auth.uid === $uid",
                ".read": "auth.uid === $uid"            
              },            
            }        
          }
        }
    

    It's more work, because when I update the isPrivate boolean I have to make sure to delete it from the other section, but it does get the job done.

    Open to other answers if there's another way to do this.


  2. The most important thing to realize is that Firebase security rules don’t filer data. Instead they merely check that you’re only requesting data you are authorized for.

    Your code already queries only for the public data, so you need to validate that query in your rules with something like:

    "shaders": {
      ".read": "query.orderByChild === 'public' &&
                query.equalTo === true"
    }
    

    Even with that you will still need separate read operations for the shared that this user created and all public shaders, as there’s no way to express that OR condition in a single query.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search