Joe Roddy
Joe Roddy

Reputation: 1098

Firebase Rules - Allow .update() Only on Certain Fields

Say I have a user collection like so:

users{
    userId1234 : {
        name: "Joe",
        interests: "Programming",
        score: 1337
    }
}

Is it possible to write rules that would allow

let user = {name:"Joey",interests:"Code"};
db.ref("users/").child("userId1234").update(user);

But not allow:

let user = {name:"Joey",interests:"Code",score:9000};
db.ref("users/").child("userId1234").update(user);

Essentially, I want to protect a certain field from being written (score in this example). I know I have the option of moving the field out to another collection, but I'd prefer to be able to do this if possible.

Here are the methods I've tried so far that have not worked:

"users":{
        ".write":"auth!=null",
        "$userId":{
          "score":{".write":false},
          "$otherFields":{".write":"auth != null"}
        }
}

^This blocks writes to /users/userId/score, but it doesn't block /users/userId with an object containing a score attribute.

"users":{
        ".write":"false",
        "$userId":{
          "score":{".write":false},
          "$otherFields":{".write":"auth != null"}
        }
}         

^This allows me to write to the fields correctly, but completely blocks .update().

Thanks! -Joe

Upvotes: 3

Views: 1402

Answers (1)

Joe Roddy
Joe Roddy

Reputation: 1098

My Solution

"users":{
        "$userId":{
          ".write":"auth!=null",
          ".validate":"newData.child('score').val()
                       ===data.child('score').val()",
          "score":{".write":false},
          "$otherFields":{".write":"auth != null"}
        }
}  

".validate": "!newData.hasChildren(['score'])" doesn't work because "newData" is actually the future merge result of the update data, not the raw data being posted, and if you have a score there already, it will fail.

Upvotes: 2

Related Questions