Como funcionam as regras de segurança do Firebase na Realtime Database?

Parte 4 — Testes Unitários

Rosário Pereira Fernandes
GDG Maputo
Published in
4 min readOct 29, 2018

--

Na parte 3 desta série de artigos mostrei como utilizar o Simulador de Regras da Realtime Database. O simulador é uma ferramenta muito útil e que ajuda bastante na hora de testar as nossas regras online.

Mas hoje, durante o Firebase Summit 2018, foram lançadas 2 novas ferramentas que ajudam também na hora de testar regras: o Emulador da Realtime Database e o módulo firebase-testing da Firebase CLI. Neste artigo mostro como funcionam estas ferramentas e como elas facilitam-nos quando queremos verificar o comportamento das nossas regras de segurança.

Realtime Database Emulator

O emulador da Realtime Database é uma ferramenta que permite simular uma instância de uma database na nossa máquina local. Todas as operações que executamos na nossa Realtime Database podem ser simuladas localmente no emulador. A única diferença é que o emulador não está interligado aos outros serviços do Firebase.

Instalação

Para instalar o emulador, temos de executar os seguintes comandos:

Iniciar

Agora que temos o emulador instalado, podemos iniciá-lo usando o comando: firebase serve --only firestore. Ao introduzir o comando, deverá aparecer uma mensagem dizendo “Listening on port 9000” no seu ecrã.

Geralmente a Realtime Database pode ser acedida através da URL https://<nome-da-database>.firebaseio.com/caminho/dos/dados.json. Ao iniciar o emulador, a mesma database pode ser acedida também pela URL http://localhost:9000/caminho/dos/dados.json?ns=<nome-da-database>.

Quando você inicia o emulador, a realtime database simulada é criada com as regras privadas (.write e .read em false).

Módulo node.js firebase-testing

Este módulo permite-nos escrever testes unitários para a nossa database. Neste artigo, vamos criar um diretório chamado teste, e neste diretório vamos instalar o nosso módulo firebase-testing. Para isso, basta utilizarmos o comando:

async/await

Antes de começarmos a escrever os testes unitários, há 2 conceitos que podem ser novos para você: async e await.

Você já deve saber que as funções de leitura e escrita do Firebase funcionam de forma assíncrona. Mas como os nossos testes serão executados em sequência, não podemos fazê-los de forma assíncrona, pois a sequência se perderá.

E para nos ajudar com isso, o JavaScript possui o async e o await que permitem-nos esperar pelo resultado de uma operação antes de ir para a próxima. Por exemplo, para ler um utilizador de forma assíncrona no JavaScript, você faria:

Para fazer a mesma leitura, de forma síncrona, você deve fazer:

Há uma coisa a notar: o async serve para anotar funções e o await só pode ser utilizado em funções que foram declaradas com a anotação async.

Você pode aprender mais sobre async e await neste post do Jose Pedro Dava.

Escrever Testes Unitários

Para escrever os nossos testes, o firebase-testing possui as funções:

  • initializeTestApp({ databaseName, auth }) — simula uma app que está a ser acedida por um utilizador autenticado, que é especificado no parâmetro auth.
  • initializeAdminApp({ databaseName }) — simula uma app que está ser acedida com privilégios de administrador (é como usar o Admin SDK ou a REST API para aceder à database).
  • loadRules({ databaseName , rulesPath }) — carrega as regras de segurança que iremos testar.
  • apps() — retorna a lista de todos as apps que foram inicializadas para simulação.
  • assertFails(pr: Promise) — verifica se uma escrita/leitura irá falhar.
  • assertSucceeds(pr: Promise) — verifica se uma escrita/leitura irá ser executada com sucesso.

Agora que conhecemos as funções, podemos então escrever testes unitários para as regras (veja database.rules.json) da database que temos usado durante esta série de artigos (veja MyDatabase.json).

Por exemplo, uma regra que definimos foi: “Utilizadores só podem enviar mensagens para grupos que fazem parte”. A regra escrita foi:

E o código JavaScript para enviar a mensagem seria algo como:

Então usamos este mesmo código simulando um utilizador autenticado. Podemos verificar se o utilizador de uid=”uid1" pode realmente escrever no grupo com a chave “g1” (que ele faz parte):

E podemos nos certificar que ele não tem acesso ao grupo “g2”:

Juntando os dois, o nosso ficheiro index.js(no directório teste) ficaria assim:

Este é um dos exemplos mais simples. Completei o ficheiro index.js para testar todas as regras que foram definidas, e ficou assim:

Depois de escrever os testes, temos de executá-los. Para isso, voltamos à terminal e (no diretório parente do diretório teste) executamos o comando npm test teste. Você deverá ter um output semelhante à este:

E por hoje é tudo. Espero que você tenha compreendido e que comece também a escrever testes unitários para a sua database. ;)

Caso tenha alguma dúvida ou sugestão, deixe abaixo nos comentários. Se você estiver tentando escrever testes unitários e teve um problema, coloque ele no StackOverflow, mostrando o que você fez e qual foi o erro que teve. De certeza que você obterá ajuda de mim ou de alguém da comunidade. 🙂

--

--

Rosário Pereira Fernandes
GDG Maputo

Firebase DevRel Engineer at Google … Views and Opinions are my own.