".read" firebase security rules

9

I've created the following security framework in Realtime Database:

{
  "rules": {
    "receita": {
      "$chave": { 
        ".write": "auth.uid === newData.child('usuario').val()",
        ".read": "auth.uid === data.child('usuario').val() || data.child('tipo').val() === true"
      }
    }
  }
}

For the following data structure in the database:

{
  "receita" : {
    "-L92JgTg4xIDCymtq26h" : {
      "imagem" : "default",
      "ingrediente" : [ "teste" ],
      "nome" : "teste",
      "preparo" : "teste",
      "tipo" : true,
      "usuario" : "Az2Mra1xJwXtpaspGwgvj7hm9NA2"
    },
    "-L9CwBmuVETG5TSjLHz7" : {
      "imagem" : "default",
      "ingrediente" : [ "teste" ],
      "nome" : "teste",
      "preparo" : "teste",
      "tipo" : true,
      "usuario" : "Az2Mra1xJwXtpaspGwgvj7hm9NA2"
    }
  }
}

Using Authentication with Google Provider

The ".write" works perfectly, but the ".read" does not (permission error), I've already changed the same to:

".read": true //Leitura pública

But also did not work, I believe the error is in the structure of my rule but I do not know where

To "work", I've changed the rules to:

{
  "rules": {
    "receita": {
      "$chave": { 
        ".write": "auth.uid === newData.child('usuario').val()"
      },
      ".read": "true"
    }
  }
}

I tested it that way too, but without success:

".read": "auth.uid === data.child($chave + '/usuario').val() || data.child($chave + '/tipo').val() === true"

With the structured rules of the first way, I tried to fetch the data as follows:

firebase.database().ref('receita').once('value').then(function(snapshot) {
    console.log(snapshot.val())
})

But it results in the permission error, but doing the same passing a valid key for reference works:

firebase.database().ref('receita/-L8UX8Ajz8P1XcudJUih').once('value').then(function(snapshot) {
    console.log(snapshot.val())
})

Then the error is when I get a reference from the database because in the recipe directory ( /receita ), I do not have any rules, only in /receita/$chave

    
asked by anonymous 31.03.2018 / 20:16

2 answers

0

I was able to solve the problem by changing the structure of the database, dividing the data access information and the data itself.

Bank structure:

{
  "receita" : {
    "acesso" : {
      "-L92JgTg4xIDCymtq26h" : {
        "tipo" : true,
        "usuario" : "Az2Mra1xJwXtpaspGwgvj7hm9NA2"
      },
      "-L9CwBmuVETG5TSjLHz7" : {
        "tipo" : true,
        "usuario" : "Az2Mra1xJwXtpaspGwgvj7hm9NA2"
      }
    }
    "dados" : {
      "-L92JgTg4xIDCymtq26h" : {
        "imagem" : "default",
        "ingrediente" : [ "teste" ],
        "nome" : "teste",
        "preparo" : "teste"
      },
      "-L9CwBmuVETG5TSjLHz7" : {
        "imagem" : "default",
        "ingrediente" : [ "teste" ],
        "nome" : "teste",
        "preparo" : "teste"
      }
    }
  }
}

Bank rules:

{
  "rules": {
    "receita": {
      "acesso": {
        ".read": true,
        "$chave": {
          ".write": "data.exists() && auth.uid === data.child('usuario').val() || !data.exists() && auth.uid === newData.child('usuario').val()"
        },
        ".indexOn": ["usuario", "tipo"]
      },
      "dado": {
        "$chave": {
          ".write": "auth.uid === root.child('receita/acesso/' + $chave + '/usuario').val()",
          ".read": "auth.uid === root.child('receita/acesso/' + $chave + '/usuario').val() || root.child('receita/acesso/' + $chave + '/tipo').val() === true",
          ".indexOn": "nome"
        }
      }
    }
  }
}

In this way, the access data is public, however to see the data of the recipes is necessary the permission

    
26.05.2018 / 20:25
4
  

So the error is when you get a reference from the bank because in the directory   recipe, I do not have any rules, only in   / recipe / $ key

That's right!

To resolve this problem, you can use query-based rules .

For the user to see all your recipes (public or private), you would do the query:

firebase.database().ref('receita').orderByChild('usuario').equalTo(currentUser.uid)
.once('value').then(function(snapshot) {
    console.log(snapshot.val())
})

For the user to see only public revenue:

firebase.database().ref('receita').orderByChild('tipo').equalTo(true)
.once('value').then(function(snapshot) {
    console.log(snapshot.val())
})

Then just indicate in the rules that only these 2 queries are allowed:

{
    "rules":{
        "receita":{
            ".read":"(query.orderByChild == 'usuario' && query.equalTo == auth.uid) || (query.orderByChild == 'tipo' && query.equalTo == true)",
            "$chave":{
                ".write":"auth.uid === newData.child('usuario').val()"
            }
        }
    }
}
    
09.04.2018 / 17:27