Laboratorio de código web AngularFire

1. Información general

En este codelab, aprenderá cómo usar AngularFire para crear aplicaciones web mediante la implementación e implementación de un cliente de chat utilizando productos y servicios de Firebase.

angularfire-2.png

lo que aprenderás

  • Cree una aplicación web usando Angular y Firebase.
  • Sincronice datos usando Cloud Firestore y Cloud Storage para Firebase.
  • Autentica a tus usuarios usando Firebase Authentication.
  • Implemente su aplicación web en Firebase Hosting.
  • Envía notificaciones con Firebase Cloud Messaging.
  • Recopile los datos de rendimiento de su aplicación web.

Lo que necesitarás

  • El IDE/editor de texto de su elección, como WebStorm , Atom , Sublime o VS Code
  • El administrador de paquetes npm , que normalmente viene con Node.js
  • Un terminal/consola
  • Un navegador de tu elección, como Chrome
  • El código de muestra del codelab (consulte el siguiente paso del codelab para saber cómo obtener el código).

2. Obtenga el código de muestra

Clona el repositorio GitHub del codelab desde la línea de comando:

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

Alternativamente, si no tienes git instalado, puedes descargar el repositorio como un archivo ZIP .

Importar la aplicación de inicio

Usando su IDE, abra o importe el directorio 📁 angularfire-start desde el repositorio clonado. Este directorio 📁 angularfire-start contiene el código inicial para codelab, que será una aplicación web de chat completamente funcional.

3. Crea y configura un proyecto de Firebase

Crear un proyecto de Firebase

  1. Inicia sesión en Firebase .
  2. En Firebase console, haz clic en Agregar proyecto y luego asigna a tu proyecto de Firebase el nombre FriendlyChat . Recuerde el ID del proyecto de su proyecto de Firebase.
  3. Desmarque Habilitar Google Analytics para este proyecto
  4. Haga clic en Crear proyecto .

La aplicación que vas a crear utiliza productos de Firebase que están disponibles para aplicaciones web:

  • Autenticación de Firebase para permitir que sus usuarios inicien sesión fácilmente en su aplicación.
  • Cloud Firestore para guardar datos estructurados en la nube y recibir notificaciones instantáneas cuando los datos cambian.
  • Cloud Storage para Firebase para guardar archivos en la nube.
  • Firebase Hosting para alojar y servir sus activos.
  • Firebase Cloud Messaging para enviar notificaciones automáticas y mostrar notificaciones emergentes del navegador.
  • Firebase Performance Monitoring para recopilar datos de rendimiento del usuario para su aplicación.

Algunos de estos productos necesitan una configuración especial o deben habilitarse mediante Firebase console.

Agregar una aplicación web de Firebase al proyecto

  1. Haga clic en el icono web 58d6543a156e56f9.png para crear una nueva aplicación web de Firebase.
  2. Registre la aplicación con el apodo Friendly Chat y luego marque la casilla junto a Configurar también Firebase Hosting para esta aplicación . Haga clic en Registrar aplicación .
  3. En el siguiente paso, verá un objeto de configuración. Copie solo el objeto JS (no el HTML circundante) en firebase-config.js

Registrar captura de pantalla de la aplicación web

Habilite el inicio de sesión de Google para la autenticación de Firebase

Para permitir que los usuarios inicien sesión en la aplicación web con sus cuentas de Google, utilizará el método de inicio de sesión de Google .

Deberá habilitar el inicio de sesión de Google :

  1. En la consola de Firebase, ubique la sección Construir en el panel izquierdo.
  2. Haga clic en Autenticación y luego haga clic en la pestaña Método de inicio de sesión (o haga clic aquí para ir directamente allí).
  3. Habilite el proveedor de inicio de sesión de Google y luego haga clic en Guardar .
  4. Establezca el nombre público de su aplicación en Friendly Chat y elija un correo electrónico de soporte del proyecto en el menú desplegable.
  5. Configure su pantalla de consentimiento de OAuth en Google Cloud Console y agregue un logotipo:

d89fb3873b5d36ae.png

Habilitar Cloud Firestore

La aplicación web utiliza Cloud Firestore para guardar mensajes de chat y recibir nuevos mensajes de chat.

Deberá habilitar Cloud Firestore:

  1. En la sección Generar de Firebase console, haz clic en Base de datos de Firestore .
  2. Haga clic en Crear base de datos en el panel de Cloud Firestore.

729991a081e7cd5.png

  1. Seleccione la opción Iniciar en modo de prueba y luego haga clic en Siguiente después de leer el descargo de responsabilidad sobre las reglas de seguridad.

El modo de prueba garantiza que pueda escribir libremente en la base de datos durante el desarrollo. Harás que nuestra base de datos sea más segura más adelante en este codelab.

77e4986cbeaf9dee.png

  1. Establezca la ubicación donde se almacenan sus datos de Cloud Firestore. Puede dejar esto como predeterminado o elegir una región cercana a usted. Haga clic en Listo para aprovisionar Firestore.

9f2bb0d4e7ca49c7.png

Habilitar almacenamiento en la nube

La aplicación web utiliza Cloud Storage para Firebase para almacenar, cargar y compartir imágenes.

Deberá habilitar el almacenamiento en la nube:

  1. En la sección Compilación de Firebase console, haz clic en Almacenamiento .
  2. Si no hay ningún botón Comenzar , significa que el almacenamiento en la nube ya está habilitado y no es necesario seguir los pasos a continuación.
  3. Haga clic en Comenzar .
  4. Lea el descargo de responsabilidad sobre las reglas de seguridad para su proyecto de Firebase y luego haga clic en Siguiente .

Con las reglas de seguridad predeterminadas, cualquier usuario autenticado puede escribir cualquier cosa en Cloud Storage. Harás que nuestro almacenamiento sea más seguro más adelante en este codelab.

62f1afdcd1260127.png

  1. La ubicación de Cloud Storage está preseleccionada con la misma región que eligió para su base de datos de Cloud Firestore. Haga clic en Listo para completar la configuración.

1d7f49ebaddb32fc.png

4. Instale la interfaz de línea de comandos de Firebase

La interfaz de línea de comandos (CLI) de Firebase le permite usar Firebase Hosting para servir su aplicación web localmente, así como para implementar su aplicación web en su proyecto de Firebase.

  1. Instale la CLI ejecutando el siguiente comando npm:
npm -g install firebase-tools
  1. Verifique que la CLI se haya instalado correctamente ejecutando el siguiente comando:
firebase --version

Asegúrese de que la versión de Firebase CLI sea v4.1.0 o posterior.

  1. Autorice Firebase CLI ejecutando el siguiente comando:
firebase login

Configuraste la plantilla de la aplicación web para extraer la configuración de tu aplicación para Firebase Hosting desde el directorio local de tu aplicación (el repositorio que clonaste anteriormente en el codelab). Pero para realizar la configuración, debes asociar tu aplicación con tu proyecto de Firebase.

  1. Asegúrese de que su línea de comando acceda al directorio local angularfire-start de su aplicación.
  2. Asocie su aplicación con su proyecto de Firebase ejecutando el siguiente comando:
firebase use --add
  1. Cuando se le solicite, seleccione su ID de proyecto y luego asigne un alias a su proyecto de Firebase.

Un alias es útil si tiene múltiples entornos (producción, puesta en escena, etc.). Sin embargo, para este codelab, usemos simplemente el alias default .

  1. Siga las instrucciones restantes en su línea de comando.

5. Instale AngularFire

Antes de ejecutar el proyecto, asegúrese de tener configurado Angular CLI y AngularFire.

  1. En una consola, ejecute el siguiente comando:
npm install -g @angular/cli
  1. Luego, en una consola desde el directorio angularfire-start , ejecute el siguiente comando Angular CLI:
ng add @angular/fire

Esto instalará todas las dependencias necesarias para su proyecto.

  1. Cuando se le solicite, seleccione las funciones que se configuraron en Firebase Console ( ng deploy -- hosting , Authentication , Firestore , Cloud Functions (callable) , Cloud Messaging , Cloud Storage ) y siga las indicaciones en la consola.

6. Ejecute la aplicación de inicio localmente

Ahora que ha importado y configurado su proyecto, está listo para ejecutar la aplicación web por primera vez.

  1. En una consola desde el directorio angularfire-start , ejecute el siguiente comando de Firebase CLI:
firebase emulators:start
  1. Su línea de comando debería mostrar la siguiente respuesta:
✔  hosting: Local server: http://localhost:5000

Estás utilizando el emulador de Firebase Hosting para ofrecer nuestra aplicación localmente. La aplicación web ahora debería estar disponible en http://localhost:5000 . Se sirven todos los archivos que se encuentran en el subdirectorio src .

  1. Usando su navegador, abra su aplicación en http://localhost:5000 .

Deberías ver la interfaz de usuario de tu aplicación FriendlyChat, que (¡todavía!) no funciona:

angularfire-2.png

La aplicación no puede hacer nada en este momento, pero con tu ayuda, ¡pronto lo hará! Hasta ahora solo has presentado la interfaz de usuario.

¡Creemos ahora un chat en tiempo real!

7. Importar y configurar Firebase

Configurar base de fuego

Deberá configurar el SDK de Firebase para indicarle qué proyecto de Firebase está utilizando.

  1. Vaya a la configuración de su proyecto en Firebase console
  2. En la tarjeta "Tus aplicaciones", selecciona el apodo de la aplicación para la que necesitas un objeto de configuración.
  3. Seleccione "Configuración" en el panel de fragmentos del SDK de Firebase.

Verá que se generó un archivo de entorno /angularfire-start/src/environments/environment.ts .

  1. Copie el fragmento del objeto de configuración y luego agréguelo a angularfire-start/src/firebase-config.js .

environment.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

Descubrirá que las funciones que seleccionó en la consola se enrutaron automáticamente en el archivo /angularfire-start/src/app/app.module.ts . Esto permite que su aplicación utilice características y funcionalidades de Firebase. Sin embargo, para desarrollar en un entorno local, es necesario conectarlos para utilizar el conjunto de emuladores.

  1. En /angularfire-start/src/app/app.module.ts , busque la sección imports y modifique las funciones proporcionadas para conectarse al conjunto de emuladores en entornos que no son de producción.
// ...

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, utilizará Firebase Authentication, Cloud Firestore, Cloud Storage, Cloud Messaging y Performance Monitoring, por lo que importará todas sus bibliotecas. En tus aplicaciones futuras, asegúrate de importar solo las partes de Firebase que necesitas para acortar el tiempo de carga de tu aplicación.

8. Configurar el inicio de sesión de usuario

AngularFire ahora debería estar listo para usar ya que se importó e inicializó en app.module.ts . Ahora implementará el inicio de sesión de usuario mediante Firebase Authentication .

Autentica a tus usuarios con el inicio de sesión de Google

En la aplicación, cuando un usuario hace clic en el botón Iniciar sesión con Google , se activa la función login . (¡Ya lo configuró por usted!) Para este codelab, desea autorizar a Firebase a usar Google como proveedor de identidad. Utilizarás una ventana emergente, pero hay varios otros métodos disponibles en Firebase.

  1. En el directorio angularfire-start , en el subdirectorio /src/app/services/ , abra chat.service.ts .
  2. Busque la función login .
  3. Reemplace toda la función con el siguiente código.

chat.service.ts

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

La función logout se activa cuando el usuario hace clic en el botón Cerrar sesión .

  1. Vuelva al archivo src/app/services/chat.service.ts .
  2. Busque la función logout .
  3. Reemplace toda la función con el siguiente código.

chat.service.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);
    })
}

Seguimiento del estado de autenticación

Para actualizar nuestra interfaz de usuario en consecuencia, necesita una forma de verificar si el usuario inició o cerró sesión. Con Firebase Authentication, puede recuperar datos observables del estado del usuario que se activarán cada vez que cambie el estado de autenticación.

  1. Vuelva al archivo src/app/services/chat.service.ts .
  2. Encuentre la asignación de variables user$ .
  3. Reemplace toda la tarea con el siguiente código.

chat.service.ts

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

El código anterior llama al user de la función AngularFire que devuelve un usuario observable. Se activará cada vez que cambie el estado de autenticación (cuando el usuario inicia o cierra sesión). Es en este punto que actualizará la interfaz de usuario para redirigir, mostrar al usuario en el encabezado de navegación, etc. Todas estas partes de la interfaz de usuario ya se han implementado.

Prueba de iniciar sesión en la aplicación

  1. Si su aplicación aún se está publicando, actualícela en el navegador. De lo contrario, ejecute firebase emulators:start en la línea de comando para comenzar a ofrecer la aplicación desde http://localhost:5000 y luego ábrala en su navegador.
  2. Inicie sesión en la aplicación utilizando el botón de inicio de sesión y su cuenta de Google. Si ve un mensaje de error que indica auth/operation-not-allowed , verifique que haya habilitado el inicio de sesión de Google como proveedor de autenticación en Firebase console.
  3. Después de iniciar sesión, deberían aparecer su foto de perfil y su nombre de usuario: fuego angular-3.png

9. Escribe mensajes en Cloud Firestore

En esta sección, escribirá algunos datos en Cloud Firestore para poder completar la interfaz de usuario de la aplicación. Esto se puede hacer manualmente con Firebase console , pero lo harás en la propia aplicación para demostrar una escritura básica en Cloud Firestore.

Modelo de datos

Los datos de Cloud Firestore se dividen en colecciones, documentos, campos y subcolecciones. Almacenarás cada mensaje del chat como un documento en una colección de nivel superior llamada messages .

688d7bc5fb662b57.png

Agregar mensajes a Cloud Firestore

Para almacenar los mensajes de chat escritos por los usuarios, utilizará Cloud Firestore .

En esta sección, agregará la funcionalidad para que los usuarios escriban nuevos mensajes en su base de datos. Un usuario que haga clic en el botón ENVIAR activará el siguiente fragmento de código. Agrega un objeto de mensaje con el contenido de los campos de mensaje a su instancia de Cloud Firestore en la colección messages . El método add() agrega un nuevo documento con una identificación generada automáticamente a la colección.

  1. Vuelva al archivo src/app/services/chat.service.ts .
  2. Busque la función addMessage .
  3. Reemplace toda la función con el siguiente código.

chat.service.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;
    }
}

Prueba de envío de mensajes

  1. Si su aplicación aún se está publicando, actualícela en el navegador. De lo contrario, ejecute firebase emulators:start en la línea de comando para comenzar a ofrecer la aplicación desde http://localhost:5000 y luego ábrala en su navegador.
  2. Después de iniciar sesión, ingrese un mensaje como "¡Hola!" y luego haga clic en ENVIAR . Esto escribirá el mensaje en Cloud Firestore. Sin embargo, aún no verá los datos en su aplicación web real porque aún necesita implementar la recuperación de datos (la siguiente sección del codelab).
  3. Puede ver el mensaje recién agregado en su Firebase Console. Abra la interfaz de usuario de su suite Emulator. En la sección Crear , haga clic en Base de datos de Firestore (o haga clic aquí y debería ver la colección de mensajes con su mensaje recién agregado:

6812efe7da395692.png

10. Leer mensajes

Sincronizar mensajes

Para leer mensajes en la aplicación, deberá agregar un observable que se activará cuando cambien los datos y luego crear un elemento de interfaz de usuario que muestre mensajes nuevos.

Agregará código que escuche los mensajes recién agregados desde la aplicación. En este código, recuperará la instantánea de la colección messages . Solo mostrarás los últimos 12 mensajes del chat para evitar mostrar un historial muy largo al cargar.

  1. Vuelva al archivo src/app/services/chat.service.ts .
  2. Encuentra la función loadMessages .
  3. Reemplace toda la función con el siguiente código.

chat.service.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 escuchar mensajes en la base de datos, crea una consulta en una colección utilizando la función collection para especificar en qué colección se encuentran los datos que desea escuchar. En el código anterior, está escuchando los cambios dentro de los messages colección, que es donde se almacenan los mensajes del chat. También está aplicando un límite escuchando solo los últimos 12 mensajes usando limit(12) y ordenando los mensajes por fecha usando orderBy('timestamp', 'desc') para obtener los 12 mensajes más nuevos.

La función collectionData utiliza instantáneas bajo el capó. La función de devolución de llamada se activará cuando haya cambios en los documentos que coincidan con la consulta. Esto podría ocurrir si un mensaje se elimina, modifica o agrega. Puede leer más sobre esto en la documentación de Cloud Firestore .

Probar la sincronización de mensajes

  1. Si su aplicación aún se está publicando, actualícela en el navegador. De lo contrario, ejecute firebase emulators:start en la línea de comando para comenzar a ofrecer la aplicación desde http://localhost:5000 y luego ábrala en su navegador.
  2. Los mensajes que creó anteriormente en la base de datos deben mostrarse en la interfaz de usuario de FriendlyChat (ver más abajo). Siéntete libre de escribir nuevos mensajes; deberían aparecer instantáneamente.
  3. (Opcional) Puede intentar eliminar, modificar o agregar mensajes nuevos manualmente directamente en la sección Firestore del paquete Emulator; cualquier cambio debe reflejarse en la interfaz de usuario.

¡Felicidades! ¡Estás leyendo documentos de Cloud Firestore en tu aplicación!

angularfire-2.png

11. Enviar imágenes

Ahora agregará una función que comparte imágenes.

Si bien Cloud Firestore es bueno para almacenar datos estructurados, Cloud Storage es más adecuado para almacenar archivos. Cloud Storage para Firebase es un servicio de almacenamiento de archivos/blobs y lo usará para almacenar cualquier imagen que un usuario comparta usando nuestra aplicación.

Guardar imágenes en el almacenamiento en la nube

Para este codelab, ya agregó un botón que activa un cuadro de diálogo de selección de archivos. Después de seleccionar un archivo, se llama a la función saveImageMessage y puede obtener una referencia al archivo seleccionado. La función saveImageMessage logra lo siguiente:

  1. Crea un mensaje de chat "marcador de posición" en el feed del chat, para que los usuarios vean una animación de "Cargando" mientras subes la imagen.
  2. Carga el archivo de imagen en Cloud Storage a esta ruta: /<uid>/<file_name>
  3. Genera una URL legible públicamente para el archivo de imagen.
  4. Actualiza el mensaje de chat con la URL del archivo de imagen recién cargado en lugar de la imagen de carga temporal.

Ahora agregará la funcionalidad para enviar una imagen:

  1. Regrese al archivo src/index.js .
  2. Encuentra la función saveImageMessage .
  3. Reemplace toda la función con el siguiente código.

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);
  }
}

Prueba de envío de imágenes

  1. Si su aplicación aún se está publicando, actualícela en el navegador. De lo contrario, ejecute firebase emulators:start en la línea de comando para comenzar a ofrecer la aplicación desde http://localhost:5000 y luego ábrala en su navegador.
  2. Después de iniciar sesión, haga clic en el botón de carga de imágenes en la parte inferior izquierda angularfire-4.png y seleccione un archivo de imagen usando el selector de archivos. Si estás buscando una imagen, no dudes en utilizar esta bonita imagen de una taza de café .
  3. Debería aparecer un nuevo mensaje en la interfaz de usuario de la aplicación con la imagen seleccionada: angularfire-2.png

Si intenta agregar una imagen sin haber iniciado sesión, debería ver un error que le indica que debe iniciar sesión para agregar imágenes.

12. Mostrar notificaciones

Ahora agregará soporte para notificaciones del navegador. La aplicación notificará a los usuarios cuando se publiquen nuevos mensajes en el chat. Firebase Cloud Messaging (FCM) es una solución de mensajería multiplataforma que le permite enviar mensajes y notificaciones de manera confiable y sin costo.

Agregar el trabajador del servicio FCM

La aplicación web necesita un trabajador de servicio que reciba y muestre notificaciones web.

El proveedor de mensajería ya debería haberse configurado cuando se agregó AngularFire, asegúrese de que exista el siguiente código en la sección de importaciones de /angularfire-start/src/app/app.module.ts

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

app/app.module.ts

El trabajador del servicio simplemente necesita cargar e inicializar el SDK de Firebase Cloud Messaging, que se encargará de mostrar las notificaciones.

Obtenga tokens de dispositivo FCM

Cuando las notificaciones se hayan habilitado en un dispositivo o navegador, se le entregará un token de dispositivo . Este token de dispositivo es lo que se utiliza para enviar una notificación a un dispositivo o navegador en particular.

Cuando el usuario inicia sesión, llama a la función saveMessagingDeviceToken . Ahí es donde obtendrá el token del dispositivo FCM del navegador y lo guardará en Cloud Firestore.

chat.service.ts

  1. Busque la función saveMessagingDeviceToken .
  2. Reemplace toda la función con el siguiente código.

chat.service.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);
    };
}

Sin embargo, este código no funcionará inicialmente. Para que su aplicación pueda recuperar el token del dispositivo, el usuario debe otorgarle permiso a su aplicación para mostrar notificaciones (el siguiente paso del codelab).

Solicitar permisos para mostrar notificaciones

Cuando el usuario aún no le haya otorgado permiso a su aplicación para mostrar notificaciones, no recibirá un token de dispositivo. En este caso, llama al método requestPermission() , que mostrará un cuadro de diálogo del navegador solicitando este permiso ( en navegadores compatibles ).

8b9d0c66dc36153d.png

  1. Vuelva al archivo src/app/services/chat.service.ts .
  2. Busque la función requestNotificationsPermissions .
  3. Reemplace toda la función con el siguiente código.

chat.service.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.');
    }
}

Obtenga el token de su dispositivo

  1. Si su aplicación aún se está publicando, actualícela en el navegador. De lo contrario, ejecute firebase emulators:start en la línea de comando para comenzar a ofrecer la aplicación desde http://localhost:5000 y luego ábrala en su navegador.
  2. Después de iniciar sesión, debería aparecer el cuadro de diálogo de permiso de notificaciones: bd3454e6dbfb6723.png
  3. Haga clic en Permitir.
  4. Abra la consola JavaScript de su navegador. Debería ver el siguiente mensaje: Got FCM device token: cWL6w:APA91bHP...4jDPL_A-wPP06GJp1OuekTaTZI5K2Tu
  5. Copie el token de su dispositivo. Lo necesitarás para la siguiente etapa del codelab.

Envía una notificación a tu dispositivo

Ahora que tienes el token de tu dispositivo, puedes enviar una notificación.

  1. Abra la pestaña Mensajería en la nube de Firebase console .
  2. Haga clic en "Nueva notificación"
  3. Ingrese un título de notificación y un texto de notificación.
  4. En el lado derecho de la pantalla, haga clic en "enviar un mensaje de prueba"
  5. Ingrese el token del dispositivo que copió desde la consola JavaScript de su navegador, luego haga clic en el signo más ("+")
  6. Haga clic en "probar"

Si su aplicación está en primer plano, verá la notificación en la consola de JavaScript.

Si su aplicación está en segundo plano, debería aparecer una notificación en su navegador, como en este ejemplo:

de79e8638a45864c.png

13. Reglas de seguridad de Cloud Firestore

Ver reglas de seguridad de la base de datos

Cloud Firestore utiliza un lenguaje de reglas específico para definir los derechos de acceso, la seguridad y las validaciones de datos.

Al configurar el proyecto de Firebase al comienzo de este codelab, elegiste usar las reglas de seguridad predeterminadas del "modo de prueba" para no restringir el acceso al almacén de datos. En Firebase console , en la pestaña Reglas de la sección Base de datos , puedes ver y modificar estas reglas.

En este momento, debería ver las reglas predeterminadas, que no restringen el acceso al almacén de datos. Esto significa que cualquier usuario puede leer y escribir en cualquier colección de su almacén de datos.

rules_version = '2';

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

Actualizará las reglas para restringir cosas mediante el uso de las siguientes reglas:

reglas.firestore

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;
    }
  }
}

Las reglas de seguridad deberían actualizarse automáticamente en su suite de emuladores.

Ver reglas de seguridad de Cloud Storage

Cloud Storage para Firebase utiliza un lenguaje de reglas específico para definir los derechos de acceso, la seguridad y las validaciones de datos.

Al configurar el proyecto de Firebase al comienzo de este codelab, elegiste usar la regla de seguridad predeterminada de Cloud Storage que solo permite a los usuarios autenticados usar Cloud Storage. En Firebase console , en la pestaña Reglas de la sección Almacenamiento , puedes ver y modificar reglas. Debería ver la regla predeterminada que permite a cualquier usuario que haya iniciado sesión leer y escribir cualquier archivo en su depósito de almacenamiento.

rules_version = '2';

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

Actualizará las reglas para hacer lo siguiente:

  • Permitir que cada usuario escriba solo en sus propias carpetas específicas
  • Permitir que cualquiera pueda leer desde Cloud Storage
  • Asegúrate de que los archivos subidos sean imágenes.
  • Restringir el tamaño de las imágenes que se pueden subir a un máximo de 5 MB

Esto se puede implementar usando las siguientes reglas:

reglas.de.almacenamiento

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. Implementa tu aplicación usando Firebase Hosting

Firebase ofrece un servicio de alojamiento para sus activos y aplicaciones web. Puedes implementar tus archivos en Firebase Hosting usando Firebase CLI. Antes de implementar, debe especificar en su archivo firebase.json qué archivos locales deben implementarse. Para este codelab, ya lo hizo porque este paso era necesario para entregar nuestros archivos durante este codelab. La configuración de alojamiento se especifica en el atributo hosting :

base de fuego.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"
  }
}

Estas configuraciones le indican a la CLI que desea implementar todos los archivos en el directorio ./public ( "public": "./public" ).

  1. Asegúrese de que su línea de comando acceda al directorio local angularfire-start de su aplicación.
  2. Implemente sus archivos en su proyecto de Firebase ejecutando el siguiente comando:
ng deploy

Luego seleccione la opción Firebase y siga las indicaciones en la línea de comando.

  1. La consola debería mostrar lo siguiente:
=== 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 su aplicación web que ahora está completamente alojada en una CDN global usando Firebase Hosting en dos de sus propios subdominios de Firebase:
  • https://<firebase-projectId>.firebaseapp.com
  • https://<firebase-projectId>.web.app

Alternativamente, puede ejecutar firebase open hosting:site en la línea de comando.

Visita la documentación para obtener más información sobre cómo funciona Firebase Hosting .

Vaya a la sección Alojamiento de la consola Firebase de su proyecto para ver información y herramientas de alojamiento útiles, incluido el historial de sus implementaciones, la funcionalidad para volver a versiones anteriores de su aplicación y el flujo de trabajo para configurar un dominio personalizado.

15. ¡Felicitaciones!

¡Has utilizado Firebase para crear una aplicación web de chat en tiempo real!

Lo que has cubierto

  • Autenticación de base de fuego
  • Tienda de fuego en la nube
  • SDK de Firebase para almacenamiento en la nube
  • Mensajería en la nube de Firebase
  • Monitoreo del rendimiento de Firebase
  • Alojamiento base de fuego

Próximos pasos

Aprende más

16. [Opcional] Aplicar con App Check

Firebase App Check ayuda a proteger sus servicios del tráfico no deseado y ayuda a proteger su backend contra abusos. En este paso, agregará validación de credenciales y bloqueará clientes no autorizados con App Check y reCAPTCHA Enterprise .

Primero, deberá habilitar App Check y reCaptcha.

Habilitando reCaptcha Enterprise

  1. En la consola de la nube, busque y seleccione reCaptcha Enterprise en Seguridad.
  2. Habilite el servicio cuando se le solicite y haga clic en Crear clave .
  3. Ingrese un nombre para mostrar cuando se le solicite y seleccione Sitio web como su tipo de plataforma.
  4. Agregue sus URL implementadas a la lista de dominios y asegúrese de que la opción "Usar desafío de casilla de verificación" no esté seleccionada.
  5. Haga clic en Crear clave y guarde la clave generada en algún lugar para su custodia. Lo necesitará más adelante en este paso.

Habilitar la verificación de aplicaciones

  1. En la consola de Firebase, ubique la sección Construir en el panel izquierdo.
  2. Haga clic en App Check y luego haga clic en la pestaña Método de inicio de sesión para navegar hasta App Check .
  3. Haga clic en Registrarse e ingrese su clave reCaptcha Enterprise cuando se le solicite, luego haga clic en Guardar .
  4. En la Vista de API, seleccione Almacenamiento y haga clic en Aplicar . Haga lo mismo con Cloud Firestore .

¡La verificación de aplicaciones ahora debería aplicarse! Actualiza tu aplicación e intenta ver o enviar mensajes de chat. Debería recibir el mensaje de error:

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

Esto significa que App Check bloquea las solicitudes no validadas de forma predeterminada. Ahora agreguemos validación a su aplicación.

Navegue hasta su archivo environment.ts y agregue reCAPTCHAEnterpriseKey al 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"
  },
};

Reemplace el valor de key con su token reCaptcha Enterprise.

Luego, navegue hasta el archivo app.module.ts y agregue las siguientes importaciones:

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

En el mismo archivo app.module.ts , agregue la siguiente declaración de variable global:

declare global {
  var FIREBASE_APPCHECK_DEBUG_TOKEN: boolean;
}

@NgModule({ ...

En las importaciones, agregue la inicialización de App Check con ReCaptchaEnterpriseProvider y establezca isTokenAutoRefreshEnabled en true para permitir que los tokens se actualicen automáticamente.

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 pruebas locales, establezca self.FIREBASE_APPCHECK_DEBUG_TOKEN en true . Cuando actualiza su aplicación en localhost , esto registrará un token de depuración en la consola similar 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.

Ahora, vaya a la Vista de aplicaciones de App Check en Firebase console.

Haga clic en el menú adicional y seleccione Administrar tokens de depuración .

Luego, haga clic en Agregar token de depuración y pegue el token de depuración desde su consola cuando se le solicite.

Navegue hasta el archivo chat.service.ts y agregue la siguiente importación:

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

En el mismo archivo chat.service.ts , inyecte App Check junto con los otros servicios de Firebase.

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

¡Felicidades! App Check ahora debería estar funcionando en su aplicación.