0

I am using firebase database in my app. I have set the rules to allow normal users to create new childs in the node but I found that it's refused.

this is the writing rules of the node :

".write":"auth.uid == \"DFhNb28506Y345CpJ3Ye7DQNn713\" || ((newData.exists() && !data.exists()) || auth.token.email == data.child(\"userEmail\").val())",

I think that newData.exists() && !data.exists() should allow users to write in the database but this doesn't happened

this is the rules of the users node :

    "users":{
  ".write":"auth.uid == \"DFhNb28506Y345CpJ3Ye7DQNn713\" || ((newData.exists() && data.child(\"userEmail\").val() != null) || auth.token.email == data.child(\"userEmail\").val())",
  ".read": "auth != null"
}

The database strucutre is like that :

-users
     -user1
          -userName, userEmail ....
     -user2
          -userName, userEmail .....

when a new user sign up in the app he should be allowed to push his data in the database

this is the database structre :

enter image description here

Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
M.Khaled
  • 49
  • 1
  • 9
  • with this: `newData.exists() && !data.exists()` you're telling me that: 1. `newData` in the current write should exist and 2. that there is nothing already written in the specific "path". Is this correct? Should your user not be able to write when there's already data in there? – Guilherme Matuella Oct 20 '18 at 18:55
  • @GuilhermeMatuella yes and I am using them together to allow users to create new childrens in the users node – M.Khaled Oct 20 '18 at 18:59
  • Well, based on your rules, this `((newData.exists() && !data.exists())` will always be false, because data.exists() will always be true after the first write to the whole database. I think what you want is to nest this check to see if there is something written in the respective user path. Anyways, could you show what is your payload in an write example? Like, I want to know if you're sending the `userEmail` as well. – Guilherme Matuella Oct 20 '18 at 19:07
  • Also, I assume the first comparison is like an Admin UID? – Guilherme Matuella Oct 20 '18 at 19:07
  • @GuilhermeMatuella yes it is – M.Khaled Oct 20 '18 at 19:09
  • @GuilhermeMatuella can you please explain more to me what I should do? – M.Khaled Oct 20 '18 at 19:11
  • Well, I can surely help you, but if you could post the whole database rules and a payload example (the data that you're "posting" from you Web/iOS/Android), that would be much easier to see what's happening – Guilherme Matuella Oct 20 '18 at 19:16
  • 1
    @GuilhermeMatuella I have updated my answer – M.Khaled Oct 20 '18 at 19:19

1 Answers1

0

Ok, I think you're creating extra validation steps that aren't needed.

First

With ".read": "auth != null" on your users root, each user is able to access other user's data, so we should address the access for each user individually.

Second

If you just want to allow users that are authenticated to write and read its own contents, you can remove these extra ((newData.exists() && !data.exists()) and auth.token.email == data.child(\"userEmail\").val()) steps.

Tip: this ((newData.exists() && !data.exists()) comparison means exactly: Write here if you're sending anything but there should be nothing written in this requested "path". You should reflect on the need of this, as I don't know your exact use cases.

Also, I would guess the hardcoded UID you're requesting is of an Admin you've created - I wouldn't recommend this, please read more about user roles on this answer.

To clarify, I think your rules structure should be something like this:

{
  "rules": {
    ".write":"auth.uid == \"DFhNb28506Y345CpJ3Ye7DQNn713\",
    ".read": "auth.uid == \"DFhNb28506Y345CpJ3Ye7DQNn713\",
    "users": {
      "$uid": {
        ".read": "$uid === auth.uid",
        ".write": "$uid === auth.uid"
      }
    }
  }
}
Guilherme Matuella
  • 2,193
  • 1
  • 17
  • 32