Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to only allow the user who “owns” the data to edit it? firebase

I have this data structure:

enter image description here

I want to have a Firebase rule that allow user who owns a code snippet to be able to edit, but no one else. So in a way, it'll work like:

  • Before data is added, everyone has access to add particular language
  • When and after added, only 'owner' is allowed to edit

How will I go about in allowing only the user who created, say the Javascript snippet to edit it?

like image 760
KhoPhi Avatar asked Jun 25 '16 09:06

KhoPhi


1 Answers

If I correctly understood what you are looking for your $language write rules will look like this:

{"rules":{
    "codes":{
        "$codeId":{
            "snippets":{
                "$language":{
                    ".write": "(!data.exists() && newData.child('uid').val() == auth.uid ) || (data.child('uid').val() == auth.uid && newData.child('uid').val() == auth.uid)"
                }
            }
        }
    }
    }
}

Update:

After adding that you still want a write rule on /codes/$codeId I strongly recommend you to move the snippets branch from the codes branch since you are adding to much complexity to one single node. You will start having this complex rules logic to deal with and your application code also will become overwhelmed by this structure.

Try to work with something more uncoupled such as the structure bellow:

{
    "rules":{
        "codes":{
            "$codeId":{
                ".write": "true",
                "snippets":{
                    "$snippetID":{
                    }
                }
            }
        },
        "snippets":{
            "$snippetID":{
                "$language":{
                    ".write": "(!data.exists() && newData.child('uid').val() == auth.uid ) || (data.child('uid').val() == auth.uid && newData.child('uid').val() == auth.uid)"
                }
            }
        }
    }
}

Explanations

As requested I'm adding some details for this specific write logic.

From the requirements I got that the user can write if he is writing a new data OR he "owns" the data he is trying to write.

!data.exists() || data.child('uid').val() == auth.uid

Since "owning" a data means that this data has the owner uid as a child I then assumed that if he is writing a data the user uid needs always to be there. Thats why I've added the newData.child('uid').val() == auth.uid. (remembering that newData means the data the user is attempting to write).

(!data.exists() && newData.child('uid').val() == auth.uid ) || (data.child('uid').val() == auth.uid && newData.child('uid').val() == auth.uid)

I could normalize it as bellow to avoid the newData check in both sides of the logic but, at least to me, it makes it much more clear for understading.

 (!data.exists() || data.child('uid').val() == auth.uid) && newData.child('uid').val() == auth.uid
like image 62
adolfosrs Avatar answered Nov 25 '22 07:11

adolfosrs