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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Настроить облачный магазин 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 Hosting для этого приложения» . Пока вы будете использовать панель предварительного просмотра 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 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 Authentication, который получает уведомление при каждом изменении статуса входа пользователя. Если в настоящее время есть пользователь, вошедший в систему, ваше приложение переключит кнопку «Ответить» на кнопку «Выход».

  1. В StackBlitz перейдите к файлу index.js .
  2. Вверху найдите оператор импорта firebase 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 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 сразу после 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 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 добавьте набор кнопок YES и NO , например:
    <!-- ... -->
      <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 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 совпадает с документом, который они пишут. Вы позволите всем читать список участников (поскольку там нет личных данных), но только создатель должен иметь возможность обновлять его.
    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() добавьте следующий код, чтобы прослушивать статус RSVP и подсчитывать клики YES .
    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();
          // Subcribe 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
  • Облако Firestore
  • Правила безопасности Firebase

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

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

Учить больше

Как прошло?

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