2 minute read

Um problema típico

“Imperfeito feito vence, perfeito nunca feito.”

O código parecia certo, mas a partida entre os dois jogadores não iniciava. A falha foi detectada e corrigida. Qual era o problema? Regras de segurança do Firebase Realtime Database.

Primeiro, uma dica para quem está começando como eu: controle a ansiedade. Antes de começar a codificar um projeto, pesquise e entenda cada ferramenta que pretende utilizar.

Neste projeto fui tomado pela pressa. Li por alto sobre o Firebase Realtime Database e decidi: “é essa a ferramenta que vou usar”. Quando comecei a codificar, percebi que havia muito mais para entender antes de seguir com a implementação.

O que fiz então? Recorri ao ChatGPT, que me deu códigos prontos. Tentei entender e aplicar, mas a cada nova implementação, percebia que a complexidade aumentava. Depois de muitos prompts mal estruturados e respostas que refletiam isso, o projeto até funcionou em certo momento. Mas a falta de conhecimento cobra caro. Qualquer falha se tornava um desafio ainda maior de resolver.

Foi necessário parar o desenvolvimento e estudar o que deveria ter sido entendido antes. Mais uma vez o projeto parou, e o sentimento de incompetência apareceu. Essa pausa — e esse sentimento — poderiam ter sido evitados por uma palavra simples: preparação.

Agora que falei da dor, quero compartilhar o que aprendi com ela.

Regras de Segurança da Realtime Database

Depois de muito procurar, finalmente encontrei a documentação correta: Security Rules language. Aprendi a estrutura básica.

{
  "rules":{
    "<<caminho>>":{
      //Condições para permissões: Leitura, Escrita e Validação
      ".read":"<<condição>>", //Condição para leitura
      ".write":"<<condicao>>",//Condição para escrita
      ".validate":"<<condicao>>"//Condição de validação
    }
  }
}

Essa estrutura, semelhante a um JSON, tem 3 componentes principais:

  • Caminho: a localização no banco de dados.
  • Requisições: métodos para conceder permissão de leitura, escrita ou validação.
  • Condições: critérios que autorizam a operação se forem validados como verdadeiros.

Como a regra estava?

A estrutura do jogo é basicamente:

|games
  |game
    |id
      |players
        |player1
        |player2
      |currentPlayer
      |isFull
      |eventos
      |moves

O problema estava nas regras de segurança que impediam o cadastro dos jogadores. A validação esperava uma estrutura que não existia userGames.

Veja como estava:

"players": {
  "player1": {
    ".write": "root.child('userGames/' + auth.uid + '/' + $matchId + '/playerId').val() === data.child('id').val() || !data.exists()"
  },
  "player2": {
    ".write": "root.child('userGames/' + auth.uid + '/' + $matchId + '/playerId').val() === data.child('id').val() || !data.exists()"
  }
}

A lógica acima verifica se existe um playerId associado ao usuário autenticado dentro da estrutura userGames, mas ela não existia no banco. Resultado: permissão negada e a chave isFull nunca era atualizada para true.

Como corrigi

Entendendo isso, reescrevi as regras de forma mais simples e adequada à minha estrutura real.

"players":{
  "player1":{
    ".write":"!data.exists()"
  },
  "player2":{
    ".write":"!data.exists() && root.child('games/game' + $matchId + '/players/player1').exists()"
  }
}

Explicando:

  • player1: só pode ser escrito se ainda não existir.
  • player2: só pode ser escrito se player1 já existir e ele próprio ainda não existir.

Agora, a regra para isFull.

"isFull":{
  ".read":"auth != null",
  ".write":"!data.exists() || (root.child('games/game' + $matchId + '/players/player1').exists() && root.child('games/game' + $matchId + '/players/player2').exists())"
}

Ou seja, a leitura é liberada para qualquer usuário autenticado, e a escrita só é permitida se ambos os jogadores estiverem cadastrados. Com essas mudanças, a chave isFull finalmente é atualizada corretamente e a partida pode começar.


Lembre-se: este diário é sobre crescimento pessoal - o meu e o seu, se você também enfrente bloqueios semelhantes.

Porque não é sobre o jogo. É sobre quebrar padrões.

📌 Repositório no GitHub
📓 Leia o post anterior da série
🧠 Saiba mais sobre o as regras de segurança do firebase realtime database