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

1. Обзор

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

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

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

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

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

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

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 .
  2. В консоли Firebase нажмите «Добавить проект» (или «Создать проект» ), затем назовите свой проект Firebase Firebase-Web-Codelab .

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

  3. Просмотрите параметры создания проекта. Примите условия Firebase, если будет предложено. На экране Google Analytics нажмите «Не включать», поскольку вы не будете использовать Analytics для этого приложения.

Дополнительные сведения о проектах Firebase см. в разделе Общие сведения о проектах Firebase .

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

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

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

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

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

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

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

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

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

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

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

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

Настройте Cloud Firestore

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

Вот как настроить Cloud Firestore:

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

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

  3. Выберите опцию «Запустить в тестовом режиме» . Прочтите отказ от ответственности о правилах безопасности. Тестовый режим гарантирует, что вы можете свободно писать в базу данных во время разработки. Нажмите "Далее .

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

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

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

  5. Нажмите Готово .

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

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

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

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

StackBlitz обеспечивает автоматическое объединение, поэтому вы можете добавлять библиотеки Firebase с помощью операторов импорта. Вы будете использовать модульные версии библиотек (v9), которые помогают уменьшить общий размер веб-страницы с помощью процесса, называемого «встряхиванием дерева». Подробнее о модульных 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.appspot.com",
      messagingSenderId: "random-unique-string",
      appId: "random-unique-string",
    };
    
    // Initialize Firebase
    initializeApp(firebaseConfig);
    

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

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

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

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

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

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

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

  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 нажмите кнопку «Ответить», чтобы войти в приложение.
    • Для этой лаборатории кода вы можете использовать любой адрес электронной почты, даже поддельный адрес электронной почты, поскольку для этой лаборатории кода вы не настраиваете этап проверки электронной почты.
    • Если вы видите сообщение об ошибке с указанием auth/operation-not-allowed или The given sign-in provider is disabled for this Firebase project , убедитесь, что вы включили адрес электронной почты/пароль в качестве поставщика входа в консоль Firebase.
    Предварительный просмотр приложения

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

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

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

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

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

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

  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 Authentication предоставляет всем вошедшим в систему пользователям.
    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. Бонусный шаг: практикуйте то, что вы узнали.

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

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

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

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

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

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

Затем зарегистрируйте прослушиватель нажатий кнопок. Если пользователь нажимает YES , используйте свой 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 , а затем зарегистрируйте ссылку на документ, если будет нажата любая кнопка «Ответить на приглашение». Установите для этой ссылки значение 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 отправителя совпадает с идентификатором документа, который он пишет. Вы разрешите всем читать список участников (поскольку в нем нет личных данных), но только создатель сможет его обновлять.
    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.

Прочитать статус ответа

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

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

Затем зарегистрируйте прослушиватель для коллекции attendees и подсчитайте количество ответов YES :

  1. В StackBlitz перейдите к файлу index.js .
  2. В нижней части функции main() добавьте следующий код для прослушивания статуса ответа и подсчета кликов ДА .
    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
  • Облачный пожарный магазин
  • Правила безопасности Firebase

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

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

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

Как прошло?

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