Познакомьтесь с Firebase для Интернета

1. Обзор

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

скриншот этого шага

Чему вы научитесь

  • Аутентифицируйте пользователей с помощью Firebase Authentication и FirebaseUI.
  • Синхронизируйте данные с помощью Cloud Firestore.
  • Напишите правила безопасности Firebase для защиты базы данных.

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

  • Браузер по вашему выбору, например Chrome.
  • Доступ к stackblitz.com (учетная запись или регистрация не требуются).
  • Учётная запись Google, например, Gmail. Мы рекомендуем использовать ту учётную запись электронной почты, которую вы уже используете для своего аккаунта GitHub. Это позволит вам использовать расширенные функции StackBlitz.
  • Пример кода для практического занятия. Чтобы узнать, как получить код, смотрите следующий шаг.

2. Получите стартовый код

В этой лабораторной работе вы создадите приложение с помощью StackBlitz — онлайн-редактора, в который интегрировано несколько рабочих процессов Firebase. Stackblitz не требует установки программного обеспечения или специальной учётной записи StackBlitz.

StackBlitz позволяет вам делиться проектами с другими. Другие пользователи, у которых есть URL вашего проекта StackBlitz, могут видеть ваш код и создавать ответвления, но не могут редактировать ваш проект StackBlitz.

  1. Перейдите по этому URL-адресу для получения начального кода: https://stackblitz.com/edit/firebase-gtk-web-start
  2. В верхней части страницы StackBlitz нажмите Fork :

скриншот этого шага

Теперь у вас есть копия начального кода в виде вашего собственного проекта StackBlitz с уникальным именем и уникальным URL-адресом. Все ваши файлы и изменения сохраняются в этом проекте StackBlitz.

3. Редактировать информацию о событии

Исходные материалы для этой практической работы предоставляют некоторую структуру веб-приложения, включая несколько таблиц стилей и несколько HTML-контейнеров. Далее в этой практической работе вы подключите эти контейнеры к Firebase.

Для начала давайте немного познакомимся с интерфейсом StackBlitz.

  1. В StackBlitz откройте файл index.html .
  2. Найдите event-details-container и description-container , затем попробуйте отредактировать некоторые сведения о событии.

Пока вы редактируете текст, автоматическая перезагрузка страницы в StackBlitz отображает информацию о новом событии. Круто, правда?

<!-- ... -->

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

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

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

  </section>

  <hr>

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

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

<!-- ... -->

Предварительный просмотр вашего приложения должен выглядеть примерно так:

Предварительный просмотр приложения

скриншот этого шага

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

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

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

  1. Войдите в консоль Firebase, используя свою учетную запись Google.
  2. Нажмите кнопку, чтобы создать новый проект, а затем введите имя проекта (например, Firebase-Web-Codelab ).
  3. Нажмите «Продолжить» .
  4. При появлении соответствующего запроса ознакомьтесь с условиями Firebase и примите их, а затем нажмите кнопку «Продолжить» .
  5. (Необязательно) Включите помощь ИИ в консоли Firebase (так называемая «Gemini в Firebase»).
  6. Для этой лабораторной работы вам не понадобится Google Analytics, поэтому отключите опцию Google Analytics.
  7. Нажмите «Создать проект» , дождитесь завершения подготовки проекта, а затем нажмите «Продолжить» .

Дополнительную информацию о проектах Firebase см. в разделе Понимание проектов Firebase .

Включите и настройте продукты Firebase в консоли

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

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

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

Включить вход по электронной почте для аутентификации Firebase

Чтобы разрешить пользователям входить в веб-приложение, для этой лабораторной работы вы будете использовать метод входа с использованием электронной почты и пароля :

  1. На левой панели консоли Firebase нажмите «Сборка» > «Аутентификация» . Затем нажмите « Начать» . Теперь вы находитесь на панели управления аутентификацией, где можете видеть зарегистрированных пользователей, настраивать поставщиков услуг входа и управлять параметрами.

    скриншот этого шага

  2. Выберите вкладку «Способ входа» (или нажмите здесь, чтобы перейти непосредственно на вкладку).

    скриншот этого шага

  3. Нажмите «Электронная почта/Пароль» в параметрах поставщика, переведите переключатель в положение «Включить» , а затем нажмите «Сохранить» .

    скриншот этого шага

Настройка Cloud Firestore

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

Вот как настроить Cloud Firestore в вашем проекте Firebase:

  1. На левой панели консоли Firebase разверните пункт «Сборка» , а затем выберите «База данных Firestore» .
  2. Нажмите Создать базу данных .
  3. Оставьте идентификатор базы данных равным (default) .
  4. Выберите местоположение вашей базы данных, затем нажмите «Далее» .
    Для настоящего приложения вам нужно выбрать местоположение, близкое к вашим пользователям.
  5. Нажмите «Начать в тестовом режиме» . Ознакомьтесь с отказом от ответственности о правилах безопасности.
    Далее в этой лабораторной работе вы добавите правила безопасности для защиты своих данных. Не распространяйте и не публикуйте приложение, не добавив правила безопасности для своей базы данных.
  6. Нажмите «Создать» .

5. Добавьте и настройте Firebase

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

Добавьте библиотеки Firebase

Чтобы ваше приложение использовало Firebase, необходимо добавить библиотеки Firebase. Это можно сделать несколькими способами, как описано в документации Firebase . Например, вы можете добавить библиотеки из CDN Google или установить их локально с помощью npm, а затем упаковать в своё приложение, если вы используете Browserify.

StackBlitz обеспечивает автоматическую сборку, поэтому вы можете добавлять библиотеки Firebase с помощью операторов импорта. Вы будете использовать модульные версии библиотек (v9), которые помогают уменьшить общий размер веб-страницы благодаря процессу, называемому «tree shake». Подробнее о модульных SDK можно узнать в документации .

Для создания этого приложения используются библиотеки Firebase Authentication, FirebaseUI и Cloud Firestore. В этой лабораторной работе следующие операторы импорта уже включены в начало файла index.js , и мы будем импортировать дополнительные методы из каждой библиотеки Firebase по мере выполнения:

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

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

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

import * as firebaseui from 'firebaseui';

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

  1. Вернувшись в консоль Firebase, перейдите на страницу обзора вашего проекта, нажав «Обзор проекта» в левом верхнем углу.
  2. В центре страницы обзора вашего проекта нажмите на значок Интернета. значок веб-приложения для создания нового веб-приложения Firebase.

    скриншот этого шага

  3. Зарегистрируйте приложение под именем Web App .
  4. Для этой практической работы НЕ устанавливайте флажок « Также настроить хостинг Firebase для этого приложения» . Пока что вы будете использовать панель предварительного просмотра StackBlitz.
  5. Нажмите «Зарегистрировать приложение» .

    скриншот этого шага

  6. Скопируйте объект конфигурации Firebase в буфер обмена.

    скриншот этого шага

  7. Нажмите «Продолжить», чтобы перейти в консоль . Добавьте объект конфигурации Firebase в свое приложение:
  8. Вернитесь в StackBlitz и перейдите к файлу index.js .
  9. Найдите строку комментария Add Firebase project configuration object here , затем вставьте фрагмент конфигурации прямо под комментарием.
  10. Добавьте вызов функции initializeApp для настройки Firebase с использованием уникальной конфигурации вашего проекта Firebase.
    // ...
    // Add Firebase project configuration object here
    const firebaseConfig = {
      apiKey: "random-unique-string",
      authDomain: "your-projectId.firebaseapp.com",
      databaseURL: "https://your-projectId.firebaseio.com",
      projectId: "your-projectId",
      storageBucket: "your-projectId.firebasestorage.app",
      messagingSenderId: "random-unique-string",
      appId: "random-unique-string",
    };
    
    // Initialize Firebase
    initializeApp(firebaseConfig);
    

6. Добавьте вход пользователя (RSVP)

Теперь, когда вы добавили Firebase в приложение, вы можете настроить кнопку RSVP, которая регистрирует людей, использующих аутентификацию Firebase .

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

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

Для FirebaseUI требуется конфигурация (см. параметры в документации ), которая выполняет две функции:

  • Сообщает FirebaseUI, что вы хотите использовать метод входа по электронной почте/паролю .
  • Обрабатывает обратный вызов при успешном входе и возвращает значение false, чтобы избежать перенаправления. Вы не хотите, чтобы страница обновлялась, поскольку создаёте одностраничное веб-приложение.

Добавьте код для инициализации FirebaseUI Auth.

  1. В StackBlitz перейдите к файлу index.js .
  2. Вверху найдите оператор импорта firebase/auth , затем добавьте getAuth и EmailAuthProvider , вот так:
    // ...
    // Add the Firebase products and methods that you want to use
    import { getAuth, EmailAuthProvider } from 'firebase/auth';
    
    import {} from 'firebase/firestore';
    
  3. Сохраните ссылку на объект аутентификации сразу после initializeApp , например так:
    initializeApp(firebaseConfig);
    auth = getAuth();
    
  4. Обратите внимание, что конфигурация FirebaseUI уже присутствует в стартовом коде. Она настроена на использование провайдера аутентификации по электронной почте.
  5. В нижней части функции main() в index.js добавьте оператор инициализации FirebaseUI, например:
    async function main() {
      // ...
    
      // Initialize the FirebaseUI widget using Firebase
      const ui = new firebaseui.auth.AuthUI(auth);
    }
    main();
    
    

Добавьте кнопку RSVP в HTML-код

  1. В StackBlitz перейдите к файлу index.html .
  2. Добавьте HTML-код для кнопки RSVP внутри event-details-container как показано в примере ниже.

    Будьте внимательны и используйте те же значения id , что показаны ниже, поскольку для этой кодовой работы уже есть хуки для этих конкретных идентификаторов в файле index.js .

    Обратите внимание, что в файле index.html есть контейнер с идентификатором firebaseui-auth-container . Этот идентификатор вы передадите в FirebaseUI для хранения данных вашего входа.
    <!-- ... -->
    
    <section id="event-details-container">
        <!-- ... -->
        <!-- ADD THE RSVP BUTTON HERE -->
        <button id="startRsvp">RSVP</button>
    </section>
    <hr>
    <section id="firebaseui-auth-container"></section>
    <!-- ... -->
    
    Предварительный просмотр приложения

    скриншот этого шага

  3. Настройте прослушиватель на кнопке RSVP и вызовите функцию запуска FirebaseUI. Это сообщит FirebaseUI, что вы хотите увидеть окно входа.

    Добавьте следующий код в конец функции main() в index.js :
    async function main() {
      // ...
    
      // Listen to RSVP button clicks
      startRsvpButton.addEventListener("click",
       () => {
            ui.start("#firebaseui-auth-container", uiConfig);
      });
    }
    main();
    

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

  1. В окне предварительного просмотра StackBlitz нажмите кнопку RSVP, чтобы войти в приложение.
    • Для этой лабораторной работы вы можете использовать любой адрес электронной почты, даже поддельный, поскольку для этой лабораторной работы вам не нужно настраивать этап проверки адреса электронной почты.
    • Если вы видите сообщение об ошибке auth/operation-not-allowed или The given sign-in provider is disabled for this Firebase project , убедитесь, что вы включили электронную почту/пароль в качестве поставщика входа в консоли Firebase.
    Предварительный просмотр приложения

    скриншот этого шага

  2. Перейдите на панель управления аутентификацией в консоли Firebase. На вкладке «Пользователи» вы увидите данные учётной записи, которые вы ввели для входа в приложение.

    скриншот этого шага

Добавить состояние аутентификации в пользовательский интерфейс

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

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

  1. В StackBlitz перейдите к файлу index.js .
  2. Вверху найдите оператор импорта firebase/auth , затем добавьте signOut и onAuthStateChanged , вот так:
    // ...
    // Add the Firebase products and methods that you want to use
    import {
      getAuth,
      EmailAuthProvider,
      signOut,
      onAuthStateChanged
    } from 'firebase/auth';
    
    import {} from 'firebase/firestore';
    
  3. Добавьте следующий код в конец функции main() :
    async function main() {
      // ...
    
      // Listen to the current Auth state
      onAuthStateChanged(auth, user => {
        if (user) {
          startRsvpButton.textContent = 'LOGOUT';
        } else {
          startRsvpButton.textContent = 'RSVP';
        }
      });
    }
    main();
    
  4. В прослушивателе кнопки проверьте наличие текущего пользователя и выйдите из системы. Для этого замените текущий startRsvpButton.addEventListener следующим:
    // ...
    // Called when the user clicks the RSVP button
    startRsvpButton.addEventListener('click', () => {
      if (auth.currentUser) {
        // User is signed in; allows user to sign out
        signOut(auth);
      } else {
        // No user is signed in; allows user to sign in
        ui.start('#firebaseui-auth-container', uiConfig);
      }
    });
    

Теперь кнопка в вашем приложении должна показывать LOGOUT (ВЫХОД) , а при нажатии она должна снова переключаться на RSVP .

Предварительный просмотр приложения

скриншот этого шага

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

Знать, что пользователи придут, — это здорово, но давайте предложим гостям что-то ещё в приложении. Что, если бы они могли оставлять сообщения в гостевой книге? Они могли бы рассказать, почему они рады приехать, или с кем надеются встретиться.

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

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

Cloud Firestore — это база данных NoSQL, в которой данные делятся на коллекции, документы, поля и подколлекции. Каждое сообщение чата будет храниться как документ в коллекции верхнего уровня, называемой guestbook .

Графическая модель данных Firestore, демонстрирующая коллекцию гостевых книг с несколькими документами сообщений

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

В этом разделе вы добавите функционал, позволяющий пользователям добавлять новые сообщения в базу данных. Сначала вы добавите HTML-код для элементов пользовательского интерфейса (поля сообщения и кнопки отправки), а затем — код, подключающий эти элементы к базе данных.

Чтобы добавить элементы пользовательского интерфейса поля сообщения и кнопку отправки:

  1. В StackBlitz перейдите к файлу index.html .
  2. Найдите guestbook-container , затем добавьте следующий HTML-код, чтобы создать форму с полем ввода сообщения и кнопкой отправки.
    <!-- ... -->
    
     <section id="guestbook-container">
       <h2>Discussion</h2>
    
       <form id="leave-message">
         <label>Leave a message: </label>
         <input type="text" id="message">
         <button type="submit">
           <i class="material-icons">send</i>
           <span>SEND</span>
         </button>
       </form>
    
     </section>
    
    <!-- ... -->
    

Предварительный просмотр приложения

скриншот этого шага

Нажатие пользователем кнопки «ОТПРАВИТЬ» активирует приведённый ниже фрагмент кода. Он добавляет содержимое поля ввода сообщения в коллекцию guestbook базы данных. В частности, метод addDoc добавляет содержимое сообщения в новый документ (с автоматически сгенерированным идентификатором) в коллекцию guestbook .

  1. В StackBlitz перейдите к файлу index.js .
  2. Вверху найдите оператор импорта firebase/firestore , затем добавьте getFirestore , addDoc и collection , вот так:
    // ...
    
    // Add the Firebase products and methods that you want to use
    import {
      getAuth,
      EmailAuthProvider,
      signOut,
      onAuthStateChanged
    } from 'firebase/auth';
    
    import {
      getFirestore,
      addDoc,
      collection
    } from 'firebase/firestore';
    
  3. Теперь сохраним ссылку на объект db Firestore сразу после initializeApp :
    initializeApp(firebaseConfig);
    auth = getAuth();
    db = getFirestore();
    
  4. Внизу функции main() добавьте следующий код.

    Обратите внимание, что auth.currentUser.uid — это ссылка на автоматически сгенерированный уникальный идентификатор, который аутентификация Firebase присваивает всем вошедшим в систему пользователям.
    async function main() {
      // ...
    
      // Listen to the form submission
      form.addEventListener('submit', async e => {
        // Prevent the default form redirect
        e.preventDefault();
        // Write a new message to the database collection "guestbook"
        addDoc(collection(db, 'guestbook'), {
          text: input.value,
          timestamp: Date.now(),
          name: auth.currentUser.displayName,
          userId: auth.currentUser.uid
        });
        // clear message input field
        input.value = '';
        // Return false to avoid redirect
        return false;
      });
    }
    main();
    

Показывать гостевую книгу только зарегистрированным пользователям

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

  1. В StackBlitz перейдите к файлу index.js .
  2. Отредактируйте прослушиватель onAuthStateChanged , чтобы скрыть и отобразить гостевую книгу.
    // ...
    
    // Listen to the current Auth state
    onAuthStateChanged(auth, user => {
      if (user) {
        startRsvpButton.textContent = 'LOGOUT';
        // Show guestbook to logged-in users
        guestbookContainer.style.display = 'block';
      } else {
        startRsvpButton.textContent = 'RSVP';
        // Hide guestbook for non-logged-in users
        guestbookContainer.style.display = 'none';
      }
    });
    

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

  1. Убедитесь, что вы вошли в приложение.
  2. Введите сообщение, например «Привет!», затем нажмите ОТПРАВИТЬ .

Это действие записывает сообщение в базу данных Cloud Firestore. Однако вы пока не увидите сообщение в своём веб-приложении, поскольку вам ещё нужно реализовать извлечение данных. Это мы сделаем далее.

Но вы можете увидеть новое добавленное сообщение в консоли Firebase.

В консоли Firebase, на панели управления базой данных Firestore , вы увидите коллекцию guestbook с вашим новым сообщением. Если вы продолжите отправлять сообщения, ваша коллекция гостевых книг будет содержать много документов, например:

Консоль Firebase

скриншот этого шага

8. Прочитать сообщения

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

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

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

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

  1. В StackBlitz перейдите к файлу index.html .
  2. В guestbook-container добавьте новый раздел с идентификатором guestbook .
    <!-- ... -->
    
      <section id="guestbook-container">
       <h2>Discussion</h2>
    
       <form><!-- ... --></form>
    
       <section id="guestbook"></section>
    
     </section>
    
    <!-- ... -->
    

Далее зарегистрируем прослушиватель, который отслеживает изменения данных:

  1. В StackBlitz перейдите к файлу index.js .
  2. Вверху найдите оператор импорта firebase/firestore , затем добавьте query , orderBy и onSnapshot , вот так:
    // ...
    import {
      getFirestore,
      addDoc,
      collection,
      query,
      orderBy,
      onSnapshot
    } from 'firebase/firestore';
    
  3. В конце функции main() добавьте следующий код для перебора всех документов (сообщений гостевой книги) в базе данных. Чтобы узнать больше о том, что происходит в этом коде, ознакомьтесь с информацией под фрагментом.
    async function main() {
      // ...
    
      // Create query for messages
      const q = query(collection(db, 'guestbook'), orderBy('timestamp', 'desc'));
      onSnapshot(q, snaps => {
        // Reset page
        guestbook.innerHTML = '';
        // Loop through documents in database
        snaps.forEach(doc => {
          // Create an HTML entry for each document and add it to the chat
          const entry = document.createElement('p');
          entry.textContent = doc.data().name + ': ' + doc.data().text;
          guestbook.appendChild(entry);
        });
      });
    }
    main();
    

Для прослушивания сообщений в базе данных вы создали запрос к определённой коллекции с помощью функции collection . Приведённый выше код прослушивает изменения в коллекции guestbook , где хранятся сообщения чата. Сообщения также сортируются по дате с помощью orderBy('timestamp', 'desc') для отображения самых новых сообщений вверху.

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

Тестовая синхронизация сообщений

Cloud Firestore автоматически и мгновенно синхронизирует данные с клиентами, подписанными на базу данных.

  • Сообщения, созданные ранее в базе данных, должны отображаться в приложении. Не стесняйтесь писать новые сообщения — они должны появляться мгновенно.
  • Если вы открываете свое рабочее пространство в нескольких окнах или вкладках, сообщения будут синхронизироваться в реальном времени между вкладками.
  • (Необязательно) Вы можете попробовать вручную удалить, изменить или добавить новые сообщения непосредственно в разделе «База данных» консоли Firebase; любые изменения должны отобразиться в пользовательском интерфейсе.

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

Предварительный просмотр приложения

скриншот этого шага

9. Установите основные правила безопасности

Изначально Cloud Firestore настроен на использование тестового режима, то есть ваша база данных открыта для чтения и записи. Однако тестовый режим следует использовать только на самых ранних этапах разработки. Рекомендуется настраивать правила безопасности для базы данных по мере разработки приложения. Безопасность должна быть неотъемлемой частью структуры и поведения вашего приложения.

Правила безопасности позволяют контролировать доступ к документам и коллекциям в базе данных. Гибкий синтаксис правил позволяет создавать правила, которые охватывают любые операции — от всех записей во всей базе данных до операций с конкретным документом.

Вы можете написать правила безопасности для Cloud Firestore в консоли Firebase:

  1. В разделе «Сборка» консоли Firebase нажмите «База данных Firestore» , затем выберите вкладку «Правила» (или нажмите здесь, чтобы перейти непосредственно на вкладку «Правила» ).
  2. Вы должны увидеть следующие правила безопасности по умолчанию с ограничением по времени публичного доступа через пару недель, начиная с сегодняшнего дня.

скриншот этого шага

Определить коллекции

Сначала определите коллекции, в которые приложение записывает данные.

  1. Удалите существующее предложение match /{document=**} , чтобы ваши правила выглядели так:
    rules_version = '2';
    service cloud.firestore {
      match /databases/{database}/documents {
      }
    }
    
  2. В match /databases/{database}/documents определите коллекцию, которую вы хотите защитить:
    rules_version = '2';
    service cloud.firestore {
      match /databases/{database}/documents {
        match /guestbook/{entry} {
         // You'll add rules here in the next step.
      }
    }
    

Добавить правила безопасности

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

  1. Добавьте правила чтения и записи в ваш набор правил, как показано ниже:
    rules_version = '2';
    service cloud.firestore {
      match /databases/{database}/documents {
        match /guestbook/{entry} {
          allow read: if request.auth.uid != null;
          allow create:
            if request.auth.uid == request.resource.data.userId;
        }
      }
    }
    
  2. Нажмите «Опубликовать» , чтобы применить новые правила. Теперь читать сообщения в гостевой книге (любые!) смогут только зарегистрированные пользователи, но создавать сообщения можно только с помощью своего идентификатора пользователя. Мы также не разрешаем редактировать и удалять сообщения.

Добавить правила проверки

  1. Добавьте проверку данных, чтобы убедиться, что все ожидаемые поля присутствуют в документе:
    rules_version = '2';
    service cloud.firestore {
      match /databases/{database}/documents {
        match /guestbook/{entry} {
          allow read: if request.auth.uid != null;
          allow create:
          if request.auth.uid == request.resource.data.userId
              && "name" in request.resource.data
              && "text" in request.resource.data
              && "timestamp" in request.resource.data;
        }
      }
    }
    
  2. Нажмите «Опубликовать» , чтобы внедрить новые правила.

Сбросить слушателей

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

  1. В StackBlitz перейдите к файлу index.js .
  2. Добавьте прослушиватель onSnapshot коллекции гостевых книг в новую функцию subscribeGuestbook . Также присвойте результаты функции onSnapshot переменной guestbookListener .

    Прослушиватель Firestore onSnapshot возвращает функцию отмены подписки, которую вы сможете использовать для отмены прослушивателя снимков позже.
    // ...
    // Listen to guestbook updates
    function subscribeGuestbook() {
      const q = query(collection(db, 'guestbook'), orderBy('timestamp', 'desc'));
      guestbookListener = onSnapshot(q, snaps => {
        // Reset page
        guestbook.innerHTML = '';
        // Loop through documents in database
        snaps.forEach(doc => {
          // Create an HTML entry for each document and add it to the chat
          const entry = document.createElement('p');
          entry.textContent = doc.data().name + ': ' + doc.data().text;
          guestbook.appendChild(entry);
        });
      });
    }
    
  3. Добавьте новую функцию под названием unsubscribeGuestbook . Проверьте, не равна ли переменная guestbookListener нулю, а затем вызовите функцию, чтобы отменить прослушивание.
    // ...
    // Unsubscribe from guestbook updates
    function unsubscribeGuestbook() {
      if (guestbookListener != null) {
        guestbookListener();
        guestbookListener = null;
      }
    }
    

Наконец, добавьте новые функции в обратный вызов onAuthStateChanged .

  1. Добавьте subscribeGuestbook() в конец if (user) .
  2. Добавьте unsubscribeGuestbook() в конец оператора else .
    // ...
    // Listen to the current Auth state
    onAuthStateChanged(auth, user => {
      if (user) {
        startRsvpButton.textContent = 'LOGOUT';
        // Show guestbook to logged-in users
        guestbookContainer.style.display = 'block';
        // Subscribe to the guestbook collection
        subscribeGuestbook();
      } else {
        startRsvpButton.textContent = 'RSVP';
        // Hide guestbook for non-logged-in users
        guestbookContainer.style.display = 'none';
        // Unsubscribe from the guestbook collection
        unsubscribeGuestbook();
      }
    });
    

10. Бонусный шаг: практикуйте то, что вы узнали

Запишите статус RSVP участника

Сейчас ваше приложение позволяет людям начать чат, если им интересно мероприятие. Кроме того, единственный способ узнать, придёт ли кто-то, — это написать об этом в чате. Давайте организуемся и сообщим людям, сколько человек придёт.

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

  1. В StackBlitz перейдите к файлу index.html .
  2. В guestbook-container добавьте набор кнопок ДА и НЕТ , например:
    <!-- ... -->
      <section id="guestbook-container">
       <h2>Are you attending?</h2>
         <button id="rsvp-yes">YES</button>
         <button id="rsvp-no">NO</button>
    
       <h2>Discussion</h2>
    
       <!-- ... -->
    
     </section>
    <!-- ... -->
    

Предварительный просмотр приложения

скриншот этого шага

Затем зарегистрируйте прослушиватель нажатий кнопок. Если пользователь нажмёт «ДА» , используйте его UID аутентификации для сохранения ответа в базе данных.

  1. В StackBlitz перейдите к файлу index.js .
  2. Вверху найдите оператор импорта firebase/firestore , затем добавьте doc , setDoc и where , вот так:
    // ...
    // Add the Firebase products and methods that you want to use
    import {
      getFirestore,
      addDoc,
      collection,
      query,
      orderBy,
      onSnapshot,
      doc,
      setDoc,
      where
    } from 'firebase/firestore';
    
  3. В нижней части функции main() добавьте следующий код для прослушивания статуса RSVP:
    async function main() {
      // ...
    
      // Listen to RSVP responses
      rsvpYes.onclick = async () => {
      };
      rsvpNo.onclick = async () => {
      };
    }
    main();
    
    
  4. Затем создайте новую коллекцию с именем attendees и зарегистрируйте ссылку на документ при нажатии любой из кнопок RSVP. Установите для этой ссылки значение true или false в зависимости от того, какая кнопка нажата.

    Во-первых, для rsvpYes :
    // ...
    // Listen to RSVP responses
    rsvpYes.onclick = async () => {
      // Get a reference to the user's document in the attendees collection
      const userRef = doc(db, 'attendees', auth.currentUser.uid);
    
      // If they RSVP'd yes, save a document with attendi()ng: true
      try {
        await setDoc(userRef, {
          attending: true
        });
      } catch (e) {
        console.error(e);
      }
    };
    
    Затем то же самое для rsvpNo , но со значением false :
    rsvpNo.onclick = async () => {
      // Get a reference to the user's document in the attendees collection
      const userRef = doc(db, 'attendees', auth.currentUser.uid);
    
      // If they RSVP'd yes, save a document with attending: true
      try {
        await setDoc(userRef, {
          attending: false
        });
      } catch (e) {
        console.error(e);
      }
    };
    

Обновите свои правила безопасности

Поскольку у вас уже установлены некоторые правила, новые данные, которые вы добавляете с помощью кнопок, будут отклонены.

Разрешить дополнения к коллекции attendees

Вам необходимо обновить правила, чтобы разрешить добавление в коллекцию attendees .

  1. Что касается коллекции attendees , поскольку вы использовали UID аутентификации в качестве имени документа, вы можете получить её и убедиться, что uid отправителя совпадает с UID создаваемого документа. Вы разрешите всем читать список участников (поскольку там нет личных данных), но обновлять его сможет только создатель.
    rules_version = '2';
    service cloud.firestore {
      match /databases/{database}/documents {
        // ... //
        match /attendees/{userId} {
          allow read: if true;
          allow write: if request.auth.uid == userId;
        }
      }
    }
    
  2. Нажмите «Опубликовать» , чтобы внедрить новые правила.

Добавить правила проверки

  1. Добавьте несколько правил проверки данных, чтобы убедиться, что все ожидаемые поля присутствуют в документе:
    rules_version = '2';
    service cloud.firestore {
      match /databases/{database}/documents {
        // ... //
        match /attendees/{userId} {
          allow read: if true;
          allow write: if request.auth.uid == userId
              && "attending" in request.resource.data;
    
        }
      }
    }
    
  2. Не забудьте нажать кнопку «Опубликовать» , чтобы внедрить свои правила!

(Необязательно) Теперь вы можете просматривать результаты нажатия кнопок. Перейдите на панель управления Cloud Firestore в консоли Firebase.

Прочитать статус RSVP

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

  1. В StackBlitz перейдите к файлу index.html .
  2. В description-container добавьте новый элемент с идентификатором number-attending .
    <!-- ... -->
    
     <section id="description-container">
         <!-- ... -->
         <p id="number-attending"></p>
     </section>
    
    <!-- ... -->
    

Далее регистрируем слушателя для сбора attendees и подсчитываем количество ответов «ДА» :

  1. В StackBlitz перейдите к файлу index.js .
  2. В нижней части функции main() добавьте следующий код для прослушивания статуса RSVP и подсчета кликов «ДА» .
    async function main() {
      // ...
    
      // Listen for attendee list
      const attendingQuery = query(
        collection(db, 'attendees'),
        where('attending', '==', true)
      );
      const unsubscribe = onSnapshot(attendingQuery, snap => {
        const newAttendeeCount = snap.docs.length;
        numberAttending.innerHTML = newAttendeeCount + ' people going';
      });
    }
    main();
    

Наконец, давайте выделим кнопку, соответствующую текущему статусу.

  1. Создайте функцию, которая проверяет, есть ли запись текущего UID аутентификации в коллекции attendees , затем задайте классу кнопки значение clicked .
    // ...
    // Listen for attendee list
    function subscribeCurrentRSVP(user) {
      const ref = doc(db, 'attendees', user.uid);
      rsvpListener = onSnapshot(ref, doc => {
        if (doc && doc.data()) {
          const attendingResponse = doc.data().attending;
    
          // Update css classes for buttons
          if (attendingResponse) {
            rsvpYes.className = 'clicked';
            rsvpNo.className = '';
          } else {
            rsvpYes.className = '';
            rsvpNo.className = 'clicked';
          }
        }
      });
    }
    
  2. Также давайте создадим функцию для отмены подписки. Она будет срабатывать при выходе пользователя из системы.
    // ...
    function unsubscribeCurrentRSVP() {
      if (rsvpListener != null) {
        rsvpListener();
        rsvpListener = null;
      }
      rsvpYes.className = '';
      rsvpNo.className = '';
    }
    
  3. Вызовите функции из прослушивателя аутентификации.
    // ...
    // Listen to the current Auth state
      // Listen to the current Auth state
      onAuthStateChanged(auth, user => {
        if (user) {
          startRsvpButton.textContent = 'LOGOUT';
          // Show guestbook to logged-in users
          guestbookContainer.style.display = 'block';
    
          // Subscribe to the guestbook collection
          subscribeGuestbook();
          // Subscribe to the user's RSVP
          subscribeCurrentRSVP(user);
        } else {
          startRsvpButton.textContent = 'RSVP';
          // Hide guestbook for non-logged-in users
          guestbookContainer.style.display = 'none'
          ;
          // Unsubscribe from the guestbook collection
          unsubscribeGuestbook();
          // Unsubscribe from the guestbook collection
          unsubscribeCurrentRSVP();
        }
      });
    
  4. Попробуйте войти в систему как несколько пользователей и увидите, как с каждым нажатием кнопки «ДА» счетчик увеличивается.

Предварительный просмотр приложения

скриншот этого шага

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

Вы использовали Firebase для создания интерактивного веб-приложения, работающего в режиме реального времени!

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

  • Аутентификация Firebase
  • FirebaseUI
  • Cloud Firestore
  • Правила безопасности Firebase

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

  • Хотите узнать больше о рабочем процессе разработчика Firebase? Ознакомьтесь с практической частью по эмулятору Firebase, чтобы узнать, как протестировать и запустить приложение полностью локально.
  • Хотите узнать больше о других продуктах Firebase? Возможно, вам нужно хранить изображения, загружаемые пользователями? Или отправлять уведомления пользователям? Ознакомьтесь с практической работой по веб-версии Firebase, где подробно рассматриваются многие другие продукты Firebase для веб-версии.
  • Хотите узнать больше о Cloud Firestore? Возможно, вам интересно узнать о вложенных коллекциях и транзакциях? Посетите веб-сайт Cloud Firestore, где вы найдете практикум, подробно рассказывающий об Cloud Firestore. Или посмотрите эту серию видео на YouTube, чтобы узнать больше об Cloud Firestore !

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

Как всё прошло?

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