Лаборатория веб-кода AngularFire

1. Обзор

В этой лабораторной работе вы узнаете, как использовать AngularFire для создания веб-приложений путем реализации и развертывания клиента чата с использованием продуктов и сервисов Firebase.

angularfire-2.png

Что вы узнаете

  • Создайте веб-приложение, используя Angular и Firebase.
  • Синхронизируйте данные с помощью Cloud Firestore и Cloud Storage for Firebase.
  • Аутентифицируйте своих пользователей с помощью Firebase Authentication.
  • Разверните свое веб-приложение на хостинге Firebase.
  • Отправляйте уведомления с помощью Firebase Cloud Messaging.
  • Соберите данные о производительности вашего веб-приложения.

Что вам понадобится

  • IDE/текстовый редактор по вашему выбору, например WebStorm , Atom , Sublime или VS Code.
  • Менеджер пакетов npm , который обычно поставляется с Node.js.
  • Терминал/консоль
  • Браузер по вашему выбору, например Chrome.
  • Пример кода лаборатории кода (см. следующий шаг лаборатории кода, чтобы узнать, как получить код).

2. Получите пример кода

Клонируйте репозиторий GitHub codelab из командной строки:

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

Альтернативно, если у вас не установлен git, вы можете загрузить репозиторий в виде ZIP-файла .

Импортируйте начальное приложение

Используя свою IDE, откройте или импортируйте каталог angularfire-start из клонированного репозитория. Этот каталог angularfire-start содержит стартовый код для codelab, который будет полнофункциональным веб-приложением для чата.

3. Создайте и настройте проект Firebase.

Создать проект Firebase

  1. Войдите в Firebase .
  2. В консоли Firebase нажмите «Добавить проект» и назовите свой проект Firebase FriendlyChat . Запомните идентификатор вашего проекта Firebase.
  3. Снимите флажок Включить Google Analytics для этого проекта.
  4. Нажмите Создать проект .

Приложение, которое вы собираетесь создать, использует продукты Firebase, доступные для веб-приложений:

  • Аутентификация Firebase , позволяющая пользователям легко входить в ваше приложение.
  • Cloud Firestore для сохранения структурированных данных в облаке и мгновенного получения уведомлений при изменении данных.
  • Облачное хранилище для Firebase для сохранения файлов в облаке.
  • Хостинг Firebase для размещения и обслуживания ваших ресурсов.
  • Firebase Cloud Messaging для отправки push-уведомлений и отображения всплывающих уведомлений браузера.
  • Мониторинг производительности Firebase для сбора данных о производительности пользователей вашего приложения.

Некоторые из этих продуктов требуют специальной настройки или их необходимо включить с помощью консоли Firebase.

Добавьте веб-приложение Firebase в проект

  1. Нажмите значок Интернета 58d6543a156e56f9.png чтобы создать новое веб-приложение Firebase.
  2. Зарегистрируйте приложение под псевдонимом Friendly Chat , затем установите флажок «Также настройте хостинг Firebase для этого приложения ». Нажмите Зарегистрировать приложение .
  3. На следующем шаге вы увидите объект конфигурации. Скопируйте только объект JS (а не окружающий его HTML) в firebase-config.js.

Скриншот зарегистрированного веб-приложения

Включите вход в Google для аутентификации Firebase

Чтобы пользователи могли входить в веб-приложение со своими учетными записями Google, вы будете использовать метод входа Google .

Вам необходимо включить вход в Google :

  1. В консоли Firebase найдите раздел «Сборка» на левой панели.
  2. Нажмите «Аутентификация » , затем перейдите на вкладку «Метод входа » (или нажмите здесь , чтобы перейти непосредственно туда).
  3. Включите службу входа в систему Google , затем нажмите «Сохранить» .
  4. Установите общедоступное имя вашего приложения «Дружественный чат» и выберите адрес электронной почты службы поддержки проекта из раскрывающегося меню.
  5. Настройте экран согласия OAuth в Google Cloud Console и добавьте логотип:

d89fb3873b5d36ae.png

Включить Cloud Firestore

Веб-приложение использует Cloud Firestore для сохранения сообщений чата и получения новых сообщений чата.

Вам нужно включить Cloud Firestore:

  1. В разделе «Сборка» консоли Firebase нажмите «База данных Firestore» .
  2. Нажмите Создать базу данных на панели Cloud Firestore.

729991a081e7cd5.png

  1. Выберите параметр «Начать в тестовом режиме» , затем нажмите «Далее» , прочитав заявление об отказе от ответственности в отношении правил безопасности.

Тестовый режим гарантирует, что вы можете свободно писать в базу данных во время разработки. Позже в этой лаборатории вы повысите безопасность нашей базы данных.

77e4986cbeaf9dee.png

  1. Укажите место, где хранятся данные Cloud Firestore. Вы можете оставить это значение по умолчанию или выбрать ближайший к вам регион. Нажмите «Готово» , чтобы подготовить Firestore.

9f2bb0d4e7ca49c7.png

Включить облачное хранилище

Веб-приложение использует Cloud Storage for Firebase для хранения, загрузки и обмена изображениями.

Вам необходимо включить облачное хранилище:

  1. В разделе «Сборка» консоли Firebase нажмите «Хранилище» .
  2. Если кнопки «Начать» нет, это означает, что облачное хранилище уже включено, и вам не нужно выполнять описанные ниже действия.
  3. Нажмите «Начать» .
  4. Прочтите заявление об отказе от ответственности о правилах безопасности для вашего проекта Firebase, затем нажмите «Далее» .

Благодаря правилам безопасности по умолчанию любой прошедший проверку подлинности пользователь может записывать в Cloud Storage что угодно. Позже в этой лаборатории вы сделаете наше хранилище более безопасным.

62f1afdcd1260127.png

  1. Местоположение Cloud Storage предварительно выбирается в том же регионе, который вы выбрали для своей базы данных Cloud Firestore. Нажмите Готово , чтобы завершить настройку.

1d7f49ebaddb32fc.png

4. Установите интерфейс командной строки Firebase.

Интерфейс командной строки (CLI) Firebase позволяет вам использовать хостинг Firebase для локального обслуживания вашего веб-приложения, а также для развертывания вашего веб-приложения в проекте Firebase.

  1. Установите CLI, выполнив следующую команду npm:
npm -g install firebase-tools
  1. Убедитесь, что CLI установлен правильно, выполнив следующую команду:
firebase --version

Убедитесь, что версия Firebase CLI — v4.1.0 или новее.

  1. Авторизуйте Firebase CLI, выполнив следующую команду:
firebase login

Вы настроили шаблон веб-приложения для извлечения конфигурации вашего приложения для хостинга Firebase из локального каталога вашего приложения (репозитория, который вы клонировали ранее в лаборатории кода). Но чтобы получить конфигурацию, вам необходимо связать свое приложение с проектом Firebase.

  1. Убедитесь, что ваша командная строка обращается к локальному каталогу angularfire-start вашего приложения.
  2. Свяжите свое приложение с проектом Firebase, выполнив следующую команду:
firebase use --add
  1. При появлении запроса выберите идентификатор проекта и присвойте проекту Firebase псевдоним.

Псевдоним полезен, если у вас несколько сред (производственная, промежуточная и т. д.). Однако для этой кодовой лаборатории давайте просто воспользуемся псевдонимом default .

  1. Следуйте остальным инструкциям в командной строке.

5. Установите AngularFire

Прежде чем запускать проект, убедитесь, что у вас настроены Angular CLI и AngularFire.

  1. В консоли выполните следующую команду:
npm install -g @angular/cli
  1. Затем в консоли из каталога angularfire-start выполните следующую команду Angular CLI:
ng add @angular/fire

Это установит все необходимые зависимости для вашего проекта.

  1. При появлении запроса выберите функции, которые были настроены в консоли Firebase ( ng deploy -- hosting , Authentication , Firestore , Cloud Functions (callable) , Cloud Messaging , Cloud Storage ), и следуйте инструкциям на консоли.

6. Запустите стартовое приложение локально.

Теперь, когда вы импортировали и настроили свой проект, вы готовы впервые запустить веб-приложение.

  1. В консоли из каталога angularfire-start выполните следующую команду Firebase CLI:
firebase emulators:start
  1. В вашей командной строке должен появиться следующий ответ:
✔  hosting: Local server: http://localhost:5000

Вы используете эмулятор хостинга Firebase для локального обслуживания нашего приложения. Веб-приложение теперь должно быть доступно по адресу http://localhost:5000 . Обслуживаются все файлы, расположенные в подкаталоге src .

  1. Используя браузер, откройте свое приложение по адресу http://localhost:5000 .

Вы должны увидеть пользовательский интерфейс вашего приложения FriendlyChat, который (пока!) не работает:

angularfire-2.png

Приложение сейчас ничего не может сделать, но с вашей помощью это скоро произойдет! Пока что вы разработали только пользовательский интерфейс.

Давайте теперь создадим чат в реальном времени!

7. Импортируйте и настройте Firebase

Настроить Firebase

Вам нужно будет настроить Firebase SDK, чтобы указать, какой проект Firebase вы используете.

  1. Перейдите к настройкам проекта в консоли Firebase.
  2. В карточке «Ваши приложения» выберите никнейм приложения, для которого вам нужен объект конфигурации.
  3. Выберите «Конфигурация» на панели фрагментов Firebase SDK.

Вы обнаружите, что для вас был создан файл среды /angularfire-start/src/environments/environment.ts .

  1. Скопируйте фрагмент объекта конфигурации, а затем добавьте его в 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",
  },
};

Импортировать AngularFire

Вы обнаружите, что функции, выбранные вами в консоли, были автоматически перенаправлены в файл /angularfire-start/src/app/app.module.ts . Это позволит вашему приложению использовать функции и возможности Firebase. Однако для разработки в локальной среде вам необходимо подключить их для использования пакета эмулятора.

  1. В /angularfire-start/src/app/app.module.ts найдите раздел imports и измените предоставленные функции для подключения к пакету эмулятора в непроизводственных средах.
// ...

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

В ходе этой лабораторной работы вы будете использовать Firebase Authentication, Cloud Firestore, Cloud Storage, Cloud Messaging и Performance Monitoring, поэтому вы импортируете все их библиотеки. В своих будущих приложениях убедитесь, что вы импортируете только те части Firebase, которые вам нужны, чтобы сократить время загрузки вашего приложения.

8. Настройте вход пользователя

AngularFire теперь должен быть готов к использованию, поскольку он импортирован и инициализирован в app.module.ts . Теперь вы собираетесь реализовать вход пользователя с помощью Firebase Authentication .

Аутентифицируйте своих пользователей с помощью входа в Google

В приложении, когда пользователь нажимает кнопку «Войти через Google» , запускается функция login . (Вы уже это настроили!) Для этой лаборатории кода вы хотите разрешить Firebase использовать Google в качестве поставщика удостоверений. Вы будете использовать всплывающее окно, но в Firebase доступно несколько других методов .

  1. В каталоге angularfire-start в подкаталоге /src/app/services/ откройте chat.service.ts .
  2. Найдите функцию login .
  3. Замените всю функцию следующим кодом.

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

Функция logout срабатывает, когда пользователь нажимает кнопку «Выход» .

  1. Вернитесь к файлу src/app/services/chat.service.ts .
  2. Найдите функцию logout .
  3. Замените всю функцию следующим кодом.

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

Отслеживайте состояние аутентификации

Чтобы соответствующим образом обновить наш пользовательский интерфейс, вам нужен способ проверить, вошел ли пользователь в систему или вышел из системы. С помощью Firebase Authentication вы можете получить наблюдаемые данные о состоянии пользователя, которые будут срабатывать каждый раз, когда состояние аутентификации изменится.

  1. Вернитесь к файлу src/app/services/chat.service.ts .
  2. Найдите назначение переменной user$ .
  3. Замените все назначение следующим кодом.

chat.service.ts

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

Приведенный выше код вызывает user функции AngularFire, который возвращает наблюдаемого пользователя. Он срабатывает каждый раз, когда изменяется состояние аутентификации (когда пользователь входит в систему или выходит из системы). Именно на этом этапе вы обновите пользовательский интерфейс для перенаправления, отображения пользователя в заголовке навигации и т. д. Все эти части пользовательского интерфейса уже реализованы.

Тестовый вход в приложение

  1. Если ваше приложение все еще обслуживается, обновите его в браузере. В противном случае запустите firebase emulators:start в командной строке, чтобы начать обслуживание приложения с http://localhost:5000 , а затем откройте его в браузере.
  2. Войдите в приложение, используя кнопку входа и свою учетную запись Google. Если вы видите сообщение об ошибке с указанием auth/operation-not-allowed , убедитесь, что вы включили вход в Google в качестве поставщика аутентификации в консоли Firebase.
  3. После входа в систему должно отобразиться изображение вашего профиля и имя пользователя: angularfire-3.png

9. Напишите сообщения в Cloud Firestore.

В этом разделе вы запишите некоторые данные в Cloud Firestore, чтобы можно было заполнить пользовательский интерфейс приложения. Это можно сделать вручную с помощью консоли Firebase , но вы сделаете это в самом приложении, чтобы продемонстрировать базовую запись в Cloud Firestore.

Модель данных

Данные Cloud Firestore разделены на коллекции, документы, поля и подколлекции. Вы будете хранить каждое сообщение чата как документ в коллекции верхнего уровня под названием messages .

688d7bc5fb662b57.png

Добавьте сообщения в Cloud Firestore

Для хранения сообщений чата, написанных пользователями, вы будете использовать Cloud Firestore .

В этом разделе вы добавите пользователям возможность записи новых сообщений в вашу базу данных. Пользователь, нажавший кнопку ОТПРАВИТЬ , активирует приведенный ниже фрагмент кода. Он добавляет объект сообщения с содержимым полей сообщений в ваш экземпляр Cloud Firestore в коллекции messages . Метод add() добавляет в коллекцию новый документ с автоматически сгенерированным идентификатором.

  1. Вернитесь к файлу src/app/services/chat.service.ts .
  2. Найдите функцию addMessage .
  3. Замените всю функцию следующим кодом.

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

Тестовая отправка сообщений

  1. Если ваше приложение все еще обслуживается, обновите его в браузере. В противном случае запустите firebase emulators:start в командной строке, чтобы начать обслуживание приложения с http://localhost:5000 , а затем откройте его в браузере.
  2. После входа в систему введите сообщение, например «Привет!», а затем нажмите «ОТПРАВИТЬ» . Это запишет сообщение в Cloud Firestore. Однако вы еще не увидите данные в своем реальном веб-приложении, поскольку вам все еще нужно реализовать извлечение данных (следующий раздел кодовой лаборатории).
  3. Вы можете увидеть новое добавленное сообщение в консоли Firebase. Откройте пользовательский интерфейс пакета эмулятора. В разделе «Сборка» нажмите «База данных Firestore» (или нажмите здесь , и вы увидите коллекцию сообщений с новым добавленным сообщением:

6812efe7da395692.png

10. Читать сообщения

Синхронизировать сообщения

Чтобы читать сообщения в приложении, вам нужно добавить наблюдаемый объект, который будет срабатывать при изменении данных, а затем создать элемент пользовательского интерфейса, отображающий новые сообщения.

Вы добавите код, который прослушивает вновь добавленные сообщения из приложения. В этом коде вы получите снимок коллекции messages . Вы будете отображать только последние 12 сообщений чата, чтобы избежать отображения очень длинной истории при загрузке.

  1. Вернитесь к файлу src/app/services/chat.service.ts .
  2. Найдите функцию loadMessages .
  3. Замените всю функцию следующим кодом.

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

Чтобы прослушивать сообщения в базе данных, вы создаете запрос к коллекции, используя функцию collection , чтобы указать, в какой коллекции находятся данные, которые вы хотите прослушивать. В приведенном выше коде вы прослушиваете изменения в messages коллекция, в которой хранятся сообщения чата. Вы также применяете ограничение, прослушивая только последние 12 сообщений с помощью limit(12) и упорядочивая сообщения по дате с помощью orderBy('timestamp', 'desc') , чтобы получить 12 самых новых сообщений.

Функция collectionData использует моментальные снимки. Функция обратного вызова будет запущена при внесении каких-либо изменений в документы, соответствующие запросу. Это может произойти, если сообщение будет удалено, изменено или добавлено. Подробнее об этом можно прочитать в документации Cloud Firestore .

Проверка синхронизации сообщений

  1. Если ваше приложение все еще обслуживается, обновите его в браузере. В противном случае запустите firebase emulators:start в командной строке, чтобы начать обслуживание приложения с http://localhost:5000 , а затем откройте его в браузере.
  2. Сообщения, которые вы создали ранее в базе данных, должны отображаться в пользовательском интерфейсе FriendlyChat (см. ниже). Не стесняйтесь писать новые сообщения; они должны появиться мгновенно.
  3. (Необязательно) Вы можете попробовать вручную удалить, изменить или добавить новые сообщения непосредственно в разделе Firestore пакета эмулятора; любые изменения должны быть отражены в пользовательском интерфейсе.

Поздравляем! Вы читаете документы Cloud Firestore в своем приложении!

angularfire-2.png

11. Отправьте изображения

Теперь вы добавите функцию обмена изображениями.

Хотя Cloud Firestore хорош для хранения структурированных данных, Cloud Storage лучше подходит для хранения файлов. Cloud Storage for Firebase — это служба хранения файлов или BLOB-объектов, которую вы будете использовать для хранения любых изображений, которыми пользователь делится с помощью нашего приложения.

Сохраняйте изображения в облачное хранилище.

Для этой лаборатории кода вы уже добавили кнопку, которая запускает диалоговое окно выбора файла. После выбора файла вызывается функция saveImageMessage , и вы можете получить ссылку на выбранный файл. Функция saveImageMessage выполняет следующее:

  1. Создает сообщение чата-заполнителя в ленте чата, чтобы пользователи видели анимацию загрузки, пока вы загружаете изображение.
  2. Загружает файл изображения в Cloud Storage по этому пути: /<uid>/<file_name>
  3. Создает общедоступный URL-адрес для файла изображения.
  4. Обновляет сообщение чата, используя URL-адрес только что загруженного файла изображения вместо временного загружаемого изображения.

Теперь вы добавите функцию отправки изображения:

  1. Вернитесь к файлу src/index.js .
  2. Найдите функцию saveImageMessage .
  3. Замените всю функцию следующим кодом.

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

Тестовая отправка изображений

  1. Если ваше приложение все еще обслуживается, обновите его в браузере. В противном случае запустите firebase emulators:start в командной строке, чтобы начать обслуживание приложения с http://localhost:5000 , а затем откройте его в своем браузере.
  2. После входа в систему нажмите кнопку загрузки изображения в левом нижнем углу. angularfire-4.png и выберите файл изображения с помощью средства выбора файлов. Если вы ищете изображение, смело используйте это красивое изображение кофейной чашки .
  3. В пользовательском интерфейсе приложения должно появиться новое сообщение с выбранным вами изображением: angularfire-2.png

Если вы попытаетесь добавить изображение, не войдя в систему, вы увидите сообщение об ошибке, сообщающее, что вам необходимо войти в систему, чтобы добавить изображения.

12. Показать уведомления

Теперь вы добавите поддержку уведомлений браузера. Приложение будет уведомлять пользователей о появлении новых сообщений в чате. Firebase Cloud Messaging (FCM) — это кроссплатформенное решение для обмена сообщениями, которое позволяет надежно доставлять сообщения и уведомления бесплатно.

Добавьте сервисного работника FCM

Веб-приложению нужен сервисный работник , который будет получать и отображать веб-уведомления.

Поставщик обмена сообщениями уже должен был быть настроен при добавлении AngularFire. Убедитесь, что следующий код существует в разделе импорта /angularfire-start/src/app/app.module.ts

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

app/app.module.ts

Сервисному работнику просто нужно загрузить и инициализировать Firebase Cloud Messaging SDK, который позаботится об отображении уведомлений.

Получите токены устройств FCM

Если на устройстве или в браузере включены уведомления, вам будет предоставлен токен устройства . Этот токен устройства — это то, что вы используете для отправки уведомления на определенное устройство или определенный браузер.

Когда пользователь входит в систему, вы вызываете функцию saveMessagingDeviceToken . Здесь вы получите токен устройства FCM из браузера и сохраните его в Cloud Firestore.

chat.service.ts

  1. Найдите функцию saveMessagingDeviceToken .
  2. Замените всю функцию следующим кодом.

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

Однако изначально этот код не будет работать. Чтобы ваше приложение могло получить токен устройства, пользователю необходимо предоставить вашему приложению разрешение на показ уведомлений (следующий этап работы с кодом).

Запросить разрешения на показ уведомлений

Если пользователь еще не предоставил вашему приложению разрешение на показ уведомлений, вам не будет предоставлен токен устройства. В этом случае вы вызываете метод requestPermission() , который отобразит диалоговое окно браузера с запросом этого разрешения ( в поддерживаемых браузерах ).

8b9d0c66dc36153d.png

  1. Вернитесь к файлу src/app/services/chat.service.ts .
  2. Найдите функцию requestNotificationsPermissions .
  3. Замените всю функцию следующим кодом.

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

Получите токен вашего устройства

  1. Если ваше приложение все еще обслуживается, обновите его в браузере. В противном случае запустите firebase emulators:start в командной строке, чтобы начать обслуживание приложения с http://localhost:5000 , а затем откройте его в своем браузере.
  2. После входа в систему должно появиться диалоговое окно разрешения уведомлений: bd3454e6dbfb6723.png
  3. Нажмите Разрешить .
  4. Откройте консоль JavaScript вашего браузера. Вы должны увидеть следующее сообщение: Got FCM device token: cWL6w:APA91bHP...4jDPL_A-wPP06GJp1OuekTaTZI5K2Tu
  5. Скопируйте токен вашего устройства. Он понадобится вам на следующем этапе работы над кодом.

Отправьте уведомление на ваше устройство

Теперь, когда у вас есть токен устройства, вы можете отправить уведомление.

  1. Откройте вкладку Cloud Messaging консоли Firebase .
  2. Нажмите «Новое уведомление».
  3. Введите заголовок и текст уведомления.
  4. В правой части экрана нажмите «отправить тестовое сообщение».
  5. Введите токен устройства, который вы скопировали из консоли JavaScript вашего браузера, затем нажмите знак плюс («+»).
  6. Нажмите «тестировать»

Если ваше приложение находится на переднем плане, вы увидите уведомление в консоли JavaScript.

Если ваше приложение работает в фоновом режиме, в вашем браузере должно появиться уведомление, как в этом примере:

de79e8638a45864c.png

13. Правила безопасности Cloud Firestore

Просмотр правил безопасности базы данных

Cloud Firestore использует специальный язык правил для определения прав доступа, безопасности и проверки данных.

При настройке проекта Firebase в начале этой лабораторной работы вы решили использовать правила безопасности по умолчанию «Тестовый режим», чтобы не ограничивать доступ к хранилищу данных. В консоли Firebase на вкладке «Правила» раздела «База данных» вы можете просмотреть и изменить эти правила.

Прямо сейчас вы должны увидеть правила по умолчанию, которые не ограничивают доступ к хранилищу данных. Это означает, что любой пользователь может читать и записывать любые коллекции в вашем хранилище данных.

rules_version = '2';

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

Вы обновите правила, чтобы ограничить некоторые действия, используя следующие правила:

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

Правила безопасности должны автоматически обновиться до вашего пакета эмулятора.

Посмотреть правила безопасности Cloud Storage

Cloud Storage for Firebase использует специальный язык правил для определения прав доступа, безопасности и проверки данных.

При настройке проекта Firebase в начале этой лабораторной работы вы решили использовать правило безопасности Cloud Storage по умолчанию, которое позволяет использовать Cloud Storage только прошедшим проверку пользователям. В консоли Firebase на вкладке «Правила» раздела «Хранилище» вы можете просматривать и изменять правила. Вы должны увидеть правило по умолчанию, которое позволяет любому вошедшему пользователю читать и записывать любые файлы в вашем сегменте хранилища.

rules_version = '2';

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

Вы обновите правила, чтобы сделать следующее:

  • Разрешить каждому пользователю писать только в свои собственные папки
  • Разрешить всем читать данные из облачного хранилища
  • Убедитесь, что загруженные файлы являются изображениями.
  • Ограничьте размер загружаемых изображений максимум 5 МБ.

Это можно реализовать с помощью следующих правил:

Storage.rules

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. Разверните свое приложение с помощью хостинга Firebase.

Firebase предлагает услуги хостинга для обслуживания ваших ресурсов и веб-приложений. Вы можете развернуть свои файлы на хостинге Firebase с помощью интерфейса командной строки Firebase. Перед развертыванием вам необходимо указать в файле firebase.json , какие локальные файлы следует развернуть. Для этой лаборатории кода вы уже сделали это за вас, поскольку этот шаг был необходим для обслуживания наших файлов во время этой лаборатории кода. Настройки хостинга указаны в атрибуте 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"
  }
}

Эти настройки сообщают CLI, что вы хотите развернуть все файлы в каталоге ./public ( "public": "./public" ).

  1. Убедитесь, что ваша командная строка обращается к локальному каталогу angularfire-start вашего приложения.
  2. Разверните файлы в проекте Firebase, выполнив следующую команду:
ng deploy

Затем выберите параметр Firebase и следуйте инструкциям в командной строке.

  1. В консоли должно появиться следующее:
=== 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. Посетите свое веб-приложение, которое теперь полностью размещено в глобальной CDN, используя хостинг Firebase на двух ваших собственных поддоменах Firebase:
  • https://<firebase-projectId>.firebaseapp.com
  • https://<firebase-projectId>.web.app

Альтернативно вы можете запустить firebase open hosting:site в командной строке.

Посетите документацию, чтобы узнать больше о том, как работает хостинг Firebase .

Перейдите в раздел « Хостинг » консоли Firebase вашего проекта, чтобы просмотреть полезную информацию о хостинге и инструменты, включая историю ваших развертываний, функции возврата к предыдущим версиям вашего приложения и рабочий процесс для настройки личного домена.

15. Поздравляем!

Вы использовали Firebase для создания веб-приложения для чата в реальном времени!

Что вы рассмотрели

  • Аутентификация Firebase
  • Облачный пожарный магазин
  • Firebase SDK для облачного хранилища
  • Облачный обмен сообщениями Firebase
  • Мониторинг производительности Firebase
  • Хостинг Firebase

Следующие шаги

Узнать больше

16. [Необязательно] Принудительное выполнение с помощью проверки приложений

Проверка приложений Firebase помогает защитить ваши сервисы от нежелательного трафика и защитить ваш сервер от злоупотреблений. На этом этапе вы добавите проверку учетных данных и заблокируете неавторизованных клиентов с помощью App Check и reCAPTCHA Enterprise .

Сначала вам нужно включить проверку приложений и reCaptcha.

Включение reCaptcha Enterprise

  1. В облачной консоли найдите и выберите reCaptcha Enterprise в разделе «Безопасность».
  2. Включите службу согласно запросу и нажмите «Создать ключ» .
  3. Введите отображаемое имя в соответствии с запросом и выберите Веб-сайт в качестве типа платформы.
  4. Добавьте развернутые URL-адреса в список доменов и убедитесь, что параметр «Использовать вызов флажка» не выбран .
  5. Нажмите «Создать ключ» и сохраните сгенерированный ключ где-нибудь для безопасного хранения. Он понадобится вам позже на этом этапе.

Включение проверки приложений

  1. В консоли Firebase найдите раздел «Сборка» на левой панели.
  2. Нажмите «Проверка приложений» , затем перейдите на вкладку «Метод входа» , чтобы перейти к «Проверка приложений» .
  3. Нажмите «Зарегистрировать» и при появлении запроса введите ключ reCaptcha Enterprise, затем нажмите «Сохранить» .
  4. В представлении API выберите «Хранилище» и нажмите «Применить» . Сделайте то же самое для Cloud Firestore .

Проверка приложений теперь должна быть принудительно включена! Обновите приложение и попробуйте просмотреть или отправить сообщения чата. Вы должны получить сообщение об ошибке:

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

Это означает, что проверка приложений по умолчанию блокирует непроверенные запросы. Теперь давайте добавим проверку в ваше приложение.

Перейдите к файлу environment.ts и добавьте reCAPTCHAEnterpriseKey к объекту 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"
  },
};

Замените значение key своим токеном reCaptcha Enterprise.

Затем перейдите к файлу app.module.ts и добавьте следующий импорт:

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

В том же файле app.module.ts добавьте следующее объявление глобальной переменной:

declare global {
  var FIREBASE_APPCHECK_DEBUG_TOKEN: boolean;
}

@NgModule({ ...

При импорте добавьте инициализацию проверки приложений с помощью ReCaptchaEnterpriseProvider и установите для isTokenAutoRefreshEnabled значение true , чтобы токены автоматически обновлялись.

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

Чтобы разрешить локальное тестирование, установите для self.FIREBASE_APPCHECK_DEBUG_TOKEN значение true . Когда вы обновляете свое приложение на localhost , в консоли регистрируется токен отладки, похожий на:

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.

Теперь перейдите в представление «Проверка приложений» в консоли Firebase.

Нажмите на дополнительное меню и выберите «Управление токенами отладки ».

Затем нажмите «Добавить токен отладки» и вставьте токен отладки с консоли, как будет предложено.

Перейдите к файлу chat.service.ts и добавьте следующий импорт:

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

В том же файле chat.service.ts добавьте проверку приложений вместе с другими службами Firebase.

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

Поздравляем! Проверка приложений теперь должна работать в вашем приложении.