5

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?

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
KhoPhi
  • 9,660
  • 17
  • 77
  • 128

1 Answers1

6

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
adolfosrs
  • 9,286
  • 5
  • 39
  • 67
  • Is there another way? What I tried was comparing the uid on the incoming data to the uid of the existing data. – KhoPhi Jun 25 '16 at 12:26
  • I will. Not behind pc at the moment. Thanks for the code snippet. Will try it immediately I get home. – KhoPhi Jun 25 '16 at 12:40
  • Thank you. Now works. I was having a rule ahead that overruled the code write rule for the `$language` part. Thanks – KhoPhi Jun 25 '16 at 13:22
  • @Rexford Nice! glad you made progress :) – adolfosrs Jun 25 '16 at 13:25
  • Only problem at the moment is, I can't write to the /codes/$codeId url, because there's no write rule, and no write rule means no write. Any idea how to fix that? – KhoPhi Jun 25 '16 at 13:28
  • 1
    @Rexford take a look at the edit and let me know if you have any doubt. – adolfosrs Jun 25 '16 at 13:59
  • Okay, that explains a huge limitation with firebase rules, the fact that they don't filter. Instead of filtering, they could simply be made to accumulate down the line. Well, thanks for the answer. Marking correct! – KhoPhi Jun 25 '16 at 14:10
  • It might be helpful to explain the logic behind the write rule and why it works. – KhoPhi Jun 27 '16 at 14:42
  • @Rexford Sure. Let me know if my edit makes things more "straight-ahead". Thanks – adolfosrs Jun 27 '16 at 16:01