Understanding Firebase Rules for Custom Write, Global Read

I am building a simple Firebase app using AngularJS. This application authenticates users through Google. Each user has a list of books. Anyone can see books, even if they are not authenticated. The editor can only edit the book creator. However, individual users should be able to record that they have read the book, even if someone has added it.

I have it rules.json

like this:

{
  "rules": {
    ".read": false,
    ".write": false,
    "book": {
      "$uid": {
        ".write": "auth !== null && auth.uid === $uid",
      }
      ".read": true,
    }
  }
}

      

And I am trying to write a book simply with

$firebaseArray(new Firebase(URL + "/book")).$add({foo: "bar"})

      

When I try to do this, I get a permission resolved error, although I seem to be able to use read

books that I manually create in Forge.

I also think that the best way to store readers is to make it the property of the book (set $uid

for registered readers). ".write"

it looks like it is blocking this, so how can I do this?

"$uid": {
  ".write": "auth !== null && auth.uid === $uid",
  "readers": {
    ".write": "auth !== null"
  }
},

      

It seems that the correct validation rule would also be appropriate ... something like newData.val() == auth.uid

, but I'm not sure how to check what readers

should be an array (or specifically a set) of these values.

+3


source to share


2 answers


Let's start with a sample JSON snippet:

  "book": {
    "-JRHTHaIs-jNPLXOQivY": { //this is the generated unique id
      "title": "Structuring Data",
      "url": "https://www.firebase.com/docs/web/guide/structuring-data.html",
      "creator": "twiter:4916627"

    },
    "-JRHTHaKuITFIhnj02kE": {
      "title": "Securing Your Data",
      "url": "https://www.firebase.com/docs/security/guide/securing-data.html",
      "creator": "twiter:209103"
    }
  }

      

So this is a list with two links to articles. Each link has been added by a different user who is identified creator

. The value creator

is equal uid

, which is the value provided by Firebase Authentication and which is available in your security policy under auth.uid

.

I will divide your rule into two parts:

{
  "rules": {
    ".read": false,
    "book": {
      ".read": true,
    }
  }
}

      

As far as I understand, your rule is .read

correct as your ref refers to the / book node.

$firebaseArray(new Firebase(URL + "/book"))

      

Please note that the link below will not work as you do not have read access to the top level node.

$firebaseArray(new Firebase(URL))

      



Now for the rules .write

. First of all, you will need to grant users write access at the level book

already. The call $add

means you are adding a node below that level, so write access is required.

{
  "rules": {
    "book": {
      ".write": "auth != null"
    }
  }
}

      

I leave the rules here .read

for clarity.

This allows any authenticated user to write to the book node. This means they can add new books (which you want) and modify existing books (which you don't need).

Your last requirement is the hardest. Anyone can add a book. But as soon as someone added a book, only that person can change it. In Firebase security rules, you would simulate for example:

{
  "rules": {
    "book": {
      ".write": "auth != null",
      "$bookid": {
        ".write": "!data.exists() || auth.uid == data.child('creator').val()"
      }
    }
  }
}

      

In this last rule, we allow a specific book to be written if there is no current data at that location (i.e. this is a new book) or if the data was created by the current user.

In the above example $bookid

, it is just a variable name. The important thing is that the rule below it applies to every book. If necessary, we could use $bookid

in our rules and it will contain -JRHTHaIs-jNPLXOQivY

or -JRHTHaKuITFIhnj02kE

accordingly. But in this case it is not required.

+7


source


Disable permission deny first. You are getting this error because you are trying to write directly to the "book" node instead of "book / $ uid".

An example of what you are doing now:

  "book": {
    "-JRHTHaIs-jNPLXOQivY": { //this is the generated unique id
      "foo": "bar"
    },
    "-JRHTHaKuITFIhnj02kE": {
      "foo": "bar"
    }
  }

      



In your rules, you have a global rule for write set to false, so it will be the default and next to you you will create a rule for a specific book node book / $ uid. So when you try to write directly in the "book", it will use the default rule, which is set to false. See "Protecting Your Data" for more information on firebase rules.

And for the last part of your question, I suggest you take a look at Data Structuring for more information on the best ways to structure your data inside firebase.

So, so have a good look at what and how you want to save and write to firebase and make sure your rules are structured accordingly.

+2


source







All Articles