1. Visão geral
Neste codelab, você vai aprender alguns dos conceitos básicos do Firebase para criar aplicativos da Web interativos. Você criará um RSVP de evento e um aplicativo de chat de livro de visitas usando vários produtos do Firebase.
O que você aprenderá
- Autentique usuários com o Firebase Authentication e a FirebaseUI.
- Sincronizar dados usando o Cloud Firestore.
- Escreva regras de segurança do Firebase para proteger um banco de dados.
O que é necessário
- Um navegador da sua escolha, como o Chrome
- Acesso a stackblitz.com sem precisar fazer login ou conta.
- Uma Conta do Google, como uma conta do Gmail. Recomendamos a conta de e-mail que você já usa na conta do GitHub. Isso permite que você use recursos avançados no StackBlitz.
- O exemplo de código do codelab. Confira a próxima etapa para saber como fazer isso.
2. Fazer o download do código inicial
Neste codelab, você vai criar um app usando o StackBlitz, um editor on-line que tem vários fluxos de trabalho do Firebase integrados. Não é preciso instalar software nem ter uma conta especial do StackBlitz.
O StackBlitz permite compartilhar projetos com outras pessoas. Outras pessoas que têm o URL do seu projeto do StackBlitz podem ver o código e bifurcar o projeto, mas não podem editá-lo.
- Acesse este URL para ver o código inicial: https://stackblitz.com/edit/firebase-gtk-web-start
- Na parte superior da página do StackBlitz, clique em Fork:
Agora você tem uma cópia do código inicial como seu próprio projeto do StackBlitz, com um nome e um URL exclusivos. Todos os seus arquivos e alterações são salvos nesse projeto do StackBlitz.
3. Editar informações do evento
Os materiais iniciais deste codelab fornecem uma estrutura para o app da Web, incluindo algumas folhas de estilo e alguns contêineres HTML para o app. Mais adiante neste codelab, você vinculará esses contêineres ao Firebase.
Para começar, vamos nos familiarizar um pouco mais com a interface do StackBlitz.
- No StackBlitz, abra o arquivo
index.html
. - Localize
event-details-container
edescription-container
e tente editar alguns detalhes do evento.
Conforme você edita o texto, o recarregamento automático de página no StackBlitz exibe os novos detalhes do evento. Legal, não é?
<!-- ... -->
<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 app vai ficar assim:
Visualização do app
4. Criar e configurar um projeto do Firebase
Exibir as informações do evento é ótimo para seus convidados, mas mostrar apenas os eventos não é muito útil para ninguém. Vamos adicionar algumas funcionalidades dinâmicas a este app. Para isso, você precisa vincular o Firebase ao seu app. Para começar a usar o Firebase, você precisa criar e configurar um projeto do Firebase.
Criar um projeto do Firebase
- Faça login no Firebase.
- No Console do Firebase, clique em Adicionar projeto (ou Criar um projeto) e nomeie seu projeto como Firebase-Web-Codelab.
- Clique nas opções de criação do projeto. Se solicitado, aceite os termos do Firebase. Na tela do Google Analytics, clique em "Não ativar", porque você não vai usar o Analytics para esse app.
Para saber mais sobre os projetos do Firebase, consulte Noções básicas sobre os projetos do Firebase.
Ativar e configurar produtos do Firebase no console
O app que você está criando usa vários produtos do Firebase disponíveis para apps da Web:
- Use o Firebase Authentication e a IU do Firebase para facilitar o login dos usuários no seu app.
- Cloud Firestore: é usado para salvar dados estruturados na nuvem e receber notificações instantâneas quando os dados são alterados.
- Regras de segurança do Firebase para proteger seu banco de dados.
Alguns desses produtos precisam de configuração especial ou ser ativados usando o Console do Firebase.
Ativar o login por e-mail para o Firebase Authentication
Para permitir que os usuários façam login no app da Web, você vai usar o método de login de E-mail/senha para este codelab:
- No painel à esquerda do Console do Firebase, clique em Build > Authentication. Em seguida, clique em Começar. Agora você está no painel do Authentication, onde pode consultar os usuários conectados, definir provedores de login e gerenciar configurações.
- Selecione a guia Método de login (ou clique aqui para acessar a guia).
- Clique em E-mail/senha nas opções do provedor, alterne a chave para Ativar e clique em Salvar.
Configurar o Cloud Firestore
O app da Web usa o Cloud Firestore para salvar mensagens de chat e receber novas mensagens.
Veja como configurar o Cloud Firestore:
- No painel à esquerda do Console do Firebase, clique em Build > Banco de dados do Firestore. Em seguida, clique em Criar banco de dados.
- Clique em Criar banco de dados.
- Selecione a opção Iniciar no modo de teste. Leia a exoneração de responsabilidade 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 Próxima.
- Selecione o local do seu banco de dados ou use o padrão. No entanto, não será possível alterar esse local depois.
- Clique em Concluído.
5. Adicionar e configurar o Firebase
Agora que seu projeto do Firebase foi criado e alguns serviços foram ativados, você precisa informar ao código que deseja usar o Firebase, bem como qual projeto do Firebase utilizar.
Adicionar as bibliotecas do Firebase
Para que seu app use o Firebase, você precisa adicionar as bibliotecas do Firebase a ele. Há várias maneiras de fazer isso, conforme descrito na documentação do Firebase. Por exemplo, você pode adicionar as bibliotecas da CDN do Google ou instalá-las localmente usando npm e empacotá-las no seu app 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 "tree shaking". Saiba mais sobre os SDKs modulares na documentação.
Para criar esse app, use as bibliotecas do Firebase Authentication, da FirebaseUI e do Cloud Firestore. Para este codelab, as seguintes instruções de importação já estão incluídas na parte de cima do arquivo index.js
, e vamos importar mais métodos de cada biblioteca do Firebase conforme avançarmos:
// 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 app da Web do Firebase ao seu projeto
- De volta ao console do Firebase, navegue até a página de visão geral do projeto clicando em Visão geral do projeto no canto superior esquerdo.
- No centro da página de visão geral do projeto, clique no ícone da Web para criar um novo app da Web do Firebase.
- Registre o app com o apelido App da Web.
- Neste codelab, NÃO marque a caixa ao lado de Também configurar o Firebase Hosting para este app. Você usará o painel de visualização do StackBlitz por enquanto.
- Clique em Registrar app.
- Copie o objeto de configuração do Firebase para a área de transferência.
- Clique em Continuar no console.Adicione o objeto de configuração do Firebase ao app:
- De volta ao StackBlitz, acesse o arquivo
index.js
. - Localize a linha de comentário
Add Firebase project configuration object here
e cole seu snippet de configuração logo abaixo do comentário. - Adicione a chamada de função
initializeApp
para configurar o Firebase usando a configuração exclusiva do seu projeto.// ... // 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 o login do usuário (RSVP)
Agora que você adicionou o Firebase ao app, configure um botão de RSVP para registrar pessoas usando o Firebase Authentication.
Autentique seus usuários com o login de e-mail e a FirebaseUI
Você precisará de um botão de RSVP que solicite que o usuário faça login com o endereço de e-mail dele. Para fazer isso, conecte a FirebaseUI a um botão de RSVP.Essa biblioteca é uma biblioteca que fornece uma interface pré-criada com base no Firebase Auth.
A FirebaseUI requer uma configuração (consulte as opções na documentação) que faz duas coisas:
- Informa à FirebaseUI que você quer usar o método de login por E-mail/senha.
- Processa o callback para um login bem-sucedido e retorna falso para evitar um redirecionamento. Você não quer que a página seja atualizada porque está criando um app da Web de uma só página.
Adicione o código para inicializar a autenticação da FirebaseUI
- No StackBlitz, acesse o arquivo
index.js
. - Na parte de cima, localize a instrução de importação
firebase/auth
e adicionegetAuth
eEmailAuthProvider
da seguinte forma:// ... // Add the Firebase products and methods that you want to use import { getAuth, EmailAuthProvider } from 'firebase/auth'; import {} from 'firebase/firestore';
- Salve uma referência ao objeto de autenticação logo após
initializeApp
, desta forma:initializeApp(firebaseConfig); auth = getAuth();
- A configuração da FirebaseUI já é fornecida no código inicial. Ele já está configurado para usar o provedor de autenticação de e-mail.
- Na parte de baixo da função
main()
emindex.js
, adicione a instrução de inicialização da FirebaseUI da seguinte maneira:async function main() { // ... // Initialize the FirebaseUI widget using Firebase const ui = new firebaseui.auth.AuthUI(auth); } main();
Adicionar um botão de RSVP ao HTML
- No StackBlitz, acesse o arquivo
index.html
. - Adicione o HTML de um botão RSVP dentro do
event-details-container
, como mostrado no exemplo abaixo.
Tenha cuidado para usar os mesmos valores deid
, conforme mostrado abaixo, porque, neste codelab, já existem hooks para esses IDs específicos no arquivoindex.js
.
No arquivoindex.html
, há um contêiner com o IDfirebaseui-auth-container
. Esse é o ID que você vai transmitir para a FirebaseUI para manter seu login.
Visualização do app<!-- ... --> <section id="event-details-container"> <!-- ... --> <!-- ADD THE RSVP BUTTON HERE --> <button id="startRsvp">RSVP</button> </section> <hr> <section id="firebaseui-auth-container"></section> <!-- ... -->
- Configure um listener no botão RSVP e chame a função de início da FirebaseUI. Isso informa à FirebaseUI que você quer ver a janela de login.
Adicione o seguinte código à parte de baixo da funçãomain()
noindex.js
:async function main() { // ... // Listen to RSVP button clicks startRsvpButton.addEventListener("click", () => { ui.start("#firebaseui-auth-container", uiConfig); }); } main();
Testar o login no app
- Na janela de visualização do StackBlitz, clique no botão "RSVP" para fazer login no aplicativo.
- Neste codelab, você pode usar qualquer endereço de e-mail, até mesmo um falso, já que você não está configurando uma etapa de verificação de e-mail neste codelab.
- Se você receber a mensagem de erro
auth/operation-not-allowed
ouThe given sign-in provider is disabled for this Firebase project
, verifique se ativou o E-mail/senha como um provedor de login no Console do Firebase.
- Acesse o painel Autenticação no Console do Firebase. Na guia Usuários, você encontra as informações da conta inseridas para fazer login no app.
Adicionar o estado de autenticação à interface
Em seguida, verifique se a interface reflete o fato de que você está conectado.
Use o callback do listener de estado do Firebase Authentication, que é notificado sempre que o status de login do usuário muda. Se houver um usuário conectado, seu app mudará o botão "RSVP" para o botão "logout".
- No StackBlitz, acesse o arquivo
index.js
. - Na parte de cima, localize a instrução de importação
firebase/auth
e adicionesignOut
eonAuthStateChanged
da seguinte forma:// ... // Add the Firebase products and methods that you want to use import { getAuth, EmailAuthProvider, signOut, onAuthStateChanged } from 'firebase/auth'; import {} from 'firebase/firestore';
- Adicione o código abaixo à parte de baixo 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();
- No listener de botão, verifique se há um usuário atual e faça logout. 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 no app vai exibir LOGOUT, e ele retornará para RSVP quando for clicado.
Visualização do app
7. Grave mensagens no Cloud Firestore
Saber que os usuários estão chegando é ótimo, mas vamos dar a eles outras coisas para fazer no app. E se eles pudessem deixar mensagens em um livro de visitas? Eles podem contar por que estão animados em participar ou quem espera conhecer.
Para armazenar as mensagens de chat que os usuários escrevem no app, use o Cloud Firestore.
Modelo de dados
O Cloud Firestore é um banco de dados NoSQL. Os dados armazenados nele são divididos em coleções, documentos, campos e subcoleções. Você armazenará cada mensagem do chat como um documento em uma coleção de nível superior chamada guestbook
.
Adicionar mensagens ao Firestore
Nesta seção, você vai adicionar a funcionalidade para que os usuários escrevam novas mensagens no banco de dados. Primeiro, adicione o HTML para os elementos da interface (campo de mensagem e botão "Enviar"). Em seguida, você adiciona o código que vincula esses elementos ao banco de dados.
Para adicionar os elementos de IU de um campo de mensagem e um botão "Enviar":
- No StackBlitz, acesse o arquivo
index.html
. - 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 app
Quando o usuário clica no botão ENVIAR, o snippet de código abaixo é acionado. Ele adiciona o conteúdo do campo de entrada da mensagem à coleção 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 guestbook
.
- No StackBlitz, acesse o arquivo
index.js
. - Na parte de cima, localize a instrução de importação
firebase/firestore
e adicionegetFirestore
,addDoc
ecollection
da seguinte maneira:// ... // 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';
- Agora, salvaremos uma referência ao objeto
db
do Firestore logo apósinitializeApp
:
:initializeApp(firebaseConfig); auth = getAuth(); db = getFirestore();
- Na parte de baixo da função
main()
, adicione o código abaixo.
Oauth.currentUser.uid
é uma referência ao ID exclusivo gerado automaticamente que o Firebase Authentication fornece a 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 que fizeram login
Você não quer que qualquer pessoa veja o bate-papo dos convidados. Uma coisa que você pode fazer para proteger o bate-papo é permitir que apenas usuários que fizeram login visualizem o livro de visitas. No caso dos seus apps, recomendamos proteger o banco de dados com as regras de segurança do Firebase. Falaremos mais sobre regras de segurança mais adiante neste codelab.
- No StackBlitz, acesse o arquivo
index.js
. - Edite o listener
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'; } });
Testar o envio de mensagens
- Verifique se você fez login no app.
- Digite uma mensagem como "Olá!" e clique em ENVIAR.
Essa ação grava a mensagem no seu banco de dados do Cloud Firestore. No entanto, você ainda não verá a mensagem no seu app da Web real porque ainda precisa implementar a recuperação dos dados. Você fará isso a seguir.
No entanto, você pode ver a mensagem recém-adicionada no Console do Firebase.
No Console do Firebase, no painel do banco de dados do Firestore, você verá a coleção guestbook
com a mensagem recém-adicionada. Se você continuar enviando mensagens, sua coleção do livro de visitas conterá muitos documentos, como este:
Console do Firebase
8. Leia mensagens
Sincronizar mensagens
Os convidados podem escrever mensagens no banco de dados, mas ainda não conseguem vê-las no app.
Para exibir mensagens, adicione listeners que são acionados quando os dados mudam e, em seguida, crie um elemento de interface que mostre novas mensagens.
Você vai adicionar um código que ouve mensagens recém-adicionadas do app. Primeiro, adicione uma seção no HTML para mostrar as mensagens:
- No StackBlitz, acesse o arquivo
index.html
. - No arquivo
guestbook-container
, adicione uma nova seção com o IDguestbook
.<!-- ... --> <section id="guestbook-container"> <h2>Discussion</h2> <form><!-- ... --></form> <section id="guestbook"></section> </section> <!-- ... -->
Em seguida, registre o listener que detecta alterações feitas nos dados:
- No StackBlitz, acesse o arquivo
index.js
. - Na parte de cima, localize a instrução de importação
firebase/firestore
e adicionequery
,orderBy
eonSnapshot
da seguinte maneira:// ... import { getFirestore, addDoc, collection, query, orderBy, onSnapshot } from 'firebase/firestore';
- Na parte de baixo da função
main()
, adicione o código abaixo para repetir todos os documentos (mensagens de livro de visitas) no banco de dados. Para saber mais sobre o que está acontecendo nesse 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 detectar mensagens no banco de dados, você criou uma consulta em uma coleção específica usando a função collection
. O código acima detecta as mudanças na coleção guestbook
, que é onde as mensagens de chat são armazenadas. As mensagens também são ordenadas por data, usando orderBy('timestamp', 'desc')
para mostrar as mensagens mais recentes na parte superior.
A função onSnapshot
usa dois parâmetros: a consulta a ser usada e uma função de callback. A função de callback é acionada quando há mudanças nos documentos que correspondem à consulta. Isso pode acontecer quando uma mensagem é excluída, modificada ou adicionada. Para mais informações, consulte a documentação do Cloud Firestore.
Testar a sincronização de mensagens
O Cloud Firestore sincroniza dados de forma automática e instantânea com os clientes inscritos no banco de dados.
- As mensagens que você criou anteriormente no banco de dados serão exibidas no app. Fique à vontade para escrever novas mensagens, que serão exibidas instantaneamente.
- Se você abrir seu espaço de trabalho em várias janelas ou guias, as mensagens serão sincronizadas em tempo real entre elas.
- (Opcional) Você pode tentar excluir, modificar ou adicionar manualmente novas mensagens diretamente na seção Banco de dados do Console do Firebase. Todas as alterações devem aparecer na interface.
Parabéns! Você está lendo documentos do Cloud Firestore no seu app.
Visualização do app
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, use o modo de teste apenas nas etapas iniciais de desenvolvimento. A prática recomendada é configurar regras de segurança para o banco de dados ao desenvolver o app. A segurança é essencial para a estrutura e o comportamento do app.
Com as regras de segurança, você controla o acesso a documentos e coleções no seu banco de dados. A sintaxe de regras flexíveis permite que você crie regras que correspondem desde todas as gravações em todo o banco de dados até operações em um documento específico.
É possível escrever regras de segurança para o Cloud Firestore no Console do Firebase:
- Na seção Criar do Console do Firebase, clique em Banco de dados do Firestore e selecione a guia Regras (ou clique aqui para acessar a guia Regras).
- Serão exibidas as regras de segurança padrão a seguir, com um limite de tempo de acesso público para algumas semanas a partir de hoje.
Identificar coleções
Primeiro, identifique as coleções em que o app grava dados.
- Exclua a cláusula
match /{document=**}
para que suas regras fiquem assim:rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { } }
- Em
match /databases/{database}/documents
, identifique a coleção que você quer 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 de livro de visitas, é possível obter o UID de autenticação e verificar se qualquer pessoa que tentar gravar no documento tem um UID de autenticação correspondente.
- 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; } } }
- Clique em Publicar para implantar as novas regras.Agora, no livro de visitas, apenas os usuários que fizerem login poderão ler mensagens (qualquer mensagem), mas só será possível criar uma mensagem usando seu ID de usuário. Também não permitimos que mensagens sejam editadas ou excluídas.
Adicionar regras de validação
- Adicione a 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; } } }
- Clique em Publicar para implantar as novas regras.
Redefinir listeners
Como o app agora só permite que usuários autenticados façam login, mova a consulta firestore
do livro de visitas para o listener do Authentication. Caso contrário, vão ocorrer erros de permissão, e o app será desconectado quando o usuário sair.
- No StackBlitz, acesse o arquivo
index.js
. - Extraia o listener
onSnapshot
da coleção do livro de visitas para uma nova função com o nomesubscribeGuestbook
. Além disso, atribua os resultados da funçãoonSnapshot
à variávelguestbookListener
.
O listeneronSnapshot
do Firestore retorna uma função de cancelamento de inscrição que pode ser usada para fazer isso mais tarde.// ... // 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); }); }); }
- Adicione uma nova função abaixo chamada
unsubscribeGuestbook
. Confira se a variávelguestbookListener
não é nula. Em seguida, chame a função para cancelar o listener.// ... // Unsubscribe from guestbook updates function unsubscribeGuestbook() { if (guestbookListener != null) { guestbookListener(); guestbookListener = null; } }
Por fim, adicione as novas funções ao callback onAuthStateChanged
.
- Adicione
subscribeGuestbook()
à parte de baixo doif (user)
. - Adicione
unsubscribeGuestbook()
na parte de baixo da instruçãoelse
.// ... // 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 você aprendeu
Registrar o status de RSVP de um convidado
No momento, o app só permite que as pessoas comecem a conversar se tiverem interesse no evento. A única maneira de saber se alguém vai participar é postando o vídeo no chat. Vamos nos organizar e informar quantas pessoas vão participar.
Você vai adicionar um botão para registrar as pessoas que vão participar do evento e, em seguida, coletar uma contagem de quantas pessoas vão participar.
- No StackBlitz, acesse o arquivo
index.html
. - Em
guestbook-container
, adicione um conjunto de botões SIM e NÃO, da seguinte maneira:<!-- ... --> <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 app
Em seguida, registre o listener para cliques no botão. Se o usuário clicar em YES, use o UID de autenticação dele para salvar a resposta no banco de dados.
- No StackBlitz, acesse o arquivo
index.js
. - Na parte de cima, localize a instrução de importação
firebase/firestore
e adicionedoc
,setDoc
ewhere
da seguinte maneira:// ... // Add the Firebase products and methods that you want to use import { getFirestore, addDoc, collection, query, orderBy, onSnapshot, doc, setDoc, where } from 'firebase/firestore';
- Na parte inferior da função
main()
, adicione o seguinte código para detectar o status de RSVP:async function main() { // ... // Listen to RSVP responses rsvpYes.onclick = async () => { }; rsvpNo.onclick = async () => { }; } main();
- Em seguida, crie uma nova coleção chamada
attendees
e registre uma referência de documento se um botão "RSVP" for clicado. Defina essa referência comotrue
oufalse
, dependendo do botão que for clicado.
Primeiro, pararsvpYes
:
Depois, o mesmo para// ... // 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); } };
rsvpNo
, mas com o valorfalse
: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); } };
Atualizar suas regras de segurança
Como você já tem algumas regras configuradas, os novos dados adicionados com os botões serão rejeitados.
Permitir adições à coleção attendees
Será necessário atualizar as regras para permitir a adição à coleção attendees
.
- Para a coleção
attendees
, como você usou o UID de autenticação como o nome do documento, é possível encontrá-lo e verificar se ouid
do remetente é igual ao documento que ele está gravando. Você permitirá que todos leiam a lista de participantes (já que não há dados privados), mas apenas o criador de conteúdo 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; } } }
- Clique em Publicar para implantar as novas regras.
Adicionar regras de validação
- 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; } } }
- Não se esqueça de clicar em Publicar para implantar suas regras.
(Opcional) Agora é possível ver os resultados ao clicar nos botões. Acesse o painel do Cloud Firestore no Console do Firebase.
Ler o status de RSVP
Agora que você registrou as respostas, é hora de saber quem está chegando e refletir isso na interface.
- No StackBlitz, acesse o arquivo
index.html
. - No
description-container
, adicione um novo elemento com o IDnumber-attending
.<!-- ... --> <section id="description-container"> <!-- ... --> <p id="number-attending"></p> </section> <!-- ... -->
Em seguida, registre o listener da coleção attendees
e conte o número de respostas YES:
- No StackBlitz, acesse o arquivo
index.js
. - Na parte de baixo da função
main()
, adicione o código a seguir para detectar 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.
- Crie uma função que verifica se o UID do Authentication atual tem uma entrada na coleção
attendees
e defina a classe de botão comoclicked
.// ... // 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'; } } }); }
- Além disso, vamos criar uma função para cancelar a inscrição. Ele será usado quando o usuário sair.
// ... function unsubscribeCurrentRSVP() { if (rsvpListener != null) { rsvpListener(); rsvpListener = null; } rsvpYes.className = ''; rsvpNo.className = ''; }
- Chame as funções do listener do Authentication.
// ... // 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(); // Subscribe 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(); } });
- Tente fazer login como vários usuários e observe o aumento na contagem a cada clique adicional no botão SIM.
Visualização do app
11. Parabéns!
Você usou o Firebase para criar um aplicativo da Web interativo em tempo real.
O que vimos
- Firebase Authentication
- FirebaseUI
- Cloud Firestore
- Regras de segurança do Firebase
Próximas etapas
- Quer saber mais sobre o fluxo de trabalho do desenvolvedor do Firebase? Confira o codelab do emulador do Firebase para aprender a testar e executar seu app de forma completa localmente.
- Quer saber mais sobre outros produtos do Firebase? Talvez você queira armazenar arquivos de imagem enviados pelos usuários? Ou enviar notificações para os usuários? Confira o codelab da Web do Firebase para um codelab que se aprofunda em muitos outros produtos do Firebase para a Web.
- Quer saber mais sobre o Cloud Firestore? Talvez você queira saber mais sobre subcoleções e transações? Acesse o codelab da Web do Cloud Firestore para mais detalhes sobre o Cloud Firestore. Ou confira esta série do YouTube para conhecer o Cloud Firestore.
Saiba mais
- Site do Firebase: firebase.google.com
- Canal do Firebase no YouTube
Como foi?
Queremos saber sua opinião. Preencha um formulário (bem) curto aqui.