Firebase: définir des règles de sécurité en fonction des rôles de l'utilisateur

Je voudrais implémenter des règles de sécurité "write" dans Firebase en fonction des rôles des utilisateurs.
Ma structure de données est comme ceci:

+ myapp
  + users
    + john
      + email: "john@mail.com"
      + roles
        + administrator: true
    + mary
      + email: "mary@mail.com"
      + roles
        + moderator: true
    + ...
  + documents
    + -JVmo6wZM35ZQr0K9tJu
      + ...
    + -JVr56hVTZxlAI5AgUaS
      + ...
    + ...

Je veux, par exemple, que seuls les utilisateurs administrateurs puissent écrire des documents.
Voici les règles auxquelles je suis arrivé:

{
  "rules": {
    ".read": true,
    "$documents": {
      ".write": "root.child('users').child(auth.uid).child('roles').child('administrator').val() === true"
    }
  }
}

Mais cela ne fonctionne pas: même les utilisateurs administrateurs ne peuvent pas écrire de documents...
Ma compréhension des règles de sécurité Firebase est-elle totalement imparfaite?

mise à JOUR: Juste avant la réponse de Jenny (croyez-le ou non: -), j'ai implémenté exactement la même solution qu'il fournit (bien sûr basé sur le commentaire de Kato).
Bien que, faisant quelques tests, Je ne pouvais pas laisser la structure des règles

{
  "rules": {
    "documents" {
      "$document" {
        ".read": "root.child('users').child(auth.uid).child('roles').child('documents').child('read').val() === true",
        ".write": "root.child('users').child(auth.uid).child('roles').child('documents').child('write').val() === true"
      }
    }
  }
}

Travail... J'ai toujours eu un avertissement comme celui-ci:

"FIREBASE WARNING: on() or once() for /documents failed: Error: permission_denied: Client doesn't have permission to access the desired data. "

Donc je suis venu avec cette structure, à la place:

{
  "rules": {
    "documents" {
      ".read": "root.child('users').child(auth.uid).child('roles').child('documents').child('read').val() === true",
      ".write": "root.child('users').child(auth.uid).child('roles').child('documents').child('write').val() === true"
    }
  }
}

Ce qui fonctionne en effet, pour moi: si je mets un nœud roles / customers / read à true sur un utilisateur, il peut lire tous les documents, sinon il ne peut pas (et la même chose pour l'écriture).

Mes doutes sont maintenant:

  • pourquoi je ne pouvais pas laisser la première règle (comme suggéré par Kato) travailler?
  • voyez - vous un trou de sécurité possible dans une règle comme celle que j'ai trouvée?
  • les règles utilisant des variables " $ " sont-elles nécessaires / utiles même si vous n'avez pas à autoriser / refuser la lisibilité/l'écriture de chaque single document basé sur sa clé, mais vous voulez juste autoriser / refuser le lisibilité / écriture d'un nœud dans son ensemble?
24
demandé sur MarcoS 2014-09-03 13:48:11

1 réponses

En fonction des noms de vos enregistrements utilisateur, ils ne correspondent pas à auth.uid, qui est probablement un identifiantsimple Login , tel que twitter:2544215.

Commencez par ajuster vos utilisateurs pour qu'ils soient stockés par leur simple UID de connexion:

+ myapp
  + users
    + twitter:2544215
      + email: "john@mail.com"
      + roles
        + administrator: true
    + twitter:2544216
      + email: "mary@mail.com"
      + roles
        + moderator: true
    + ...
  + documents
    + -JVmo6wZM35ZQr0K9tJu
      + ...
    + -JVr56hVTZxlAI5AgUaS
      + ...
    + ...

Ensuite, ajoutez une règle de sécurité afin que les administrateurs puissent accéder à documents. Vous avez quelques options ici, en fonction de votre cas d'utilisation spécifique.

  1. Pour donner aux administrateurs un accès en écriture au contenu de chaque document:

    {
      "rules": {
        "documents": {
          "$documents": {
            ".write": "root.child('users').child(auth.uid).child('roles').child('administrator').val() === true"
          }
        }
      }
    }
    
  2. Ou, alternativement, leur donner accès à l'ensemble de la collection:

    {
      "rules": {
        "documents": {
          ".write": "root.child('users').child(auth.uid).child('roles').child('administrator').val() === true"
        }
      }
    }
    

La différence entre ces deux étant la variable $documents qui déplace la règle de sécurité un peu plus loin dans la hiérarchie.

(c'était surtout une agrégation des commentaires de @ Kato en forme de réponse)

27
répondu mimming 2014-09-12 18:02:57