Catch up on everything announced at Firebase Summit, and learn how Firebase can help you accelerate app development and run your app with confidence. Learn More

Condições de gravação para regras de segurança do Cloud Firestore

Mantenha tudo organizado com as coleções Salve e categorize o conteúdo com base nas suas preferências.

Este guia se baseia no guia de estruturação de regras de segurança para mostrar como adicionar condições às regras de segurança do Cloud Firestore. Se você não estiver familiarizado com os fundamentos das regras de segurança do Cloud Firestore , consulte o guia de primeiros passos.

O elemento básico básico das regras de segurança do Cloud Firestore é a condição. Uma condição é uma expressão booleana que determina se uma determinada operação deve ser permitida ou negada. Use regras de segurança para escrever condições que verificam a autenticação do usuário, validam os dados recebidos ou até mesmo acessam outras partes do seu banco de dados.

Autenticação

Um dos padrões de regra de segurança mais comuns é controlar o acesso com base no estado de autenticação do usuário. Por exemplo, seu aplicativo pode permitir que apenas usuários conectados gravem dados:

service cloud.firestore {
  match /databases/{database}/documents {
    // Allow the user to access documents in the "cities" collection
    // only if they are authenticated.
    match /cities/{city} {
      allow read, write: if request.auth != null;
    }
  }
}

Outro padrão comum é garantir que os usuários só possam ler e gravar seus próprios dados:

service cloud.firestore {
  match /databases/{database}/documents {
    // Make sure the uid of the requesting user matches name of the user
    // document. The wildcard expression {userId} makes the userId variable
    // available in rules.
    match /users/{userId} {
      allow read, update, delete: if request.auth != null && request.auth.uid == userId;
      allow create: if request.auth != null;
    }
  }
}

Se seu aplicativo usa Firebase Authentication ou Google Cloud Identity Platform , a variável request.auth contém as informações de autenticação para o cliente que solicita dados. Para obter mais informações sobre request.auth , consulte a documentação de referência .

Data de validade

Muitos aplicativos armazenam informações de controle de acesso como campos em documentos no banco de dados. As regras de segurança do Cloud Firestore podem permitir ou negar acesso dinamicamente com base nos dados do documento:

service cloud.firestore {
  match /databases/{database}/documents {
    // Allow the user to read data if the document has the 'visibility'
    // field set to 'public'
    match /cities/{city} {
      allow read: if resource.data.visibility == 'public';
    }
  }
}

A variável resource refere-se ao documento solicitado e resource.data é um mapa de todos os campos e valores armazenados no documento. Para obter mais informações sobre a variável de resource , consulte a documentação de referência .

Ao gravar dados, você pode querer comparar os dados recebidos com os dados existentes. Nesse caso, se seu conjunto de regras permitir a gravação pendente, a variável request.resource conterá o estado futuro do documento. Para operações de update que apenas modificam um subconjunto dos campos do documento, a variável request.resource conterá o estado do documento pendente após a operação. Você pode verificar os valores dos campos em request.resource para evitar atualizações de dados indesejadas ou inconsistentes:

service cloud.firestore {
  match /databases/{database}/documents {
    // Make sure all cities have a positive population and
    // the name is not changed
    match /cities/{city} {
      allow update: if request.resource.data.population > 0
                    && request.resource.data.name == resource.data.name;
    }
  }
}

Acesse outros documentos

Usando as funções get() e exists() , suas regras de segurança podem avaliar as solicitações recebidas em relação a outros documentos no banco de dados. As funções get() e exists() esperam caminhos de documento totalmente especificados. Ao usar variáveis ​​para construir caminhos para get() e exists() , você precisa escapar explicitamente das variáveis ​​usando a sintaxe $(variable) .

No exemplo abaixo, a variável do database de dados é capturada pela instrução match /databases/{database}/documents e usada para formar o caminho:

service cloud.firestore {
  match /databases/{database}/documents {
    match /cities/{city} {
      // Make sure a 'users' document exists for the requesting user before
      // allowing any writes to the 'cities' collection
      allow create: if request.auth != null && exists(/databases/$(database)/documents/users/$(request.auth.uid))

      // Allow the user to delete cities if their user document has the
      // 'admin' field set to 'true'
      allow delete: if request.auth != null && get(/databases/$(database)/documents/users/$(request.auth.uid)).data.admin == true
    }
  }
}

Para gravações, você pode usar a função getAfter() para acessar o estado de um documento após a conclusão de uma transação ou lote de gravações, mas antes da confirmação da transação ou lote. Como get() , a função getAfter() usa um caminho de documento totalmente especificado. Você pode usar getAfter() para definir conjuntos de gravações que devem ocorrer juntas como uma transação ou lote.

Limites de chamadas de acesso

Há um limite de chamadas de acesso a documentos por avaliação de conjunto de regras:

  • 10 para solicitações de documento único e solicitações de consulta.
  • 20 para leituras de vários documentos, transações e gravações em lote. O limite anterior de 10 também se aplica a cada operação.

    Por exemplo, imagine que você cria uma solicitação de gravação em lote com 3 operações de gravação e que suas regras de segurança usam 2 chamadas de acesso a documentos para validar cada gravação. Nesse caso, cada gravação usa 2 de suas 10 chamadas de acesso e a solicitação de gravação em lote usa 6 de suas 20 chamadas de acesso.

Exceder um dos limites resulta em um erro de permissão negada. Algumas chamadas de acesso a documentos podem ser armazenadas em cache e as chamadas armazenadas em cache não contam para os limites.

Para obter uma explicação detalhada de como esses limites afetam transações e gravações em lote, consulte o guia para proteger operações atômicas .

Acessar chamadas e preços

O uso dessas funções executa uma operação de leitura em seu banco de dados, o que significa que você será cobrado pela leitura de documentos, mesmo que suas regras rejeitem a solicitação. Consulte Preços do Cloud Firestore para obter informações de cobrança mais específicas.

Funções personalizadas

À medida que suas regras de segurança se tornam mais complexas, você pode querer agrupar conjuntos de condições em funções que podem ser reutilizadas em seu conjunto de regras. As regras de segurança oferecem suporte a funções personalizadas. A sintaxe para funções personalizadas é um pouco como JavaScript, mas as funções de regras de segurança são escritas em uma linguagem específica de domínio que possui algumas limitações importantes:

  • As funções podem conter apenas uma única instrução de return . Eles não podem conter nenhuma lógica adicional. Por exemplo, eles não podem executar loops ou chamar serviços externos.
  • As funções podem acessar automaticamente funções e variáveis ​​do escopo em que são definidas. Por exemplo, uma função definida no escopo do service cloud.firestore tem acesso à variável de resource e às funções integradas, como get() e exists() .
  • As funções podem chamar outras funções, mas não podem ser recursivas. A profundidade total da pilha de chamadas é limitada a 10.
  • Na versão v2 das regras, as funções podem definir variáveis ​​usando a palavra-chave let . As funções podem ter até 10 ligações let, mas devem terminar com uma instrução return.

Uma função é definida com a palavra-chave function e recebe zero ou mais argumentos. Por exemplo, você pode querer combinar os dois tipos de condições usados ​​nos exemplos acima em uma única função:

service cloud.firestore {
  match /databases/{database}/documents {
    // True if the user is signed in or the requested data is 'public'
    function signedInOrPublic() {
      return request.auth.uid != null || resource.data.visibility == 'public';
    }

    match /cities/{city} {
      allow read, write: if signedInOrPublic();
    }

    match /users/{user} {
      allow read, write: if signedInOrPublic();
    }
  }
}

O uso de funções em suas regras de segurança as torna mais fáceis de manter à medida que a complexidade de suas regras aumenta.

Regras não são filtros

Depois de proteger seus dados e começar a escrever consultas, lembre-se de que as regras de segurança não são filtros. Você não pode escrever uma consulta para todos os documentos em uma coleção e esperar que o Cloud Firestore retorne apenas os documentos que o cliente atual tem permissão para acessar.

Por exemplo, considere a seguinte regra de segurança:

service cloud.firestore {
  match /databases/{database}/documents {
    // Allow the user to read data if the document has the 'visibility'
    // field set to 'public'
    match /cities/{city} {
      allow read: if resource.data.visibility == 'public';
    }
  }
}

Negado : Esta regra rejeita a seguinte consulta porque o conjunto de resultados pode incluir documentos onde a visibility não é public :

Rede
db.collection("cities").get()
    .then(function(querySnapshot) {
        querySnapshot.forEach(function(doc) {
            console.log(doc.id, " => ", doc.data());
    });
});

Permitido : esta regra permite a seguinte consulta porque a cláusula where("visibility", "==", "public") garante que o conjunto de resultados satisfaça a condição da regra:

Rede
db.collection("cities").where("visibility", "==", "public").get()
    .then(function(querySnapshot) {
        querySnapshot.forEach(function(doc) {
            console.log(doc.id, " => ", doc.data());
        });
    });

As regras de segurança do Cloud Firestore avaliam cada consulta em relação ao seu resultado potencial e falham na solicitação se ela puder retornar um documento que o cliente não tem permissão para ler. As consultas devem seguir as restrições definidas por suas regras de segurança. Para saber mais sobre regras e consultas de segurança, consulte consulta segura de dados .

Próximos passos