Codelab da Web AngularFire

1. Visão Geral

Neste codelab, você aprenderá a usar o AngularFire para criar aplicativos da Web implementando e implantando um cliente de chat usando produtos e serviços do Firebase.

angularfire-2.png

O que você aprenderá

  • Crie um aplicativo da web usando Angular e Firebase.
  • Sincronize dados usando o Cloud Firestore e o Cloud Storage for Firebase.
  • Autentique seus usuários usando o Firebase Authentication.
  • Implante seu aplicativo da web no Firebase Hosting.
  • Envie notificações com o Firebase Cloud Messaging.
  • Colete os dados de desempenho do seu aplicativo web.

O que você precisará

  • O IDE/editor de texto de sua escolha, como WebStorm , Atom , Sublime ou VS Code
  • O gerenciador de pacotes npm , que normalmente vem com o Node.js
  • Um terminal/console
  • Um navegador de sua preferência, como o Chrome
  • O código de amostra do codelab (veja a próxima etapa do codelab para saber como conseguir o código).

2. Obtenha o código de exemplo

Clone o repositório GitHub do codelab na linha de comando:

git clone https://github.com/firebase/codelab-friendlychat-web

Alternativamente, se você não tiver o git instalado, poderá baixar o repositório como um arquivo ZIP .

Importe o aplicativo inicial

Usando seu IDE, abra ou importe o diretório 📁 angularfire-start do repositório clonado. Este diretório 📁 angularfire-start contém o código inicial do codelab, que será um aplicativo web de bate-papo totalmente funcional.

3. Crie e configure um projeto Firebase

Crie um projeto do Firebase

  1. Faça login no Firebase .
  2. No console do Firebase, clique em Adicionar projeto e nomeie seu projeto do Firebase como FriendlyChat . Lembre-se do ID do seu projeto do Firebase.
  3. Desmarque Ativar Google Analytics para este projeto
  4. Clique em Criar projeto .

O aplicativo que você criará usa produtos do Firebase disponíveis para aplicativos da Web:

  • Firebase Authentication para permitir que seus usuários façam login facilmente em seu aplicativo.
  • Cloud Firestore para salvar dados estruturados na nuvem e receber notificações instantâneas quando os dados forem alterados.
  • Cloud Storage para Firebase para salvar arquivos na nuvem.
  • Firebase Hosting para hospedar e servir seus ativos.
  • Firebase Cloud Messaging para enviar notificações push e exibir notificações pop-up do navegador.
  • Monitoramento de desempenho do Firebase para coletar dados de desempenho do usuário para seu aplicativo.

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

Adicione um aplicativo da Web do Firebase ao projeto

  1. Clique no ícone da web 58d6543a156e56f9.png para criar um novo aplicativo da web do Firebase.
  2. Registre o aplicativo com o apelido Friendly Chat e marque a caixa ao lado de Configurar também o Firebase Hosting para este aplicativo . Clique em Registrar aplicativo .
  3. Na próxima etapa, você verá um objeto de configuração. Copie apenas o objeto JS (não o HTML ao redor) para firebase-config.js

Registrar captura de tela do aplicativo da web

Ative o login do Google para Firebase Authentication

Para permitir que os usuários façam login no aplicativo Web com suas contas do Google, você usará o método de login do Google .

Você precisará ativar o login do Google :

  1. No console do Firebase, localize a seção Build no painel esquerdo.
  2. Clique em Autenticação e, em seguida, clique na guia Método de login (ou clique aqui para ir diretamente para lá).
  3. Ative o provedor de login do Google e clique em Salvar .
  4. Defina o nome público do seu aplicativo como Friendly Chat e escolha um e-mail de suporte do projeto no menu suspenso.
  5. Configure sua tela de consentimento do OAuth no Console do Google Cloud e adicione um logotipo:

d89fb3873b5d36ae.png

Ativar o Cloud Firestore

O aplicativo da web usa o Cloud Firestore para salvar mensagens de chat e receber novas mensagens de chat.

Você precisará ativar o Cloud Firestore:

  1. Na seção Build do console do Firebase, clique em Firestore Database .
  2. Clique em Criar banco de dados no painel Cloud Firestore.

729991a081e7cd5.png

  1. Selecione a opção Iniciar em modo de teste e clique em Avançar após ler 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. Você tornará nosso banco de dados mais seguro posteriormente neste codelab.

77e4986cbeaf9dee.png

  1. Defina o local onde seus dados do Cloud Firestore são armazenados. Você pode deixar isso como padrão ou escolher uma região mais próxima de você. Clique em Concluído para provisionar o Firestore.

9f2bb0d4e7ca49c7.png

Habilitar armazenamento em nuvem

O aplicativo da web usa Cloud Storage for Firebase para armazenar, fazer upload e compartilhar imagens.

Você precisará ativar o Cloud Storage:

  1. Na seção Build do console do Firebase, clique em Storage .
  2. Se não houver um botão Começar , significa que o armazenamento em nuvem já está ativado e você não precisa seguir as etapas abaixo.
  3. Clique em Começar .
  4. Leia a isenção de responsabilidade sobre as regras de segurança do seu projeto do Firebase e clique em Avançar .

Com as regras de segurança padrão, qualquer usuário autenticado pode gravar qualquer coisa no Cloud Storage. Você tornará nosso armazenamento mais seguro posteriormente neste codelab.

62f1afdcd1260127.png

  1. O local do Cloud Storage é pré-selecionado com a mesma região escolhida para seu banco de dados do Cloud Firestore. Clique em Concluído para concluir a configuração.

1d7f49ebaddb32fc.png

4. Instale a interface de linha de comando do Firebase

A interface de linha de comando (CLI) do Firebase permite que você use o Firebase Hosting para servir seu aplicativo da Web localmente, bem como para implantar seu aplicativo da Web em seu projeto do Firebase.

  1. Instale a CLI executando o seguinte comando npm:
npm -g install firebase-tools
  1. Verifique se a CLI foi instalada corretamente executando o seguinte comando:
firebase --version

Certifique-se de que a versão do Firebase CLI seja v4.1.0 ou posterior.

  1. Autorize a CLI do Firebase executando o seguinte comando:
firebase login

Você configurou o modelo de aplicativo da Web para extrair a configuração do seu aplicativo para o Firebase Hosting do diretório local do seu aplicativo (o repositório que você clonou anteriormente no codelab). Mas para obter a configuração, você precisa associar seu aplicativo ao projeto do Firebase.

  1. Certifique-se de que sua linha de comando esteja acessando o diretório angularfire-start local do seu aplicativo.
  2. Associe seu aplicativo ao projeto do Firebase executando o seguinte comando:
firebase use --add
  1. Quando solicitado, selecione o ID do projeto e forneça um alias ao projeto do Firebase.

Um alias é útil se você tiver vários ambientes (produção, teste, etc.). No entanto, para este codelab, vamos usar apenas o alias default .

  1. Siga as instruções restantes em sua linha de comando.

5. Instale o AngularFire

Antes de executar o projeto, certifique-se de ter o Angular CLI e o AngularFire configurados.

  1. Em um console, execute o seguinte comando:
npm install -g @angular/cli
  1. Em seguida, em um console do diretório angularfire-start , execute o seguinte comando Angular CLI:
ng add @angular/fire

Isso instalará todas as dependências necessárias para o seu projeto.

  1. Quando solicitado, selecione os recursos que foram configurados no Firebase Console ( ng deploy -- hosting , Authentication , Firestore , Cloud Functions (callable) , Cloud Messaging , Cloud Storage ) e siga as instruções no console.

6. Execute o aplicativo inicial localmente

Agora que importou e configurou seu projeto, você está pronto para executar o aplicativo web pela primeira vez.

  1. Em um console do diretório angularfire-start , execute o seguinte comando Firebase CLI:
firebase emulators:start
  1. Sua linha de comando deve exibir a seguinte resposta:
✔  hosting: Local server: http://localhost:5000

Você está usando o emulador do Firebase Hosting para disponibilizar nosso aplicativo localmente. O aplicativo da web agora deve estar disponível em http://localhost:5000 . Todos os arquivos localizados no subdiretório src são servidos.

  1. Usando seu navegador, abra seu aplicativo em http://localhost:5000 .

Você deverá ver a interface do usuário do seu aplicativo FriendlyChat, que (ainda!) não está funcionando:

angularfire-2.png

O aplicativo não pode fazer nada agora, mas com a sua ajuda, fará em breve! Você só definiu a interface do usuário até agora.

Vamos agora construir um chat em tempo real!

7. Importe e configure o Firebase

Configurar o Firebase

Você precisará configurar o SDK do Firebase para informar qual projeto do Firebase você está usando.

  1. Vá para as configurações do seu projeto no console do Firebase
  2. No cartão "Seus aplicativos", selecione o apelido do aplicativo para o qual você precisa de um objeto de configuração.
  3. Selecione "Config" no painel de snippets do SDK do Firebase.

Você descobrirá que um arquivo de ambiente /angularfire-start/src/environments/environment.ts foi gerado para você.

  1. Copie o snippet do objeto de configuração e adicione-o a angularfire-start/src/firebase-config.js .

ambiente.ts

export const environment = {
  firebase: {
    apiKey: "API_KEY",
    authDomain: "PROJECT_ID.firebaseapp.com",
    databaseURL: "https://PROJECT_ID.firebaseio.com",
    projectId: "PROJECT_ID",
    storageBucket: "PROJECT_ID.appspot.com",
    messagingSenderId: "SENDER_ID",
    appId: "APP_ID",
    measurementId: "G-MEASUREMENT_ID",
  },
};

Importar AngularFire

Você descobrirá que os recursos selecionados no console foram roteados automaticamente no arquivo /angularfire-start/src/app/app.module.ts . Isso permite que seu aplicativo use recursos e funcionalidades do Firebase. Porém, para desenvolver em um ambiente local, você precisa conectá-los para usar o pacote Emulator.

  1. Em /angularfire-start/src/app/app.module.ts , encontre a seção imports e modifique as funções fornecidas para conectar-se ao pacote Emulator em ambientes que não sejam de produção.
// ...

import { provideAuth,getAuth, connectAuthEmulator } from '@angular/fire/auth';
import { provideFirestore,getFirestore, connectFirestoreEmulator } from '@angular/fire/firestore';
import { provideFunctions,getFunctions, connectFunctionsEmulator } from '@angular/fire/functions';
import { provideMessaging,getMessaging } from '@angular/fire/messaging';
import { provideStorage,getStorage, connectStorageEmulator } from '@angular/fire/storage';

// ...

provideFirebaseApp(() => initializeApp(environment.firebase)),
provideAuth(() => {
    const auth = getAuth();
    if (location.hostname === 'localhost') {
        connectAuthEmulator(auth, 'http://127.0.0.1:9099', { disableWarnings: true });
    }
    return auth;
}),
provideFirestore(() => {
    const firestore = getFirestore();
    if (location.hostname === 'localhost') {
        connectFirestoreEmulator(firestore, '127.0.0.1', 8080);
    }
    return firestore;
}),
provideFunctions(() => {
    const functions = getFunctions();
    if (location.hostname === 'localhost') {
        connectFunctionsEmulator(functions, '127.0.0.1', 5001);
    }
    return functions;
}),
provideStorage(() => {
    const storage = getStorage();
    if (location.hostname === 'localhost') {
        connectStorageEmulator(storage, '127.0.0.1', 5001);
    }
    return storage;
}),
provideMessaging(() => {
    return getMessaging();
}),

// ...

app.module.ts

Durante este codelab, você usará Firebase Authentication, Cloud Firestore, Cloud Storage, Cloud Messaging e Performance Monitoring, portanto, importará todas as suas bibliotecas. Em seus aplicativos futuros, certifique-se de importar apenas as partes do Firebase necessárias para reduzir o tempo de carregamento do seu aplicativo.

8. Configure o login do usuário

AngularFire agora deve estar pronto para uso, pois foi importado e inicializado em app.module.ts . Agora você implementará o login do usuário usando o Firebase Authentication .

Autentique seus usuários com o Login do Google

No aplicativo, quando um usuário clica no botão Fazer login com o Google , a função login é acionada. (Você já configurou isso!) Para este codelab, você quer autorizar o Firebase a usar o Google como provedor de identidade. Você usará um pop-up, mas vários outros métodos estão disponíveis no Firebase.

  1. No diretório angularfire-start , no subdiretório /src/app/services/ , abra chat.service.ts .
  2. Encontre a função login .
  3. Substitua a função inteira pelo código a seguir.

chat.serviço.ts

// Signs-in Friendly Chat.
login() {
    signInWithPopup(this.auth, this.provider).then((result) => {
        const credential = GoogleAuthProvider.credentialFromResult(result);
        this.router.navigate(['/', 'chat']);
        return credential;
    })
}

A função logout é acionada quando o usuário clica no botão Sair .

  1. Volte para o arquivo src/app/services/chat.service.ts .
  2. Encontre a função logout .
  3. Substitua a função inteira pelo código a seguir.

chat.serviço.ts

// Logout of Friendly Chat.
logout() {
    signOut(this.auth).then(() => {
        this.router.navigate(['/', 'login'])
        console.log('signed out');
    }).catch((error) => {
        console.log('sign out error: ' + error);
    })
}

Rastreie o estado de autenticação

Para atualizar nossa IU de acordo, você precisa verificar se o usuário está conectado ou desconectado. Com o Firebase Authentication, você pode recuperar dados observáveis ​​no estado do usuário que serão acionados sempre que o estado de autenticação mudar.

  1. Volte para o arquivo src/app/services/chat.service.ts .
  2. Encontre a atribuição de variável user$ .
  3. Substitua toda a atribuição pelo código a seguir.

chat.serviço.ts

// Observable user
user$ = user(this.auth);

O código acima chama a função AngularFire user que retorna um usuário observável. Ele será acionado sempre que o estado de autenticação for alterado (quando o usuário entrar ou sair). É nesse ponto que você atualizará a IU para redirecionar, exibir o usuário na navegação do cabeçalho e assim por diante. Todas essas partes da UI já foram implementadas.

Teste o login no aplicativo

  1. Se seu aplicativo ainda estiver sendo veiculado, atualize-o no navegador. Caso contrário, execute firebase emulators:start na linha de comando para começar a servir o aplicativo em http://localhost:5000 e, em seguida, abra-o em seu navegador.
  2. Faça login no aplicativo usando o botão de login e sua conta do Google. Se você vir uma mensagem de erro informando auth/operation-not-allowed , verifique se você ativou o Login do Google como provedor de autenticação no console do Firebase.
  3. Após o login, sua foto de perfil e nome de usuário deverão ser exibidos: angularfire-3.png

9. Escreva mensagens no Cloud Firestore

Nesta seção, você gravará alguns dados no Cloud Firestore para preencher a IU do aplicativo. Isso pode ser feito manualmente com o console do Firebase , mas você fará isso no próprio aplicativo para demonstrar uma gravação básica do Cloud Firestore.

Modelo de dados

Os dados do Cloud Firestore 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 messages .

688d7bc5fb662b57.png

Adicionar mensagens ao Cloud Firestore

Para armazenar as mensagens de chat escritas pelos usuários, você usará o Cloud Firestore .

Nesta seção, você adicionará a funcionalidade para que os usuários gravem novas mensagens em seu banco de dados. Um usuário clicando no botão ENVIAR acionará o snippet de código abaixo. Ele adiciona um objeto de mensagem com o conteúdo dos campos de mensagem à sua instância do Cloud Firestore na coleção messages . O método add() adiciona um novo documento com um ID gerado automaticamente à coleção.

  1. Volte para o arquivo src/app/services/chat.service.ts .
  2. Encontre a função addMessage .
  3. Substitua a função inteira pelo código a seguir.

chat.serviço.ts

// Adds a text or image message to Cloud Firestore.
addMessage = async(textMessage: string | null, imageUrl: string | null): Promise<void | DocumentReference<DocumentData>> => {
    let data: any;
    try {
      this.user$.subscribe(async (user) => 
      { 
        if(textMessage && textMessage.length > 0) {
          data =  await addDoc(collection(this.firestore, 'messages'), {
            name: user?.displayName,
            text: textMessage,
            profilePicUrl: user?.photoURL,
            timestamp: serverTimestamp(),
            uid: user?.uid
          })}
          else if (imageUrl && imageUrl.length > 0) {
            data =  await addDoc(collection(this.firestore, 'messages'), {
              name: user?.displayName,
              imageUrl: imageUrl,
              profilePicUrl: user?.photoURL,
              timestamp: serverTimestamp(),
              uid: user?.uid
            });
          }
          return data;
        }
      );
    }
    catch(error) {
      console.error('Error writing new message to Firebase Database', error);
      return;
    }
}

Teste o envio de mensagens

  1. Se seu aplicativo ainda estiver sendo veiculado, atualize-o no navegador. Caso contrário, execute firebase emulators:start na linha de comando para começar a servir o aplicativo em http://localhost:5000 e, em seguida, abra-o em seu navegador.
  2. Após fazer login, digite uma mensagem como "Olá!" e clique em ENVIAR . Isso gravará a mensagem no Cloud Firestore. No entanto, você ainda não verá os dados no seu aplicativo da Web real porque ainda precisará implementar a recuperação dos dados (a próxima seção do codelab).
  3. Você pode ver a mensagem recém-adicionada em seu Firebase Console. Abra a interface do usuário do pacote do emulador. Na seção Build , clique em Firestore Database (ou clique aqui e você deverá ver a coleção de mensagens com sua mensagem recém-adicionada:

6812efe7da395692.png

10. Leia mensagens

Sincronizar mensagens

Para ler mensagens no aplicativo, você precisará adicionar um observável que será acionado quando os dados forem alterados e, em seguida, criar um elemento de UI que mostre novas mensagens.

Você adicionará um código que escuta mensagens recém-adicionadas do aplicativo. Neste código, você recuperará o instantâneo da coleção messages . Você exibirá apenas as últimas 12 mensagens do chat para evitar a exibição de um histórico muito longo ao carregar.

  1. Volte para o arquivo src/app/services/chat.service.ts .
  2. Encontre a função loadMessages .
  3. Substitua a função inteira pelo código a seguir.

chat.serviço.ts

// Loads chat message history and listens for upcoming ones.
loadMessages = () => {
  // Create the query to load the last 12 messages and listen for new ones.
  const recentMessagesQuery = query(collection(this.firestore, 'messages'), orderBy('timestamp', 'desc'), limit(12));
  // Start listening to the query.
  return collectionData(recentMessagesQuery);
}

Para ouvir mensagens no banco de dados, você cria uma consulta em uma coleção usando a função collection para especificar em qual coleção estão os dados que você deseja ouvir. No código acima, você está ouvindo as alterações nas messages coleção, que é onde as mensagens de bate-papo são armazenadas. Você também está aplicando um limite ouvindo apenas as últimas 12 mensagens usando limit(12) e ordenando as mensagens por data usando orderBy('timestamp', 'desc') para obter as 12 mensagens mais recentes.

A função collectionData usa instantâneos nos bastidores. A função de retorno de chamada será acionada quando houver alguma alteração nos documentos que correspondam à consulta. Isso pode ocorrer se uma mensagem for excluída, modificada ou adicionada. Você pode ler mais sobre isso na documentação do Cloud Firestore .

Testar mensagens de sincronização

  1. Se seu aplicativo ainda estiver sendo veiculado, atualize-o no navegador. Caso contrário, execute firebase emulators:start na linha de comando para começar a servir o aplicativo em http://localhost:5000 e, em seguida, abra-o em seu navegador.
  2. As mensagens que você criou anteriormente no banco de dados devem ser exibidas na UI do FriendlyChat (veja abaixo). Sinta-se à vontade para escrever novas mensagens; eles devem aparecer instantaneamente.
  3. (Opcional) Você pode tentar excluir, modificar ou adicionar manualmente novas mensagens diretamente na seção Firestore do pacote Emulator; quaisquer alterações devem ser refletidas na IU.

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

angularfire-2.png

11. Envie imagens

Agora você adicionará um recurso que compartilha imagens.

Embora o Cloud Firestore seja bom para armazenar dados estruturados, o Cloud Storage é mais adequado para armazenar arquivos. O Cloud Storage para Firebase é um serviço de armazenamento de arquivos/blobs e você o usará para armazenar quaisquer imagens que um usuário compartilhe usando nosso aplicativo.

Salve imagens no Cloud Storage

Neste codelab, você já adicionou um botão que aciona uma caixa de diálogo de seletor de arquivos. Após selecionar um arquivo, a função saveImageMessage é chamada e você pode obter uma referência ao arquivo selecionado. A função saveImageMessage realiza o seguinte:

  1. Cria uma mensagem de bate-papo "espaço reservado" no feed de bate-papo, para que os usuários vejam uma animação "Carregando" enquanto você carrega a imagem.
  2. Faz upload do arquivo de imagem para o Cloud Storage neste caminho: /<uid>/<file_name>
  3. Gera um URL legível publicamente para o arquivo de imagem.
  4. Atualiza a mensagem de bate-papo com o URL do arquivo de imagem recém-carregado em vez da imagem de carregamento temporário.

Agora você adicionará a funcionalidade para enviar uma imagem:

  1. Volte para o arquivo src/index.js .
  2. Encontre a função saveImageMessage .
  3. Substitua a função inteira pelo código a seguir.

index.js

// Saves a new message containing an image in Firebase.
// This first saves the image in Firebase storage.
saveImageMessage = async(file: any) => {
  try {
    // 1 - You add a message with a loading icon that will get updated with the shared image.
    const messageRef = await this.addMessage(null, this.LOADING_IMAGE_URL);

    // 2 - Upload the image to Cloud Storage.
    const filePath = `${this.auth.currentUser?.uid}/${file.name}`;
    const newImageRef = ref(this.storage, filePath);
    const fileSnapshot = await uploadBytesResumable(newImageRef, file);
    
    // 3 - Generate a public URL for the file.
    const publicImageUrl = await getDownloadURL(newImageRef);

    // 4 - Update the chat message placeholder with the image's URL.
    messageRef ?
    await updateDoc(messageRef,{
      imageUrl: publicImageUrl,
      storageUri: fileSnapshot.metadata.fullPath
    }): null;
  } catch (error) {
    console.error('There was an error uploading a file to Cloud Storage:', error);
  }
}

Teste o envio de imagens

  1. Se seu aplicativo ainda estiver sendo veiculado, atualize-o no navegador. Caso contrário, execute firebase emulators:start na linha de comando para começar a servir o aplicativo em http://localhost:5000 e, em seguida, abra-o em seu navegador.
  2. Após fazer login, clique no botão de upload de imagem no canto inferior esquerdo angularfire-4.png e selecione um arquivo de imagem usando o seletor de arquivos. Se você está procurando uma imagem, fique à vontade para usar esta bela imagem de uma xícara de café .
  3. Uma nova mensagem deve aparecer na interface do aplicativo com a imagem selecionada: angularfire-2.png

Se você tentar adicionar uma imagem sem fazer login, verá um erro informando que você deve fazer login para adicionar imagens.

12. Mostrar notificações

Agora você adicionará suporte para notificações do navegador. O aplicativo notificará os usuários quando novas mensagens forem postadas no chat. Firebase Cloud Messaging (FCM) é uma solução de mensagens multiplataforma que permite entregar mensagens e notificações de maneira confiável e sem nenhum custo.

Adicione o service worker do FCM

O aplicativo da web precisa de um service worker que receba e exiba notificações da web.

O provedor de mensagens já deveria ter sido configurado quando o AngularFire foi adicionado, certifique-se de que o código a seguir exista na seção de importações de /angularfire-start/src/app/app.module.ts

provideMessaging(() => {
    return getMessaging();
}),

app/app.module.ts

O service worker simplesmente precisa carregar e inicializar o Firebase Cloud Messaging SDK, que se encarregará de exibir notificações.

Obtenha tokens de dispositivo FCM

Quando as notificações forem ativadas em um dispositivo ou navegador, você receberá um token de dispositivo . Este token de dispositivo é o que você usa para enviar uma notificação para um determinado dispositivo ou navegador específico.

Quando o usuário fizer login, você chamará a função saveMessagingDeviceToken . É aí que você obterá o token do dispositivo FCM do navegador e o salvará no Cloud Firestore.

chat.serviço.ts

  1. Encontre a função saveMessagingDeviceToken .
  2. Substitua a função inteira pelo código a seguir.

chat.serviço.ts

// Saves the messaging device token to Cloud Firestore.
saveMessagingDeviceToken= async () => {
    try {
      const currentToken = await getToken(this.messaging);
      if (currentToken) {
        console.log('Got FCM device token:', currentToken);
        // Saving the Device Token to Cloud Firestore.
        const tokenRef = doc(this.firestore, 'fcmTokens', currentToken);
        await setDoc(tokenRef, { uid: this.auth.currentUser?.uid });
 
        // This will fire when a message is received while the app is in the foreground.
        // When the app is in the background, firebase-messaging-sw.js will receive the message instead.
        onMessage(this.messaging, (message) => {
          console.log(
            'New foreground notification from Firebase Messaging!',
            message.notification
          );
        });
      } else {
        // Need to request permissions to show notifications.
        this.requestNotificationsPermissions();
      }
    } catch(error) {
      console.error('Unable to get messaging token.', error);
    };
}

No entanto, este código não funcionará inicialmente. Para que seu app consiga recuperar o token do dispositivo, o usuário precisa conceder permissão ao app para mostrar notificações (a próxima etapa do codelab).

Solicite permissões para mostrar notificações

Quando o usuário ainda não tiver concedido permissão ao seu aplicativo para mostrar notificações, você não receberá um token de dispositivo. Nesse caso, você chama o método requestPermission() , que exibirá uma caixa de diálogo do navegador solicitando essa permissão ( em navegadores suportados ).

8b9d0c66dc36153d.png

  1. Volte para o arquivo src/app/services/chat.service.ts .
  2. Encontre a função requestNotificationsPermissions .
  3. Substitua a função inteira pelo código a seguir.

chat.serviço.ts

// Requests permissions to show notifications.
requestNotificationsPermissions = async () => {
    console.log('Requesting notifications permission...');
    const permission = await Notification.requestPermission();
    
    if (permission === 'granted') {
      console.log('Notification permission granted.');
      // Notification permission granted.
      await this.saveMessagingDeviceToken();
    } else {
      console.log('Unable to get permission to notify.');
    }
}

Obtenha o token do seu dispositivo

  1. Se seu aplicativo ainda estiver sendo veiculado, atualize-o no navegador. Caso contrário, execute firebase emulators:start na linha de comando para começar a servir o aplicativo em http://localhost:5000 e, em seguida, abra-o em seu navegador.
  2. Após o login, a caixa de diálogo de permissão de notificações deverá aparecer: bd3454e6dbfb6723.png
  3. Clique em Permitir .
  4. Abra o console JavaScript do seu navegador. Você deverá ver a seguinte mensagem: Got FCM device token: cWL6w:APA91bHP...4jDPL_A-wPP06GJp1OuekTaTZI5K2Tu
  5. Copie o token do seu dispositivo. Você precisará dele na próxima etapa do codelab.

Envie uma notificação para o seu dispositivo

Agora que você tem o token do seu dispositivo, pode enviar uma notificação.

  1. Abra a guia Cloud Messaging do console do Firebase .
  2. Clique em "Nova Notificação"
  3. Insira um título e um texto de notificação para a notificação.
  4. No lado direito da tela, clique em “enviar uma mensagem de teste”
  5. Insira o token do dispositivo que você copiou do console JavaScript do seu navegador e clique no sinal de mais ("+")
  6. Clique em "teste"

Se seu aplicativo estiver em primeiro plano, você verá a notificação no console JavaScript.

Se o seu aplicativo estiver em segundo plano, uma notificação deverá aparecer no seu navegador, como neste exemplo:

de79e8638a45864c.png

13. Regras de segurança do Cloud Firestore

Ver regras de segurança do banco de dados

O Cloud Firestore utiliza uma linguagem de regras específica para definir direitos de acesso, segurança e validações de dados.

Ao configurar o projeto do Firebase no início deste codelab, você optou por usar regras de segurança padrão do "Modo de teste" para não restringir o acesso ao armazenamento de dados. No console do Firebase , na guia Regras da seção Banco de dados , você pode visualizar e modificar essas regras.

Neste momento, você deverá ver as regras padrão, que não restringem o acesso ao armazenamento de dados. Isso significa que qualquer usuário pode ler e gravar em qualquer coleção do seu armazenamento de dados.

rules_version = '2';

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write;
    }
  }
}

Você atualizará as regras para restringir coisas usando as seguintes regras:

firestore.rules

rules_version = '2';

service cloud.firestore {
  match /databases/{database}/documents {
    // Messages:
    //   - Anyone can read.
    //   - Authenticated users can add and edit messages.
    //   - Validation: Check name is same as auth token and text length below 300 char or that imageUrl is a URL.
    //   - Deletes are not allowed.
    match /messages/{messageId} {
      allow read;
      allow create, update: if request.auth != null
                    && request.resource.data.name == request.auth.token.name
                    && (request.resource.data.text is string
                      && request.resource.data.text.size() <= 300
                      || request.resource.data.imageUrl is string
                      && request.resource.data.imageUrl.matches('https?://.*'));
      allow delete: if false;
    }
    // FCM Tokens:
    //   - Anyone can write their token.
    //   - Reading list of tokens is not allowed.
    match /fcmTokens/{token} {
      allow read: if false;
      allow write;
    }
  }
}

As regras de segurança devem ser atualizadas automaticamente para o seu pacote de emuladores.

Ver regras de segurança do Cloud Storage

O Cloud Storage para Firebase usa uma linguagem de regras específica para definir direitos de acesso, segurança e validações de dados.

Ao configurar o projeto do Firebase no início deste codelab, você optou por usar a regra de segurança padrão do Cloud Storage, que permite apenas que usuários autenticados usem o Cloud Storage. No console do Firebase , na guia Regras da seção Armazenamento , você pode visualizar e modificar regras. Você deverá ver a regra padrão que permite que qualquer usuário conectado leia e grave qualquer arquivo em seu bucket de armazenamento.

rules_version = '2';

service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write: if request.auth != null;
    }
  }
}

Você atualizará as regras para fazer o seguinte:

  • Permitir que cada usuário grave apenas em suas próprias pastas específicas
  • Permitir que qualquer pessoa leia no Cloud Storage
  • Certifique-se de que os arquivos enviados sejam imagens
  • Restrinja o tamanho das imagens que podem ser enviadas para no máximo 5 MB

Isso pode ser implementado usando as seguintes regras:

regras de armazenamento

rules_version = '2';

// Returns true if the uploaded file is an image and its size is below the given number of MB.
function isImageBelowMaxSize(maxSizeMB) {
  return request.resource.size < maxSizeMB * 1024 * 1024
      && request.resource.contentType.matches('image/.*');
}

service firebase.storage {
  match /b/{bucket}/o {
    match /{userId}/{messageId}/{fileName} {
      allow write: if request.auth != null && request.auth.uid == userId && isImageBelowMaxSize(5);
      allow read;
    }
  }
}

14. Implante seu aplicativo usando Firebase Hosting

O Firebase oferece um serviço de hospedagem para servir seus ativos e aplicativos da web. Você pode implantar seus arquivos no Firebase Hosting usando a CLI do Firebase. Antes de implantar, você precisa especificar no arquivo firebase.json quais arquivos locais devem ser implantados. Neste codelab, você já fez isso porque essa etapa foi necessária para veicular nossos arquivos durante o codelab. As configurações de hospedagem são especificadas no atributo hosting :

firebase.json

{
  // If you went through the "Cloud Firestore Security Rules" step.
  "firestore": {
    "rules": "firestore.rules"
  },
  // If you went through the "Storage Security Rules" step.
  "storage": {
    "rules": "storage.rules"
  },
  "hosting": {
    "public": "./public"
  }
}

Essas configurações informam à CLI que você deseja implementar todos os arquivos no diretório ./public ( "public": "./public" ).

  1. Certifique-se de que sua linha de comando esteja acessando o diretório angularfire-start local do seu aplicativo.
  2. Implante seus arquivos em seu projeto do Firebase executando o seguinte comando:
ng deploy

Em seguida, selecione a opção Firebase e siga as instruções na linha de comando.

  1. O console deve exibir o seguinte:
=== Deploying to 'friendlychat-1234'...

i  deploying firestore, storage, hosting
i  storage: checking storage.rules for compilation errors...
✔  storage: rules file storage.rules compiled successfully
i  firestore: checking firestore.rules for compilation errors...
✔  firestore: rules file firestore.rules compiled successfully
i  storage: uploading rules storage.rules...
i  firestore: uploading rules firestore.rules...
i  hosting[friendlychat-1234]: beginning deploy...
i  hosting[friendlychat-1234]: found 8 files in ./public
✔  hosting[friendlychat-1234]: file upload complete
✔  storage: released rules storage.rules to firebase.storage/friendlychat-1234.appspot.com
✔  firestore: released rules firestore.rules to cloud.firestore
i  hosting[friendlychat-1234]: finalizing version...
✔  hosting[friendlychat-1234]: version finalized
i  hosting[friendlychat-1234]: releasing new version...
✔  hosting[friendlychat-1234]: release complete

✔  Deploy complete!

Project Console: https://console.firebase.google.com/project/friendlychat-1234/overview
Hosting URL: https://friendlychat-1234.firebaseapp.com
  1. Visite seu aplicativo da Web que agora está totalmente hospedado em uma CDN global usando o Firebase Hosting em dois de seus próprios subdomínios do Firebase:
  • https://<firebase-projectId>.firebaseapp.com
  • https://<firebase-projectId>.web.app

Como alternativa, você pode executar firebase open hosting:site na linha de comando.

Acesse a documentação para saber mais sobre como funciona o Firebase Hosting .

Acesse a seção Hospedagem do Firebase console do seu projeto para ver informações e ferramentas úteis de hospedagem, incluindo o histórico de suas implantações, a funcionalidade para reverter para versões anteriores do seu aplicativo e o fluxo de trabalho para configurar um domínio personalizado.

15. Parabéns!

Você usou o Firebase para criar um aplicativo Web de bate-papo em tempo real.

O que você cobriu

  • Autenticação Firebase
  • Cloud Fire Store
  • SDK do Firebase para armazenamento em nuvem
  • Mensagens na nuvem do Firebase
  • Monitoramento de desempenho do Firebase
  • Hospedagem Firebase

Próximos passos

Saber mais

16. [Opcional] Aplicar com App Check

O Firebase App Check ajuda a proteger seus serviços contra tráfego indesejado e ajuda a proteger seu back-end contra abusos. Nesta etapa, você adicionará validação de credenciais e bloqueará clientes não autorizados com App Check e reCAPTCHA Enterprise .

Primeiro, você precisará ativar o App Check e o reCaptcha.

Habilitando o reCaptcha Enterprise

  1. No console do Cloud, encontre e selecione reCaptcha Enterprise em Segurança.
  2. Habilite o serviço conforme solicitado e clique em Criar chave .
  3. Insira um nome de exibição conforme solicitado e selecione Site como seu tipo de plataforma.
  4. Adicione seus URLs implantados à lista de domínios e certifique-se de que a opção "Usar desafio de caixa de seleção" esteja desmarcada .
  5. Clique em Criar chave e armazene a chave gerada em algum lugar por segurança. Você precisará dele posteriormente nesta etapa.

Ativando a verificação de aplicativos

  1. No console do Firebase, localize a seção Build no painel esquerdo.
  2. Clique em App Check e, em seguida, clique na guia Método de login para navegar até App Check .
  3. Clique em Registrar e insira sua chave reCaptcha Enterprise quando solicitado e clique em Salvar .
  4. Na visualização APIs, selecione Armazenamento e clique em Aplicar . Faça o mesmo para o Cloud Firestore .

O App Check agora deve ser aplicado! Atualize seu aplicativo e tente visualizar ou enviar mensagens de bate-papo. Você deve receber a mensagem de erro:

Uncaught Error in snapshot listener: FirebaseError: [code=permission-denied]: Missing or insufficient permissions.

Isso significa que o App Check está bloqueando solicitações não validadas por padrão. Agora vamos adicionar validação ao seu aplicativo.

Navegue até o arquivo Environment.ts e adicione reCAPTCHAEnterpriseKey ao objeto environment .

export const environment = {
  firebase: {
    apiKey: 'API_KEY',
    authDomain: 'PROJECT_ID.firebaseapp.com',
    databaseURL: 'https://PROJECT_ID.firebaseio.com',
    projectId: 'PROJECT_ID',
    storageBucket: 'PROJECT_ID.appspot.com',
    messagingSenderId: 'SENDER_ID',
    appId: 'APP_ID',
    measurementId: 'G-MEASUREMENT_ID',
  },
  reCAPTCHAEnterpriseKey: {
    key: "Replace with your recaptcha enterprise site key"
  },
};

Substitua o valor da key pelo seu token reCaptcha Enterprise.

Em seguida, navegue até o arquivo app.module.ts e adicione as seguintes importações:

import { getApp } from '@angular/fire/app';
import {
  ReCaptchaEnterpriseProvider,
  initializeAppCheck,
  provideAppCheck,
} from '@angular/fire/app-check';

No mesmo arquivo app.module.ts , adicione a seguinte declaração de variável global:

declare global {
  var FIREBASE_APPCHECK_DEBUG_TOKEN: boolean;
}

@NgModule({ ...

Nas importações, adicione a inicialização do App Check com ReCaptchaEnterpriseProvider e defina isTokenAutoRefreshEnabled como true para permitir a atualização automática dos tokens.

imports: [
BrowserModule,
AppRoutingModule,
CommonModule,
FormsModule,
provideFirebaseApp(() => initializeApp(environment.firebase)),
provideAppCheck(() => {
const appCheck = initializeAppCheck(getApp(), {
  provider: new ReCaptchaEnterpriseProvider(
  environment.reCAPTCHAEnterpriseKey.key
  ),
  isTokenAutoRefreshEnabled: true,
  });
  if (location.hostname === 'localhost') {
    self.FIREBASE_APPCHECK_DEBUG_TOKEN = true;
  }
  return appCheck;
}),

Para permitir testes locais, defina self.FIREBASE_APPCHECK_DEBUG_TOKEN como true . Quando você atualizar seu aplicativo em localhost , isso registrará um token de depuração no console semelhante a:

App Check debug token: CEFC0C76-7891-494B-B764-349BDFD00D00. You will need to add it to your app's App Check settings in the Firebase console for it to work.

Agora, vá para a visualização de aplicativos do App Check no console do Firebase.

Clique no menu flutuante e selecione Gerenciar tokens de depuração .

Em seguida, clique em Adicionar token de depuração e cole o token de depuração do seu console conforme solicitado.

Navegue até o arquivo chat.service.ts e adicione a seguinte importação:

import { AppCheck } from '@angular/fire/app-check';

No mesmo arquivo chat.service.ts](angularfire-start/src/app/services/chat.service.ts), injete o App Check junto com os outros serviços do Firebase.

export class ChatService {
appCheck: AppCheck = inject(AppCheck);
...

Parabéns! O App Check agora deve estar funcionando em seu aplicativo.