1

I have a static web page application (no backend server), that uses Firebase as User's database (javascript client). The database has the following structure:

{
  users:
  {
     $userId:{
       ///private user data
     }
  },
  project:
  {
     $projectId:{
        data:{...},
        permissions:{
           $userId:"owner"|"read"|"write"
        }
     }
  }
}

And user only have access to his private data and projects where his Id is mentioned in project's permissions. Here is security RULES:

{
  "rules": {
    "users": {
      "$uid": {
        ".read": "$uid === auth.uid",
        ".write": "$uid === auth.uid"
      }
    },
    "project":{
        "$projectId":
        {
          ".write":"auth!=null && (!data.exists() || root.child('project/'+$projectId+'/permissions/'+auth.uid).val()==='owner')",
          ".read":"root.child('project/'+$projectId+'/permissions/'+auth.uid).val()!==null",
          "data":{
            ".write":"root.child('project/'+$projectId+'/permissions/'+auth.uid).val()==='write'"
          }
        }
    }
  }
}

QUESTION:

How can I query all projects by UserId? where project.permissions.contains(userId) Or at least how to get all subkeys current user has permissions to read?

If I query just this:

let query = firebaseApp.database().ref("/project").orderByKey();
let val = await query.once("value");

it throws an error "Error: permission_denied at /project: Client doesn't have permission to access the desired data."

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
Philipp Munin
  • 5,610
  • 7
  • 37
  • 60
  • Is the user Id is default key of generated timestamp like this `-L2Wu0suIqJrev1vL4pK` or user defined by your code – Himanshu Jan 11 '18 at 12:52
  • it's the Id generated by Authentication provider (GoogleAuthProvider in my case) – Philipp Munin Jan 11 '18 at 12:58
  • do you know userid or projectId in advance ? – Himanshu Jan 11 '18 at 13:04
  • I know UserId (auth.uid), and my goal is to query all project Ids, which match the rule ~/project/$projectId/permissions/{auth.uid}.exists() – Philipp Munin Jan 11 '18 at 13:07
  • 1
    If you attach a listener to `/project`, then Firebase will check whether you have read permission on `/project`. Since you don't, the listener is rejected. With your current rules, the user can only read a specific project. Nobody can read `/project`. If you move the read permission up to `/project`, then everyone can read all projects. This is because Firebase rules cannot be used to filter data. Have a look at https://firebase.google.com/docs/database/security/securing-data#rules_are_not_filters in the documentation, and this question http://stackoverflow.com/a/14298525/209103 – Frank van Puffelen Jan 11 '18 at 14:35
  • thanks for response. So how should I structure my data and change rules to get this simple use case working? This use case is very similar to the chat use case, where user should see only rooms he has access to or see messages that directed to him only. – Philipp Munin Jan 11 '18 at 15:20

0 Answers0