Conheça o Firebase para Web

1. Visão Geral

Neste codelab, você aprenderá algumas noções básicas do Firebase para criar aplicativos da Web interativos. Você criará um RSVP de evento e um aplicativo de bate-papo com livro de visitas usando vários produtos do Firebase.

captura de tela desta etapa

O que você vai aprender

  • Autentique usuários com Firebase Authentication e FirebaseUI.
  • Sincronize dados usando o Cloud Firestore.
  • Escreva regras de segurança do Firebase para proteger um banco de dados.

O que você precisará

  • Um navegador de sua escolha, como o Chrome.
  • Acesso ao stackblitz.com (sem necessidade de conta ou login).
  • Uma conta do Google, como uma conta do Gmail. Recomendamos a conta de e-mail que você já usa para sua conta do GitHub. Isso permite que você use recursos avançados no StackBlitz.
  • O código de amostra do codelab. Veja a próxima etapa para saber como obter o código.

2. Obtenha o código inicial

Neste codelab, você cria um aplicativo usando o StackBlitz , um editor on-line que tem vários fluxos de trabalho do Firebase integrados a ele. O Stackblitz não requer instalação de software ou conta especial do StackBlitz.

StackBlitz permite compartilhar projetos com outras pessoas. Outras pessoas que têm a URL do seu projeto StackBlitz podem ver seu código e bifurcar seu projeto, mas não podem editar seu projeto StackBlitz.

  1. Vá para este URL para o código inicial: https://stackblitz.com/edit/firebase-gtk-web-start
  2. Na parte superior da página do StackBlitz, clique em Fork :

captura de tela desta etapa

Agora você tem uma cópia do código inicial como seu próprio projeto StackBlitz, que tem um nome exclusivo, juntamente com um URL exclusivo. Todos os seus arquivos e alterações são salvos neste projeto StackBlitz.

3. Edite as informações do evento

Os materiais iniciais para este codelab fornecem alguma estrutura para o aplicativo da Web, incluindo algumas folhas de estilo e alguns contêineres HTML para o aplicativo. Mais adiante neste codelab, você conectará esses contêineres ao Firebase.

Para começar, vamos nos familiarizar um pouco mais com a interface do StackBlitz.

  1. No StackBlitz, abra o arquivo index.html .
  2. Localize event-details-container e description-container e tente editar alguns detalhes do evento.

Conforme você edita o texto, o recarregamento automático da página no StackBlitz exibe os novos detalhes do evento. Legal, sim?

<!-- ... -->

<div id="app">
  <img src="..." />

  <section id="event-details-container">
     <h1>Firebase Meetup</h1>

     <p><i class="material-icons">calendar_today</i> October 30</p>
     <p><i class="material-icons">location_city</i> San Francisco</p>

  </section>

  <hr>

  <section id="firebaseui-auth-container"></section>

  <section id="description-container">
     <h2>What we'll be doing</h2>
     <p>Join us for a day full of Firebase Workshops and Pizza!</p>
  </section>
</div>

<!-- ... -->

A visualização do seu aplicativo deve ser algo como isto:

Visualização do aplicativo

captura de tela desta etapa

4. Crie e configure um projeto do Firebase

Exibir as informações do evento é ótimo para seus convidados, mas apenas mostrar os eventos não é muito útil para ninguém. Vamos adicionar algumas funcionalidades dinâmicas a este aplicativo. Para isso, você precisará conectar o Firebase ao seu aplicativo. Para começar a usar o Firebase, você precisará criar e configurar um projeto do Firebase.

Criar um projeto do Firebase

  1. Faça login no Firebase .
  2. No console do Firebase, clique em Add Project (ou Create a project ) e nomeie seu projeto do Firebase Firebase-Web-Codelab .

    captura de tela desta etapa

  3. Clique nas opções de criação do projeto. Aceite os termos do Firebase, se solicitado. Na tela do Google Analytics, clique em "Não habilitar", pois você não usará o Analytics para este aplicativo.

Para saber mais sobre os projetos do Firebase, consulte Entender os projetos do Firebase .

Ativar e configurar produtos Firebase no console

O aplicativo que você está criando usa vários produtos do Firebase disponíveis para aplicativos da Web:

  • Firebase Authentication e Firebase UI para permitir que seus usuários façam login no seu aplicativo com facilidade.
  • Cloud Firestore para salvar dados estruturados na nuvem e receber notificações instantâneas quando os dados forem alterados.
  • Regras de segurança do Firebase para proteger seu banco de dados.

Alguns desses produtos precisam de configuração especial ou precisam ser ativados usando o Firebase console.

Ativar login por e-mail para o Firebase Authentication

Para permitir que os usuários façam login no aplicativo da Web, você usará o método de login por e- mail/senha para este codelab:

  1. No painel esquerdo do console do Firebase, clique em Build > Authentication . Em seguida, clique em Começar . Agora você está no painel Autenticação, onde pode ver usuários inscritos, configurar provedores de entrada e gerenciar configurações.

    captura de tela desta etapa

  2. Selecione a guia Método de login (ou clique aqui para ir diretamente para a guia).

    captura de tela desta etapa

  3. Clique em Email/Senha nas opções do provedor, alterne a opção para Ativar e clique em Salvar .

    captura de tela desta etapa

Configurar o Cloud Firestore

O aplicativo da Web usa o Cloud Firestore para salvar mensagens de bate-papo e receber novas mensagens de bate-papo.

Veja como configurar o Cloud Firestore:

  1. No painel esquerdo do console do Firebase, clique em Build > Firestore Database . Em seguida, clique em Criar banco de dados.
  2. Clique em Criar banco de dados.

    captura de tela desta etapa

  3. Selecione a opção Iniciar no modo de teste . Leia o aviso sobre as regras de segurança. O modo de teste garante que você possa gravar livremente no banco de dados durante o desenvolvimento. Clique em Avançar .

    captura de tela desta etapa

  4. Selecione o local para seu banco de dados (você pode usar apenas o padrão). Observe, porém, que esse local não pode ser alterado posteriormente.

    captura de tela desta etapa

  5. Clique em Concluído .

5. Adicione e configure o Firebase

Agora que você criou seu projeto do Firebase e alguns serviços estão ativados, você precisa informar ao código que deseja usar o Firebase, bem como qual projeto do Firebase usar.

Adicionar as bibliotecas do Firebase

Para que seu aplicativo use o Firebase, você precisa adicionar as bibliotecas do Firebase ao aplicativo. Há várias maneiras de fazer isso, conforme descrito na documentação do Firebase . Por exemplo, você pode adicionar as bibliotecas do CDN do Google ou instalá-las localmente usando npm e depois empacotá-las em seu aplicativo se estiver usando o Browserify.

O StackBlitz oferece agrupamento automático, para que você possa adicionar as bibliotecas do Firebase usando instruções de importação. Você usará as versões modulares (v9) das bibliotecas, que ajudam a reduzir o tamanho geral da página da Web por meio de um processo chamado "agitação de árvore". Você pode saber mais sobre os SDKs modulares nos documentos .

Para criar este aplicativo, você usa as bibliotecas Firebase Authentication, FirebaseUI e Cloud Firestore. Para este codelab, as seguintes instruções de importação já estão incluídas na parte superior do arquivo index.js e importaremos mais métodos de cada biblioteca do Firebase à medida que avançamos:

// Import stylesheets
import './style.css';

// Firebase App (the core Firebase SDK) is always required
import { initializeApp } from 'firebase/app';

// Add the Firebase products and methods that you want to use
import {} from 'firebase/auth';
import {} from 'firebase/firestore';

import * as firebaseui from 'firebaseui';

Adicionar um aplicativo da Web do Firebase ao seu projeto do Firebase

  1. De volta ao Firebase console, navegue até a página de visão geral do seu projeto clicando em Visão geral do projeto no canto superior esquerdo.
  2. No centro da página de visão geral do seu projeto, clique no ícone da web ícone de aplicativo da web para criar um novo app da Web do Firebase.

    captura de tela desta etapa

  3. Registre o aplicativo com o apelido Web App .
  4. Para este codelab, NÃO marque a caixa ao lado de Também configurar o Firebase Hosting para este aplicativo . Você usará o painel de visualização do StackBlitz por enquanto.
  5. Clique em Registrar aplicativo .

    captura de tela desta etapa

  6. Copie o objeto de configuração do Firebase para sua área de transferência.

    captura de tela desta etapa

  7. Clique em Continuar para o console .Adicione o objeto de configuração do Firebase ao seu aplicativo:
  8. De volta ao StackBlitz, acesse o arquivo index.js .
  9. Localize a linha de comentário Add Firebase project configuration object here e cole o snippet de configuração logo abaixo do comentário.
  10. Adicione a chamada de função initializeApp para configurar o Firebase usando sua configuração exclusiva de projeto do Firebase.
    // ...
    // Add Firebase project configuration object here
    const firebaseConfig = {
      apiKey: "random-unique-string",
      authDomain: "your-projectId.firebaseapp.com",
      databaseURL: "https://your-projectId.firebaseio.com",
      projectId: "your-projectId",
      storageBucket: "your-projectId.appspot.com",
      messagingSenderId: "random-unique-string",
      appId: "random-unique-string",
    };
    
    // Initialize Firebase
    initializeApp(firebaseConfig);
    

6. Adicionar login do usuário (RSVP)

Agora que você adicionou o Firebase ao aplicativo, pode configurar um botão RSVP que registre pessoas usando o Firebase Authentication .

Autentique seus usuários com login por e-mail e FirebaseUI

Você precisará de um botão RSVP que solicite ao usuário que faça login com seu endereço de e-mail. Você pode fazer isso conectando o FirebaseUI a um botão RSVP. O FirebaseUI é uma biblioteca que oferece uma IU pré-criada sobre o Firebase Auth.

O FirebaseUI requer uma configuração (consulte as opções na documentação ) que faz duas coisas:

  • Informa ao FirebaseUI que você deseja usar o método de login por e- mail/senha .
  • Manipula o retorno de chamada para uma entrada bem-sucedida e retorna false para evitar um redirecionamento. Você não deseja que a página seja atualizada porque está criando um aplicativo Web de página única.

Adicione o código para inicializar o FirebaseUI Auth

  1. No StackBlitz, acesse o arquivo index.js .
  2. Na parte superior, localize a instrução de importação do firebase/auth e adicione getAuth e EmailAuthProvider , assim:
    // ...
    // Add the Firebase products and methods that you want to use
    import { getAuth, EmailAuthProvider } from 'firebase/auth';
    
    import {} from 'firebase/firestore';
    
  3. Salve uma referência ao objeto auth logo após initializeApp , assim:
    initializeApp(firebaseConfig);
    auth = getAuth();
    
  4. Observe que a configuração do FirebaseUI já é fornecida no código inicial. Já está configurado para usar o provedor de autenticação de e-mail.
  5. Na parte inferior da função main() em index.js , adicione a instrução de inicialização do FirebaseUI, assim:
    async function main() {
      // ...
    
      // Initialize the FirebaseUI widget using Firebase
      const ui = new firebaseui.auth.AuthUI(auth);
    }
    main();
    
    

Adicionar um botão RSVP ao HTML

  1. No StackBlitz, acesse o arquivo index.html .
  2. Adicione o HTML para um botão RSVP dentro do event-details-container conforme mostrado no exemplo abaixo.

    Tenha cuidado para usar os mesmos valores de id mostrados abaixo porque, para este codelab, já existem ganchos para esses IDs específicos no arquivo index.js .

    Observe que no arquivo index.html há um contêiner com o ID firebaseui-auth-container . Este é o ID que você passará ao FirebaseUI para manter seu login.
    <!-- ... -->
    
    <section id="event-details-container">
        <!-- ... -->
        <!-- ADD THE RSVP BUTTON HERE -->
        <button id="startRsvp">RSVP</button>
    </section>
    <hr>
    <section id="firebaseui-auth-container"></section>
    <!-- ... -->
    
    Visualização do aplicativo

    captura de tela desta etapa

  3. Configure um listener no botão RSVP e chame a função de início do FirebaseUI. Isso informa ao FirebaseUI que você deseja ver a janela de login.

    Adicione o seguinte código na parte inferior da função main() em index.js :
    async function main() {
      // ...
    
      // Listen to RSVP button clicks
      startRsvpButton.addEventListener("click",
       () => {
            ui.start("#firebaseui-auth-container", uiConfig);
      });
    }
    main();
    

Teste o login no aplicativo

  1. Na janela de visualização do StackBlitz, clique no botão RSVP para entrar no aplicativo.
    • Para este codelab, você pode usar qualquer endereço de e-mail, até mesmo um endereço de e-mail falso, pois não está configurando uma etapa de verificação de e-mail para este codelab.
    • Se você vir uma mensagem de erro informando auth/operation-not-allowed ou The given sign-in provider is disabled for this Firebase project , verifique se você ativou E-mail/senha como provedor de login no console do Firebase.
    Visualização do aplicativo

    captura de tela desta etapa

  2. Acesse o painel Autenticação no console do Firebase. Na guia Usuários , você deve ver as informações da conta inseridas para entrar no aplicativo.

    captura de tela desta etapa

Adicionar estado de autenticação à IU

Em seguida, verifique se a interface do usuário reflete o fato de você estar conectado.

Você usará o retorno de chamada do ouvinte de estado do Firebase Authentication, que é notificado sempre que o status de login do usuário é alterado. Se houver um usuário conectado no momento, seu aplicativo mudará o botão "RSVP" para um botão "logout".

  1. No StackBlitz, acesse o arquivo index.js .
  2. Na parte superior, localize a instrução de importação do firebase/auth e adicione signOut e onAuthStateChanged , assim:
    // ...
    // Add the Firebase products and methods that you want to use
    import {
      getAuth,
      EmailAuthProvider,
      signOut,
      onAuthStateChanged
    } from 'firebase/auth';
    
    import {} from 'firebase/firestore';
    
  3. Adicione o seguinte código na parte inferior da função main() :
    async function main() {
      // ...
    
      // Listen to the current Auth state
      onAuthStateChanged(auth, user => {
        if (user) {
          startRsvpButton.textContent = 'LOGOUT';
        } else {
          startRsvpButton.textContent = 'RSVP';
        }
      });
    }
    main();
    
  4. No listener do botão, verifique se existe um usuário atual e desconecte-o. Para fazer isso, substitua o startRsvpButton.addEventListener atual pelo seguinte:
    // ...
    // Called when the user clicks the RSVP button
    startRsvpButton.addEventListener('click', () => {
      if (auth.currentUser) {
        // User is signed in; allows user to sign out
        signOut(auth);
      } else {
        // No user is signed in; allows user to sign in
        ui.start('#firebaseui-auth-container', uiConfig);
      }
    });
    

Agora, o botão em seu aplicativo deve mostrar LOGOUT e deve voltar para RSVP quando for clicado.

Visualização do aplicativo

captura de tela desta etapa

7. Gravar mensagens no Cloud Firestore

Saber que os usuários estão chegando é ótimo, mas vamos dar aos convidados algo mais para fazer no aplicativo. E se eles pudessem deixar mensagens em um livro de visitas? Eles podem compartilhar por que estão animados para vir ou quem esperam conhecer.

Para armazenar as mensagens de bate-papo que os usuários escrevem no aplicativo, você usará o Cloud Firestore .

Modelo de dados

O Cloud Firestore é um banco de dados NoSQL e os dados armazenados no banco de dados são divididos em coleções, documentos, campos e subcoleções. Você armazenará cada mensagem do bate-papo como um documento em uma coleção de nível superior chamada guestbook .

Gráfico de modelo de dados do Firestore mostrando uma coleção de livros de visitas com vários documentos de mensagem

Adicionar mensagens ao Firestore

Nesta seção, você adicionará a funcionalidade para que os usuários escrevam novas mensagens no banco de dados. Primeiro, você adiciona o HTML para os elementos da interface do usuário (campo de mensagem e botão de envio). Em seguida, você adiciona o código que conecta esses elementos ao banco de dados.

Para adicionar os elementos da interface do usuário de um campo de mensagem e um botão de envio:

  1. No StackBlitz, acesse o arquivo index.html .
  2. Localize o guestbook-container e adicione o seguinte HTML para criar um formulário com o campo de entrada de mensagem e o botão enviar.
    <!-- ... -->
    
     <section id="guestbook-container">
       <h2>Discussion</h2>
    
       <form id="leave-message">
         <label>Leave a message: </label>
         <input type="text" id="message">
         <button type="submit">
           <i class="material-icons">send</i>
           <span>SEND</span>
         </button>
       </form>
    
     </section>
    
    <!-- ... -->
    

Visualização do aplicativo

captura de tela desta etapa

Um usuário clicando no botão ENVIAR acionará o snippet de código abaixo. Ele adiciona o conteúdo do campo de entrada de mensagem à coleção de livros de guestbook do banco de dados. Especificamente, o método addDoc adiciona o conteúdo da mensagem a um novo documento (com um ID gerado automaticamente) à coleção do guestbook de visitas.

  1. No StackBlitz, acesse o arquivo index.js .
  2. Na parte superior, localize a instrução de importação do firebase/firestore e adicione getFirestore , addDoc e collection , assim:
    // ...
    
    // Add the Firebase products and methods that you want to use
    import {
      getAuth,
      EmailAuthProvider,
      signOut,
      onAuthStateChanged
    } from 'firebase/auth';
    
    import {
      getFirestore,
      addDoc,
      collection
    } from 'firebase/firestore';
    
  3. Agora vamos salvar uma referência ao objeto db do Firestore logo após initializeApp :
    initializeApp(firebaseConfig);
    auth = getAuth();
    db = getFirestore();
    
  4. Na parte inferior da função main() , adicione o código a seguir.

    Observe que auth.currentUser.uid é uma referência ao ID exclusivo gerado automaticamente que o Firebase Authentication fornece para todos os usuários conectados.
    async function main() {
      // ...
    
      // Listen to the form submission
      form.addEventListener('submit', async e => {
        // Prevent the default form redirect
        e.preventDefault();
        // Write a new message to the database collection "guestbook"
        addDoc(collection(db, 'guestbook'), {
          text: input.value,
          timestamp: Date.now(),
          name: auth.currentUser.displayName,
          userId: auth.currentUser.uid
        });
        // clear message input field
        input.value = '';
        // Return false to avoid redirect
        return false;
      });
    }
    main();
    

Mostrar o livro de visitas apenas para usuários conectados

Você não quer que qualquer um veja o bate-papo dos convidados. Uma coisa que você pode fazer para proteger o bate-papo é permitir que apenas usuários conectados visualizem o livro de visitas. Dito isso, para seus próprios aplicativos, você também deve proteger seu banco de dados com as regras de segurança do Firebase . (Há mais informações sobre regras de segurança posteriormente no codelab.)

  1. No StackBlitz, acesse o arquivo index.js .
  2. Edite o ouvinte onAuthStateChanged para ocultar e mostrar o livro de visitas.
    // ...
    
    // Listen to the current Auth state
    onAuthStateChanged(auth, user => {
      if (user) {
        startRsvpButton.textContent = 'LOGOUT';
        // Show guestbook to logged-in users
        guestbookContainer.style.display = 'block';
      } else {
        startRsvpButton.textContent = 'RSVP';
        // Hide guestbook for non-logged-in users
        guestbookContainer.style.display = 'none';
      }
    });
    

Teste o envio de mensagens

  1. Verifique se você está conectado ao aplicativo.
  2. Digite uma mensagem como "E aí!" e clique em ENVIAR .

Esta ação grava a mensagem no banco de dados do Cloud Firestore. No entanto, você ainda não verá a mensagem em seu aplicativo Web real porque ainda precisa implementar a recuperação dos dados. Você vai fazer isso a seguir.

Mas você pode ver a mensagem recém-adicionada no console do Firebase.

No console do Firebase, no painel do Firestore Database , você verá a coleção de livros de guestbook com sua mensagem recém-adicionada. Se você continuar enviando mensagens, sua coleção de livros de visitas conterá muitos documentos, como este:

Console do Firebase

captura de tela desta etapa

8. Leia mensagens

Sincronizar mensagens

É ótimo que os convidados possam escrever mensagens no banco de dados, mas ainda não podem vê-las no aplicativo.

Para exibir mensagens, você precisará adicionar ouvintes que acionam quando os dados forem alterados e, em seguida, criar um elemento de interface do usuário que mostre novas mensagens.

Você adicionará um código que detecta mensagens recém-adicionadas do aplicativo. Primeiro, adicione uma seção no HTML para mostrar as mensagens:

  1. No StackBlitz, acesse o arquivo index.html .
  2. Em guestbook-container , adicione uma nova seção com o ID de guestbook .
    <!-- ... -->
    
      <section id="guestbook-container">
       <h2>Discussion</h2>
    
       <form><!-- ... --></form>
    
       <section id="guestbook"></section>
    
     </section>
    
    <!-- ... -->
    

Em seguida, registre o ouvinte que escuta as alterações feitas nos dados:

  1. No StackBlitz, acesse o arquivo index.js .
  2. Na parte superior, localize a instrução de importação do firebase/firestore e adicione query , orderBy e onSnapshot , assim:
    // ...
    import {
      getFirestore,
      addDoc,
      collection,
      query,
      orderBy,
      onSnapshot
    } from 'firebase/firestore';
    
  3. Na parte inferior da função main() , adicione o código a seguir para percorrer todos os documentos (mensagens do livro de visitas) no banco de dados. Para saber mais sobre o que está acontecendo neste código, leia as informações abaixo do snippet.
    async function main() {
      // ...
    
      // Create query for messages
      const q = query(collection(db, 'guestbook'), orderBy('timestamp', 'desc'));
      onSnapshot(q, snaps => {
        // Reset page
        guestbook.innerHTML = '';
        // Loop through documents in database
        snaps.forEach(doc => {
          // Create an HTML entry for each document and add it to the chat
          const entry = document.createElement('p');
          entry.textContent = doc.data().name + ': ' + doc.data().text;
          guestbook.appendChild(entry);
        });
      });
    }
    main();
    

Para ouvir mensagens no banco de dados, você criou uma consulta em uma coleção específica usando a função de collection . O código acima ouve as alterações na coleção do guestbook de visitas, que é onde as mensagens de bate-papo são armazenadas. As mensagens também são ordenadas por data, usando orderBy('timestamp', 'desc') para exibir as mensagens mais recentes no topo.

A função onSnapshot recebe dois parâmetros: a consulta a ser usada e uma função de retorno de chamada. A função de retorno de chamada é acionada quando há alterações nos documentos que correspondem à consulta. Isso pode acontecer se uma mensagem for excluída, modificada ou adicionada. Para obter mais informações, consulte a documentação do Cloud Firestore .

Testar mensagens de sincronização

O Cloud Firestore sincroniza automaticamente e instantaneamente os dados com os clientes inscritos no banco de dados.

  • As mensagens que você criou anteriormente no banco de dados devem ser exibidas no aplicativo. Sinta-se à vontade para escrever novas mensagens; eles devem aparecer instantaneamente.
  • Se você abrir seu espaço de trabalho em várias janelas ou guias, as mensagens serão sincronizadas em tempo real entre as guias.
  • (Opcional) Você pode tentar excluir, modificar ou adicionar novas mensagens manualmente diretamente na seção Banco de dados do console do Firebase; todas as alterações devem aparecer na interface do usuário.

Parabéns! Você está lendo documentos do Cloud Firestore em seu aplicativo!

Visualização do aplicativo

captura de tela desta etapa

9. Configure regras básicas de segurança

Você configurou inicialmente o Cloud Firestore para usar o modo de teste, o que significa que seu banco de dados está aberto para leituras e gravações. No entanto, você só deve usar o modo de teste durante os estágios iniciais de desenvolvimento. Como prática recomendada, você deve configurar regras de segurança para seu banco de dados à medida que desenvolve seu aplicativo. A segurança deve ser parte integrante da estrutura e do comportamento do seu aplicativo.

As Regras de Segurança permitem controlar o acesso a documentos e coleções em seu banco de dados. A sintaxe de regras flexíveis permite que você crie regras que correspondam a qualquer coisa, desde todas as gravações em todo o banco de dados até operações em um documento específico.

Você pode escrever regras de segurança para o Cloud Firestore no console do Firebase:

  1. Na seção Build do console do Firebase, clique em Firestore Database e selecione a guia Rules (ou clique aqui para ir diretamente para a guia Rules ).
  2. Você deve ver as seguintes regras de segurança padrão, com um limite de tempo de acesso público em algumas semanas a partir de hoje.

captura de tela desta etapa

Identificar coleções

Primeiro, identifique as coleções nas quais o aplicativo grava dados.

  1. Exclua a cláusula match /{document=**} existente, para que suas regras fiquem assim:
    rules_version = '2';
    service cloud.firestore {
      match /databases/{database}/documents {
      }
    }
    
  2. Em match /databases/{database}/documents , identifique a coleção que você deseja proteger:
    rules_version = '2';
    service cloud.firestore {
      match /databases/{database}/documents {
        match /guestbook/{entry} {
         // You'll add rules here in the next step.
      }
    }
    

Adicionar regras de segurança

Como você usou o UID de autenticação como um campo em cada documento do livro de visitas, você pode obter o UID de autenticação e verificar se qualquer pessoa tentando gravar no documento tem um UID de autenticação correspondente.

  1. Adicione as regras de leitura e gravação ao seu conjunto de regras conforme mostrado abaixo:
    rules_version = '2';
    service cloud.firestore {
      match /databases/{database}/documents {
        match /guestbook/{entry} {
          allow read: if request.auth.uid != null;
          allow create:
            if request.auth.uid == request.resource.data.userId;
        }
      }
    }
    
  2. Clique em Publicar para implantar suas novas regras. Agora, para o livro de visitas, apenas usuários conectados podem ler mensagens (qualquer mensagem!), mas você só pode criar uma mensagem usando sua ID de usuário. Também não permitimos que as mensagens sejam editadas ou excluídas.

Adicionar regras de validação

  1. Adicione validação de dados para garantir que todos os campos esperados estejam presentes no documento:
    rules_version = '2';
    service cloud.firestore {
      match /databases/{database}/documents {
        match /guestbook/{entry} {
          allow read: if request.auth.uid != null;
          allow create:
          if request.auth.uid == request.resource.data.userId
              && "name" in request.resource.data
              && "text" in request.resource.data
              && "timestamp" in request.resource.data;
        }
      }
    }
    
  2. Clique em Publicar para implantar suas novas regras.

Redefinir ouvintes

Como seu aplicativo agora só permite que usuários autenticados façam login, você deve mover a consulta firestore do livro de visitas para dentro do ouvinte Autenticação. Caso contrário, ocorrerão erros de permissão e o aplicativo será desconectado quando o usuário fizer logout.

  1. No StackBlitz, acesse o arquivo index.js .
  2. Puxe a coleção de livros de visitas onSnapshot listener para uma nova função chamada subscribeGuestbook . Além disso, atribua os resultados da função onSnapshot à variável guestbookListener .

    O listener onSnapshot do Firestore retorna uma função de cancelamento de assinatura que você poderá usar para cancelar o listener de snapshot posteriormente.
    // ...
    // Listen to guestbook updates
    function subscribeGuestbook() {
      const q = query(collection(db, 'guestbook'), orderBy('timestamp', 'desc'));
      guestbookListener = onSnapshot(q, snaps => {
        // Reset page
        guestbook.innerHTML = '';
        // Loop through documents in database
        snaps.forEach(doc => {
          // Create an HTML entry for each document and add it to the chat
          const entry = document.createElement('p');
          entry.textContent = doc.data().name + ': ' + doc.data().text;
          guestbook.appendChild(entry);
        });
      });
    }
    
  3. Adicione uma nova função abaixo chamada unsubscribeGuestbook . Verifique se a variável guestbookListener não é nula e chame a função para cancelar o ouvinte.
    // ...
    // Unsubscribe from guestbook updates
    function unsubscribeGuestbook() {
      if (guestbookListener != null) {
        guestbookListener();
        guestbookListener = null;
      }
    }
    

Por fim, adicione as novas funções ao retorno de chamada onAuthStateChanged .

  1. Adicione subscribeGuestbook() na parte inferior de if (user) .
  2. Adicione unsubscribeGuestbook() na parte inferior da instrução else .
    // ...
    // Listen to the current Auth state
    onAuthStateChanged(auth, user => {
      if (user) {
        startRsvpButton.textContent = 'LOGOUT';
        // Show guestbook to logged-in users
        guestbookContainer.style.display = 'block';
        // Subscribe to the guestbook collection
        subscribeGuestbook();
      } else {
        startRsvpButton.textContent = 'RSVP';
        // Hide guestbook for non-logged-in users
        guestbookContainer.style.display = 'none';
        // Unsubscribe from the guestbook collection
        unsubscribeGuestbook();
      }
    });
    

10. Etapa bônus: pratique o que aprendeu

Gravar o status de RSVP de um participante

No momento, seu aplicativo apenas permite que as pessoas comecem a conversar se estiverem interessadas no evento. Além disso, a única maneira de saber se alguém está vindo é postando no chat. Vamos nos organizar e deixar as pessoas saberem quantas pessoas estão vindo.

Você adicionará uma alternância para registrar as pessoas que desejam participar do evento e, em seguida, coletar uma contagem de quantas pessoas estão participando.

  1. No StackBlitz, acesse o arquivo index.html .
  2. Em guestbook-container , adicione um conjunto de botões SIM e NÃO , assim:
    <!-- ... -->
      <section id="guestbook-container">
       <h2>Are you attending?</h2>
         <button id="rsvp-yes">YES</button>
         <button id="rsvp-no">NO</button>
    
       <h2>Discussion</h2>
    
       <!-- ... -->
    
     </section>
    <!-- ... -->
    

Visualização do aplicativo

captura de tela desta etapa

Em seguida, registre o ouvinte para cliques de botão. Se o usuário clicar em YES , use seu UID de autenticação para salvar a resposta no banco de dados.

  1. No StackBlitz, acesse o arquivo index.js .
  2. Na parte superior, localize a instrução de importação do firebase/firestore e adicione doc , setDoc e where , assim:
    // ...
    // Add the Firebase products and methods that you want to use
    import {
      getFirestore,
      addDoc,
      collection,
      query,
      orderBy,
      onSnapshot,
      doc,
      setDoc,
      where
    } from 'firebase/firestore';
    
  3. Na parte inferior da função main() , adicione o seguinte código para ouvir o status de RSVP:
    async function main() {
      // ...
    
      // Listen to RSVP responses
      rsvpYes.onclick = async () => {
      };
      rsvpNo.onclick = async () => {
      };
    }
    main();
    
    
  4. Em seguida, crie uma nova coleção chamada attendees e registre uma referência de documento se um dos botões RSVP for clicado. Defina essa referência como true ou false dependendo de qual botão for clicado.

    Primeiro, para rsvpYes :
    // ...
    // Listen to RSVP responses
    rsvpYes.onclick = async () => {
      // Get a reference to the user's document in the attendees collection
      const userRef = doc(db, 'attendees', auth.currentUser.uid);
    
      // If they RSVP'd yes, save a document with attendi()ng: true
      try {
        await setDoc(userRef, {
          attending: true
        });
      } catch (e) {
        console.error(e);
      }
    };
    
    Depois, o mesmo para rsvpNo , mas com o valor false :
    rsvpNo.onclick = async () => {
      // Get a reference to the user's document in the attendees collection
      const userRef = doc(db, 'attendees', auth.currentUser.uid);
    
      // If they RSVP'd yes, save a document with attending: true
      try {
        await setDoc(userRef, {
          attending: false
        });
      } catch (e) {
        console.error(e);
      }
    };
    

Atualize suas regras de segurança

Como você já tem algumas regras configuradas, os novos dados que você está adicionando com os botões serão rejeitados.

Permitir adições à coleção de attendees

Você precisará atualizar as regras para permitir a adição à coleção de attendees .

  1. Para a coleção de attendees , como você usou o UID de autenticação como o nome do documento, você pode pegá-lo e verificar se o uid do remetente é o mesmo do documento que ele está escrevendo. Você permitirá que todos leiam a lista de participantes (já que não há dados privados lá), mas apenas o criador deve poder atualizá-la.
    rules_version = '2';
    service cloud.firestore {
      match /databases/{database}/documents {
        // ... //
        match /attendees/{userId} {
          allow read: if true;
          allow write: if request.auth.uid == userId;
        }
      }
    }
    
  2. Clique em Publicar para implantar suas novas regras.

Adicionar regras de validação

  1. Adicione algumas regras de validação de dados para garantir que todos os campos esperados estejam presentes no documento:
    rules_version = '2';
    service cloud.firestore {
      match /databases/{database}/documents {
        // ... //
        match /attendees/{userId} {
          allow read: if true;
          allow write: if request.auth.uid == userId
              && "attending" in request.resource.data;
    
        }
      }
    }
    
  2. Não se esqueça de clicar em Publicar para implantar suas regras!

(Opcional) Agora você pode visualizar os resultados de clicar nos botões. Acesse o painel do Cloud Firestore no console do Firebase.

Leia o status de RSVP

Agora que você gravou as respostas, vamos ver quem está vindo e refletir isso na interface do usuário.

  1. No StackBlitz, acesse o arquivo index.html .
  2. Em description-container , adicione um novo elemento com o ID de number-attending .
    <!-- ... -->
    
     <section id="description-container">
         <!-- ... -->
         <p id="number-attending"></p>
     </section>
    
    <!-- ... -->
    

Em seguida, registre o ouvinte para a coleção de attendees e conte o número de respostas SIM :

  1. No StackBlitz, acesse o arquivo index.js .
  2. Na parte inferior da função main() , adicione o código a seguir para ouvir o status de RSVP e contar os cliques YES .
    async function main() {
      // ...
    
      // Listen for attendee list
      const attendingQuery = query(
        collection(db, 'attendees'),
        where('attending', '==', true)
      );
      const unsubscribe = onSnapshot(attendingQuery, snap => {
        const newAttendeeCount = snap.docs.length;
        numberAttending.innerHTML = newAttendeeCount + ' people going';
      });
    }
    main();
    

Por fim, vamos destacar o botão correspondente ao status atual.

  1. Crie uma função que verifique se o UID de autenticação atual tem uma entrada na coleção de attendees e, em seguida, defina a classe do botão como clicked .
    // ...
    // Listen for attendee list
    function subscribeCurrentRSVP(user) {
      const ref = doc(db, 'attendees', user.uid);
      rsvpListener = onSnapshot(ref, doc => {
        if (doc && doc.data()) {
          const attendingResponse = doc.data().attending;
    
          // Update css classes for buttons
          if (attendingResponse) {
            rsvpYes.className = 'clicked';
            rsvpNo.className = '';
          } else {
            rsvpYes.className = '';
            rsvpNo.className = 'clicked';
          }
        }
      });
    }
    
  2. Além disso, vamos fazer uma função para cancelar a inscrição. Isso será usado quando o usuário fizer logout.
    // ...
    function unsubscribeCurrentRSVP() {
      if (rsvpListener != null) {
        rsvpListener();
        rsvpListener = null;
      }
      rsvpYes.className = '';
      rsvpNo.className = '';
    }
    
  3. Chame as funções do ouvinte de autenticação.
    // ...
    // Listen to the current Auth state
      // Listen to the current Auth state
      onAuthStateChanged(auth, user => {
        if (user) {
          startRsvpButton.textContent = 'LOGOUT';
          // Show guestbook to logged-in users
          guestbookContainer.style.display = 'block';
    
          // Subscribe to the guestbook collection
          subscribeGuestbook();
          // Subcribe to the user's RSVP
          subscribeCurrentRSVP(user);
        } else {
          startRsvpButton.textContent = 'RSVP';
          // Hide guestbook for non-logged-in users
          guestbookContainer.style.display = 'none'
          ;
          // Unsubscribe from the guestbook collection
          unsubscribeGuestbook();
          // Unsubscribe from the guestbook collection
          unsubscribeCurrentRSVP();
        }
      });
    
  4. Tente fazer login como vários usuários e veja a contagem aumentar com cada clique adicional no botão SIM .

Visualização do aplicativo

captura de tela desta etapa

11. Parabéns!

Você usou o Firebase para criar um aplicativo da Web interativo em tempo real!

O que cobrimos

  • Autenticação do Firebase
  • FirebaseUI
  • Cloud Firestore
  • Regras de segurança do Firebase

Próximos passos

  • Quer saber mais sobre o fluxo de trabalho do desenvolvedor do Firebase? Confira o codelab do emulador do Firebase para saber como testar e executar seu aplicativo completamente localmente.
  • Quer saber mais sobre outros produtos Firebase? Talvez você queira armazenar arquivos de imagem que os usuários carregam? Ou enviar notificações para seus usuários? Confira o codelab da Web do Firebase para ver um codelab que se aprofunda em muitos outros produtos do Firebase para a Web.
  • Quer saber mais sobre o Cloud Firestore? Talvez você queira aprender sobre subcoleções e transações? Acesse o codelab da Web do Cloud Firestore para ver um codelab mais detalhado sobre o Cloud Firestore. Ou confira esta série do YouTube para conhecer o Cloud Firestore !

Saber mais

Como foi?

Adoraríamos seu feedback! Por favor, preencha um formulário (muito) curto aqui .