Informacje o Firebase w przeglądarce

1. Omówienie

W tym laboratorium programistycznym poznasz podstawy korzystania z Firebase, aby tworzyć interaktywne aplikacje internetowe. Utworzysz aplikację do potwierdzania udziału w imprezie i prowadzenia rozmów w księdze gości za pomocą kilku usług Firebase.

zrzut ekranu z tego kroku

Czego się nauczysz

  • Uwierzytelniaj użytkowników za pomocą Uwierzytelniania Firebase i FirebaseUI.
  • Synchronizuj dane za pomocą Cloud Firestore.
  • Aby zabezpieczyć bazę danych, napisz reguły zabezpieczeń Firebase.

Czego potrzebujesz

  • przeglądarkę, np. Chrome;
  • Dostęp do stackblitz.com (nie trzeba zakładać konta ani się logować).
  • Konto Google, np. konto Gmail. Zalecamy użycie adresu e-mail, którego używasz już na koncie GitHub. Dzięki temu możesz korzystać z funkcji zaawansowanych w StackBlitz.
  • Przykładowy kod w laboratorium programistycznym. Aby dowiedzieć się, jak uzyskać kod, przejdź do następnego kroku.

2. Pobieranie kodu początkowego

W tym laboratorium programistycznym utworzysz aplikację za pomocą StackBlitz, edytora online z kilkoma zintegrowanymi przepływami pracy Firebase. Aby korzystać z Stackblitz, nie musisz instalować żadnego oprogramowania ani zakładać specjalnego konta StackBlitz.

StackBlitz umożliwia udostępnianie projektów innym osobom. Inne osoby, które mają adres URL Twojego projektu StackBlitz, mogą zobaczyć Twój kod i stworzyć jego fork, ale nie mogą edytować Twojego projektu StackBlitz.

  1. Aby uzyskać kod początkowy, otwórz ten adres URL: https://stackblitz.com/edit/firebase-gtk-web-start
  2. U góry strony StackBlitz kliknij Rozwiń:

zrzut ekranu z tego kroku

Masz teraz kopię kodu początkowego jako swój własny projekt StackBlitz, który ma unikalną nazwę i niepowtarzalny adres URL. Wszystkie pliki i zmiany są zapisywane w tym projekcie StackBlitz.

3. Edytowanie informacji o wydarzeniu

Materiały początkowe w tym samouczku zawierają strukturę aplikacji internetowej, w tym kilka arkuszy stylów i kilka kontenerów HTML. W dalszej części samouczka te kontenery zostaną połączone z Firebase.

Na początek zapoznaj się z interfejsem StackBlitz.

  1. W StackBlitz otwórz plik index.html.
  2. Odszukaj event-details-containerdescription-container, a potem spróbuj edytować niektóre szczegóły wydarzenia.

Gdy edytujesz tekst, automatyczne odświeżanie strony w StackBlitz spowoduje wyświetlenie nowych szczegółów wydarzenia. Świetnie.

<!-- ... -->

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

<!-- ... -->

Podgląd aplikacji powinien wyglądać mniej więcej tak:

Podgląd aplikacji

zrzut ekranu z tego kroku

4. Tworzenie i konfigurowanie projektu Firebase

Wyświetlanie informacji o imprezie jest przydatne dla gości, ale samo wyświetlanie wydarzeń nie jest zbyt przydatne. Dodajmy do tej aplikacji kilka dynamicznych funkcji. Aby to zrobić, musisz połączyć Firebase z aplikacją. Aby zacząć korzystać z Firebase, musisz utworzyć i skonfigurować projekt Firebase.

Tworzenie projektu Firebase

  1. Zaloguj się w Firebase.
  2. W konsoli Firebase kliknij Dodaj projekt (lub Utwórz projekt), a następnie nadaj projektowi Firebase nazwę Firebase-Web-Codelab.

    zrzut ekranu z tego kroku

  3. Przejrzyj opcje tworzenia projektu. Zaakceptuj warunki korzystania z Firebase, jeśli pojawi się taka prośba. Na ekranie Google Analytics kliknij „Nie włączaj”, ponieważ nie będziesz używać Analytics w przypadku tej aplikacji.

Więcej informacji o projektach Firebase znajdziesz w artykule Informacje o projektach Firebase.

Włączanie i konfigurowanie usług Firebase w konsoli

Tworzona przez Ciebie aplikacja korzysta z kilku usług Firebase dostępnych dla aplikacji internetowych:

  • Uwierzytelnianie Firebaseinterfejs Firebase, aby umożliwić użytkownikom łatwe logowanie się w aplikacji.
  • Cloud Firestore do zapisywania ustrukturyzowanych danych w chmurze i otrzymywania natychmiastowych powiadomień o zmianach danych.
  • Reguły zabezpieczeń Firebase, aby zabezpieczyć bazę danych.

Niektóre z tych usług wymagają specjalnej konfiguracji lub ich włączenie musi nastąpić w konsoli Firebase.

Włączanie logowania przez e-maila w Uwierzytelnianiu Firebase

Aby umożliwić użytkownikom logowanie się w aplikacji internetowej, w tym ćwiczeniu będziesz używać metody logowania E-mail/hasło:

  1. W panelu po lewej stronie w konsoli Firebase kliknij Kompilacja > Uwierzytelnianie. Następnie kliknij Rozpocznij. Jesteś teraz w panelu uwierzytelniania, w którym możesz wyświetlać zarejestrowanych użytkowników, konfigurować dostawców logowania i zarządzać ustawieniami.

    zrzut ekranu z tego kroku

  2. Wybierz kartę Metoda logowania (lub kliknij tutaj, aby przejść bezpośrednio do tej karty).

    zrzut ekranu z tego kroku

  3. W opcjach dostawcy kliknij E-mail/hasło, przełącz przełącznik na Włącz, a następnie kliknij Zapisz.

    zrzut ekranu z tego kroku

Konfigurowanie Cloud Firestore

Aplikacja internetowa używa usługi Cloud Firestore do zapisywania wiadomości czatu i odbierania nowych wiadomości czatu.

Aby skonfigurować Cloud Firestore w projekcie Firebase:

  1. W panelu po lewej stronie w konsoli Firebase rozwiń Kompilacja, a potem wybierz Baza danych Firestore.
  2. Kliknij Utwórz bazę danych.
  3. Pozostaw wartość (default) w polu Identyfikator bazy danych.
  4. Wybierz lokalizację bazy danych, a potem kliknij Dalej.
    W przypadku prawdziwej aplikacji wybierz lokalizację blisko użytkowników.
  5. Kliknij Rozpocznij w trybie testowym. Przeczytaj wyłączenie odpowiedzialności dotyczące reguł bezpieczeństwa.
    W dalszej części tego Codelab dodasz reguły bezpieczeństwa, aby chronić swoje dane. Nie udostępniaj ani nie udostępniaj publicznie aplikacji bez dodania reguł bezpieczeństwa dla bazy danych.
  6. Kliknij Utwórz.

5. Dodawanie i konfigurowanie Firebase

Po utworzeniu projektu Firebase i włączeniu niektórych usług musisz wskazać kodowi, że chcesz korzystać z Firebase, a także z którego projektu Firebase.

Dodawanie bibliotek Firebase

Aby aplikacja mogła korzystać z Firebase, musisz dodać do niej biblioteki Firebase. Możesz to zrobić na kilka sposobów, które zostały opisane w dokumentacji Firebase. Możesz na przykład dodać biblioteki z usługi CDN Google lub zainstalować je lokalnie za pomocą npm, a następnie spakować je w aplikacji, jeśli używasz Browserify.

StackBlitz zapewnia automatyczne łączenie, dzięki czemu możesz dodawać biblioteki Firebase za pomocą instrukcji importu. Będziesz używać modułowych wersji bibliotek (wersja 9), które pomagają zmniejszyć ogólny rozmiar strony internetowej dzięki procesowi zwanemu „tree shaking”. Więcej informacji o modułowych pakietach SDK znajdziesz w dokumentacji.

Do jej utworzenia użyjesz bibliotek Firebase Authentication, FirebaseUI i Cloud Firestore. W tym laboratorium kodowania na początku pliku index.js znajdują się już te instrukcje importowania: w dalszej części laboratorium będziemy importować kolejne metody z każdej biblioteki 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';

Dodaj aplikację internetową Firebase do projektu Firebase

  1. W konsoli Firebase otwórz stronę przeglądu projektu, klikając w lewym górnym rogu Przegląd projektu.
  2. W środku strony przeglądu projektu kliknij ikonę sieci Ikona aplikacji internetowej, aby utworzyć nową aplikację internetową Firebase.

    zrzut ekranu z tego kroku

  3. Zarejestruj aplikację przy użyciu pseudonimu Aplikacja internetowa.
  4. W tym ćwiczeniu NIE zaznaczaj pola obok opcji Skonfiguruj również Hosting Firebase dla tej aplikacji. Na razie użyjesz panelu podglądu StackBlitz.
  5. Kliknij Zarejestruj aplikację.

    zrzut ekranu z tego kroku

  6. Skopiuj obiekt konfiguracji Firebase do schowka.

    zrzut ekranu z tego kroku

  7. Kliknij Przejdź do konsoli.Dodaj obiekt konfiguracji Firebase do aplikacji:
  8. Wróć do StackBlitz i otwórz plik index.js.
  9. Znajdź wiersz komentarza Add Firebase project configuration object here, a następnie wklej fragment kodu konfiguracyjnego tuż pod komentarzem.
  10. Aby skonfigurować Firebase, używając unikalnej konfiguracji projektu Firebase, dodaj wywołanie funkcji initializeApp.
    // ...
    // 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. Dodawanie logowania użytkownika (odpowiedzi na zaproszenie)

Po dodaniu Firebase do aplikacji możesz skonfigurować przycisk potwierdzenia, który rejestruje osoby korzystające z usługi uwierzytelniania Firebase.

Uwierzytelnianie użytkowników za pomocą logowania e-mail i FirebaseUI

Potrzebujesz przycisku odpowiedzi, który zachęca użytkownika do zalogowania się za pomocą adresu e-mail. Możesz to zrobić, łącząc FirebaseUI z przyciskiem odpowiedzi.FirebaseUI to biblioteka, która zapewnia gotowe interfejs użytkownika oparty na Firebase Auth.

FirebaseUI wymaga konfiguracji (zobacz opcje w dokumentacji), która spełnia 2 funkcje:

  • Informuje FirebaseUI, że chcesz używać metody logowania Adres e-mail i hasło.
  • Obsługuje wywołanie zwrotne w przypadku udanego logowania i zwraca wartość false, aby uniknąć przekierowania. Nie chcesz, aby strona była odświeżana, ponieważ tworzysz aplikację internetową na jednej stronie.

Dodaj kod do inicjowania FirebaseUI Auth

  1. W StackBlitz otwórz plik index.js.
  2. U góry odszukaj instrukcję importu firebase/auth, a potem dodaj getAuthEmailAuthProvider, tak jak tutaj:
    // ...
    // Add the Firebase products and methods that you want to use
    import { getAuth, EmailAuthProvider } from 'firebase/auth';
    
    import {} from 'firebase/firestore';
    
  3. Zapisz odwołanie do obiektu autoryzacji tuż po initializeApp, np.:
    initializeApp(firebaseConfig);
    auth = getAuth();
    
  4. Zwróć uwagę, że konfiguracja FirebaseUI jest już podana w kodzie początkowym. Jest już skonfigurowany do korzystania z dostawcy uwierzytelniania e-mail.
  5. Na dole funkcji main() w pliku index.js dodaj instrukcję inicjowania FirebaseUI, np.:
    async function main() {
      // ...
    
      // Initialize the FirebaseUI widget using Firebase
      const ui = new firebaseui.auth.AuthUI(auth);
    }
    main();
    
    

Dodawanie przycisku odpowiedzi do kodu HTML

  1. W StackBlitz otwórz plik index.html.
  2. Dodaj kod HTML przycisku odpowiedzi w miejscu event-details-container, jak pokazano w przykładzie poniżej.

    Upewnij się, że używasz tych samych wartości id, co w przykładzie, ponieważ w pliku index.js są już zaimplementowane odpowiednie uchwyty dla tych konkretnych identyfikatorów.

    Pamiętaj, że w pliku index.html znajduje się kontener o identyfikatorze firebaseui-auth-container. Ten identyfikator przekażesz FirebaseUI, aby przechowywać dane logowania.
    <!-- ... -->
    
    <section id="event-details-container">
        <!-- ... -->
        <!-- ADD THE RSVP BUTTON HERE -->
        <button id="startRsvp">RSVP</button>
    </section>
    <hr>
    <section id="firebaseui-auth-container"></section>
    <!-- ... -->
    
    Podgląd aplikacji

    zrzut ekranu z tego kroku

  3. Skonfiguruj odbiornik na przycisku RSVP i wywołaj funkcję start FirebaseUI. To powoduje, że FirebaseUI wyświetla okno logowania.

    Dodaj ten kod na dole funkcji main() w pliku index.js:
    async function main() {
      // ...
    
      // Listen to RSVP button clicks
      startRsvpButton.addEventListener("click",
       () => {
            ui.start("#firebaseui-auth-container", uiConfig);
      });
    }
    main();
    

Testowanie logowania się w aplikacji

  1. W oknie podglądu StackBlitz kliknij przycisk RSVP, aby zalogować się w aplikacji.
    • W tym ćwiczeniu możesz użyć dowolnego adresu e-mail, nawet fałszywego, ponieważ nie konfigurujesz w nim weryfikacji adresu e-mail.
    • Jeśli zobaczysz komunikat o błędzie auth/operation-not-allowed lub The given sign-in provider is disabled for this Firebase project, sprawdź, czy w konsoli Firebase jako dostawcę logowania masz włączoną opcję E-mail/hasło.
    Podgląd aplikacji

    zrzut ekranu z tego kroku

  2. Otwórz panel Uwierzytelnianie w konsoli Firebase. Na karcie Użytkownicy powinny być widoczne informacje o koncie, które zostały podane podczas logowania się w aplikacji.

    zrzut ekranu z tego kroku

Dodawanie stanu uwierzytelniania do interfejsu użytkownika

Następnie sprawdź, czy interfejs użytkownika odzwierciedla fakt, że jesteś zalogowany.

Użyjesz wywołania zwrotnego Listenera stanu uwierzytelniania Firebase, który jest powiadamiany o zmianie stanu logowania użytkownika. Jeśli jest zalogowany użytkownik, aplikacja zmieni przycisk „Odpowiedz” na przycisk „Wyloguj”.

  1. W StackBlitz otwórz plik index.js.
  2. U góry odszukaj instrukcję importu firebase/auth, a potem dodaj signOutonAuthStateChanged, tak jak tutaj:
    // ...
    // Add the Firebase products and methods that you want to use
    import {
      getAuth,
      EmailAuthProvider,
      signOut,
      onAuthStateChanged
    } from 'firebase/auth';
    
    import {} from 'firebase/firestore';
    
  3. Dodaj ten kod na dole funkcji main():
    async function main() {
      // ...
    
      // Listen to the current Auth state
      onAuthStateChanged(auth, user => {
        if (user) {
          startRsvpButton.textContent = 'LOGOUT';
        } else {
          startRsvpButton.textContent = 'RSVP';
        }
      });
    }
    main();
    
  4. W słuchaczu przycisku sprawdź, czy jest obecny użytkownik, i wyloguj go. Aby to zrobić, zastąp bieżący kod startRsvpButton.addEventListener tym:
    // ...
    // 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);
      }
    });
    

Przycisk w aplikacji powinien teraz wyświetlać tekst WYLOGUJ SIĘ, a po kliknięciu powinien zmienić się na ODPOWIEDZ.

Podgląd aplikacji

zrzut ekranu z tego kroku

7. Pisanie wiadomości do Cloud Firestore

Wiemy, że użytkownicy chętnie odwiedzają aplikację, ale warto dać gościom możliwość zrobienia w niej czegoś jeszcze. Może mogliby zostawiać wiadomości w księdze gości? Mogą powiedzieć, dlaczego się cieszą z przyjazdu lub kogo chcą spotkać.

Aby przechowywać wiadomości czatu, które użytkownicy piszą w aplikacji, użyjesz Cloud Firestore.

Model danych

Cloud Firestore to baza danych NoSQL, a dane w niej przechowywane są w kolekcjach, dokumentach, polach i podkolekcjach. Każdą wiadomość na czacie zapiszesz jako dokument w zbiorze najwyższego poziomu o nazwie guestbook.

Grafika modelu danych Firestore pokazująca kolekcję księgi gości z wieloma dokumentami z wiadomościami

Dodawanie wiadomości do Firestore

W tej sekcji dodasz funkcję umożliwiającą użytkownikom zapisywanie nowych wiadomości w bazie danych. Najpierw dodaj kod HTML elementów interfejsu (pole wiadomości i przycisk wysyłania). Następnie dodajesz kod, który łączy te elementy z bazą danych.

Aby dodać elementy interfejsu użytkownika pola wiadomości i przycisku wysyłania:

  1. W StackBlitz otwórz plik index.html.
  2. Odszukaj guestbook-container, a potem dodaj ten kod HTML, aby utworzyć formularz z polem do wpisywania wiadomości i przyciskiem wysyłania.
    <!-- ... -->
    
     <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>
    
    <!-- ... -->
    

Podgląd aplikacji

zrzut ekranu z tego kroku

Gdy użytkownik kliknie przycisk WYŚLIJ, zostanie uruchomiony podany niżej fragment kodu. Dodaje zawartość pola wejściowego wiadomości do kolekcji guestbook bazy danych. Konkretnie metoda addDoc dodaje treść wiadomości do nowego dokumentu (z automatycznie wygenerowanym identyfikatorem) w kolekcji guestbook.

  1. W StackBlitz otwórz plik index.js.
  2. U góry odszukaj instrukcję importu firebase/firestore, a następnie dodaj getFirestore, addDoc i collection w ten sposób:
    // ...
    
    // 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. Teraz zapisujemy odwołanie do obiektu Firestore db tuż po initializeApp:
    initializeApp(firebaseConfig);
    auth = getAuth();
    db = getFirestore();
    
  4. U dołu funkcji main() dodaj ten kod.

    Pamiętaj, że auth.currentUser.uid to odwołanie do automatycznie wygenerowanego unikalnego identyfikatora, który Uwierzytelnianie Firebase przypisuje wszystkim zalogowanym użytkownikom.
    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();
    

Pokaż księgę gości tylko zalogowanym użytkownikom

Nie chcesz, aby ktokolwiek mógł zobaczyć czat gości. Aby zabezpieczyć czat, możesz na przykład zezwolić na wyświetlanie księgi gości tylko zalogowanym użytkownikom. W przypadku własnych aplikacji musisz też zabezpieczyć bazę danych za pomocą reguł bezpieczeństwa Firebase. (więcej informacji o regułach zabezpieczeń znajdziesz w dalszej części tego ćwiczenia).

  1. W StackBlitz otwórz plik index.js.
  2. Zmień listenera onAuthStateChanged, aby ukryć lub wyświetlić księgę gości.
    // ...
    
    // 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';
      }
    });
    

Testowanie wysyłania wiadomości

  1. Zaloguj się w aplikacji.
  2. Wpisz wiadomość, np. „Cześć!”, a następnie kliknij WYŚLIJ.

To działanie zapisuje wiadomość w bazie danych Cloud Firestore. Nie zobaczysz jednak tego komunikatu w aplikacji internetowej, ponieważ musisz jeszcze zaimplementować pobieranie danych. W następnym kroku to zrobisz.

Możesz jednak zobaczyć nowo dodaną wiadomość w konsoli Firebase.

W konsoli Firebase, w panelu Baza danych Firestore, powinna się wyświetlić kolekcja guestbook z nowo dodanym komunikatem. Jeśli będziesz wysyłać więcej wiadomości, w Twojej kolekcji księgi gości znajdzie się wiele dokumentów, takich jak ten:

Konsola Firebase

zrzut ekranu z tego kroku

8. Czytanie wiadomości

Synchroniz wiadomości

To świetne, że goście mogą pisać wiadomości do bazy danych, ale nie mogą ich jeszcze zobaczyć w aplikacji.

Aby wyświetlać wiadomości, musisz dodać odbiorców, którzy będą reagować na zmiany danych, a potem utworzyć element interfejsu, który będzie wyświetlać nowe wiadomości.

Dodasz kod, który będzie nasłuchiwać nowo dodanych wiadomości z aplikacji. Najpierw dodaj sekcję w pliku HTML, aby wyświetlać wiadomości:

  1. W StackBlitz otwórz plik index.html.
  2. W pliku guestbook-container dodaj nową sekcję o identyfikatorze guestbook.
    <!-- ... -->
    
      <section id="guestbook-container">
       <h2>Discussion</h2>
    
       <form><!-- ... --></form>
    
       <section id="guestbook"></section>
    
     </section>
    
    <!-- ... -->
    

Następnie zarejestruj listenera, który będzie nasłuchiwać zmian w danych:

  1. W StackBlitz otwórz plik index.js.
  2. U góry odszukaj instrukcję importu firebase/firestore, a potem dodaj query, orderByonSnapshot w ten sposób:
    // ...
    import {
      getFirestore,
      addDoc,
      collection,
      query,
      orderBy,
      onSnapshot
    } from 'firebase/firestore';
    
  3. U dołu funkcji main() dodaj ten kod, aby przejść przez wszystkie dokumenty (wiadomości w księdze gości) w bazie danych. Aby dowiedzieć się więcej o tym, co dzieje się w tym kodzie, przeczytaj informacje pod fragmentem kodu.
    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();
    

Aby odsłuchać wiadomości w bazie danych, utworzysz zapytanie dotyczące konkretnej kolekcji za pomocą funkcji collection. Powyższy kod śledzi zmiany w kolekcji guestbook, w której są przechowywane wiadomości na czacie. Wiadomości są też sortowane według daty, a użycie orderBy('timestamp', 'desc') powoduje wyświetlanie najświeższych wiadomości u góry.

Funkcja onSnapshot przyjmuje 2 parametry: zapytanie do użycia i funkcję wywołania zwrotnego. Funkcja wywołania zwrotnego jest wywoływana, gdy w dokumentach, które pasują do zapytania, nastąpią jakiekolwiek zmiany. Może się tak zdarzyć, jeśli wiadomość zostanie usunięta, zmodyfikowana lub dodana. Więcej informacji znajdziesz w dokumentacji Cloud Firestore.

Testowanie synchronizacji wiadomości

Cloud Firestore automatycznie i natychmiast synchronizuje dane z klientami subskrybującym bazę danych.

  • Wiadomości utworzone wcześniej w bazie danych powinny być wyświetlane w aplikacji. Możesz też napisać nowe wiadomości, które powinny się pojawić natychmiast.
  • Jeśli otworzysz obszar roboczy w wielu oknach lub kartach, wiadomości będą synchronizowane w czasie rzeczywistym na wszystkich kartach.
  • (Opcjonalnie) Możesz ręcznie usuwać, modyfikować lub dodawać nowe wiadomości bezpośrednio w sekcji Baza danych w konsoli Firebase. Wszelkie zmiany powinny być widoczne w interfejsie.

Gratulacje! W aplikacji odczytujesz dokumenty Cloud Firestore.

Podgląd aplikacji

zrzut ekranu z tego kroku

9. Konfigurowanie podstawowych reguł zabezpieczeń

Cloud Firestore został początkowo skonfigurowany do używania trybu testowego, co oznacza, że baza danych jest otwarta na odczyty i zapisy. Tryb testowy należy jednak używać tylko na bardzo wczesnych etapach tworzenia. Najlepiej jest skonfigurować reguły bezpieczeństwa bazy danych podczas tworzenia aplikacji. Zabezpieczenia powinny być integralną częścią struktury i działania aplikacji.

Reguły zabezpieczeń umożliwiają kontrolowanie dostępu do dokumentów i kolekcji w bazie danych. Elastyczna składnia reguł umożliwia tworzenie reguł, które pasują do wszystkiego, od wszystkich zapisów w całej bazie danych po operacje na konkretnym dokumencie.

Reguły zabezpieczeń Cloud Firestore możesz pisać w konsoli Firebase:

  1. W sekcji Kompilowanie w konsoli Firebase kliknij Baza danych Firestore, a potem wybierz kartę Reguły (lub kliknij tutaj, aby przejść bezpośrednio do karty Reguły).
  2. Powinny się wyświetlić te domyślne reguły zabezpieczeń, które ograniczają dostęp do aplikacji przez kilka tygodni.

zrzut ekranu z tego kroku

Identyfikowanie kolekcji

Najpierw określ kolekcje, do których aplikacja zapisuje dane.

  1. Usuń istniejące zastrzeżenie match /{document=**}, aby Twoje reguły wyglądały tak:
    rules_version = '2';
    service cloud.firestore {
      match /databases/{database}/documents {
      }
    }
    
  2. W sekcji match /databases/{database}/documents zidentyfikuj kolekcję, którą chcesz zabezpieczyć:
    rules_version = '2';
    service cloud.firestore {
      match /databases/{database}/documents {
        match /guestbook/{entry} {
         // You'll add rules here in the next step.
      }
    }
    

Dodawanie reguł zabezpieczeń

Ponieważ w każdym dokumencie w księdze gości używasz identyfikatora uwierzytelniania jako pola, możesz pobrać ten identyfikator i sprawdzić, czy każda osoba, która próbuje zapisać w dokumencie, ma zgodny identyfikator uwierzytelniania.

  1. Dodaj reguły odczytu i zapisu do zestawu reguł, jak pokazano poniżej:
    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. Kliknij Opublikuj, aby wdrożyć nowe reguły.Teraz w księdze gości tylko zalogowani użytkownicy mogą czytać wiadomości (wszystkie wiadomości!), ale wiadomość może utworzyć tylko użytkownik, który ma swój identyfikator. Nie zezwalamy też na edytowanie ani usuwanie wiadomości.

Dodawanie reguł sprawdzania poprawności

  1. Dodaj walidację danych, aby upewnić się, że wszystkie oczekiwane pola są obecne w dokumencie:
    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. Aby wdrożyć nowe reguły, kliknij Opublikuj.

Resetowanie słuchaczy

Ponieważ Twoja aplikacja zezwala teraz na logowanie się tylko uwierzytelnionych użytkowników, zapytanie dotyczące księgi gości firestore należy przenieść do odbiornika uwierzytelniania. W przeciwnym razie wystąpią błędy uprawnień, a aplikacja zostanie rozłączona, gdy użytkownik się wyloguje.

  1. W StackBlitz otwórz plik index.js.
  2. Przeciągnij listenera kolekcji onSnapshot do nowej funkcji o nazwie subscribeGuestbook. Przypisz też wyniki funkcji onSnapshot do zmiennej guestbookListener.

    Detektor Firestore onSnapshot zwraca funkcję anulowania subskrypcji, której można użyć do anulowania detektora migawek.
    // ...
    // 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. Dodaj pod nią nową funkcję o nazwie unsubscribeGuestbook. Sprawdź, czy zmienna guestbookListener nie jest pusta, a potem wywołaj funkcję, aby anulować odbiornik.
    // ...
    // Unsubscribe from guestbook updates
    function unsubscribeGuestbook() {
      if (guestbookListener != null) {
        guestbookListener();
        guestbookListener = null;
      }
    }
    

Na koniec dodaj nowe funkcje do wywołania zwrotnego onAuthStateChanged.

  1. Dodaj subscribeGuestbook() na dole if (user).
  2. Dodaj unsubscribeGuestbook() na dole oświadczenia 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. Krok dodatkowy: ćwiczenie zdobytej wiedzy

Rejestrowanie stanu odpowiedzi na zaproszenie

Obecnie Twoja aplikacja pozwala użytkownikom na rozpoczęcie czatu tylko wtedy, gdy są zainteresowani wydarzeniem. Ponadto jedynym sposobem, aby dowiedzieć się, czy ktoś dołączy do rozmowy, jest sprawdzenie, czy ktoś o tym napisał w czacie. Zorganizujmy to i poinformujmy ludzi, ilu gości się spodziewamy.

Dodasz przełącznik, aby rejestrować osoby, które chcą wziąć udział w wydarzeniu, a następnie zliczać, ile osób się zgłasza.

  1. W StackBlitz otwórz plik index.html.
  2. guestbook-container dodaj zestaw przycisków TAKNIE, na przykład:
    <!-- ... -->
      <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>
    <!-- ... -->
    

Podgląd aplikacji

zrzut ekranu z tego kroku

Następnie zarejestruj odbiornik kliknięć przycisku. Jeśli użytkownik kliknie TAK, zapisz odpowiedź w bazie danych, korzystając z identyfikatora uwierzytelniania.

  1. W StackBlitz otwórz plik index.js.
  2. U góry odszukaj instrukcję importu firebase/firestore, a następnie dodaj doc, setDoc i where w ten sposób:
    // ...
    // 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. U dołu funkcji main() dodaj ten kod, aby sprawdzać stan odpowiedzi:
    async function main() {
      // ...
    
      // Listen to RSVP responses
      rsvpYes.onclick = async () => {
      };
      rsvpNo.onclick = async () => {
      };
    }
    main();
    
    
  4. Następnie utwórz nową kolekcję o nazwie attendees, a następnie zarejestruj odwołanie do dokumentu, jeśli kliknięty zostanie którykolwiek z przycisków RSVP. Ustaw to odwołanie jako true lub false w zależności od tego, który przycisk został kliknięty.

    Najpierw dla 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);
      }
    };
    
    Następnie to samo dla rsvpNo, ale z wartością 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);
      }
    };
    

Aktualizowanie reguł zabezpieczeń

Ponieważ masz już skonfigurowane pewne reguły, nowe dane, które dodajesz za pomocą przycisków, zostaną odrzucone.

Zezwalaj na dodawanie elementów do kolekcji attendees

Musisz zaktualizować reguły, aby zezwolić na dodawanie elementów do kolekcji attendees.

  1. W przypadku kolekcji attendees, ponieważ jako nazwę dokumentu użyto identyfikatora uwierzytelniania UID, możesz go pobrać i sprawdzić, czy uid nadawcy jest taki sam jak w dokumencie. Zezwalasz na odczytywanie listy uczestników przez wszystkich (ponieważ nie zawiera ona danych prywatnych), ale tylko twórca powinien mieć możliwość jej aktualizowania.
    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. Aby wdrożyć nowe reguły, kliknij Opublikuj.

Dodawanie reguł sprawdzania poprawności

  1. Dodaj reguły sprawdzania poprawności danych, aby mieć pewność, że wszystkie oczekiwane pola są obecne w dokumencie:
    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. Nie zapomnij kliknąć Opublikuj, aby wdrożyć reguły.

(Opcjonalnie) Teraz możesz wyświetlić wyniki kliknięcia przycisków. Otwórz panel Cloud Firestore w konsoli Firebase.

Czytanie stanu odpowiedzi

Teraz, gdy już masz nagrane odpowiedzi, sprawdź, kto się pojawi, i odzwierciedl to w interfejsie.

  1. W StackBlitz otwórz plik index.html.
  2. W description-container dodaj nowy element o identyfikatorze number-attending.
    <!-- ... -->
    
     <section id="description-container">
         <!-- ... -->
         <p id="number-attending"></p>
     </section>
    
    <!-- ... -->
    

Następnie zarejestruj listenera dla zbioru attendees i policz liczbę odpowiedzi TAK:

  1. W StackBlitz otwórz plik index.js.
  2. U dołu funkcji main() dodaj ten kod, aby sprawdzać stan odpowiedzi i zliczać kliknięcia TAK.
    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();
    

Na koniec wyróżnimy przycisk odpowiadający bieżącemu stanowi.

  1. Utwórz funkcję, która sprawdza, czy bieżący identyfikator UID uwierzytelniania ma wpis w zbiorze attendees, a potem ustaw klasę przycisku na 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. Stwórzmy też funkcję anulowania subskrypcji. Będzie on używany, gdy użytkownik się wyloguje.
    // ...
    function unsubscribeCurrentRSVP() {
      if (rsvpListener != null) {
        rsvpListener();
        rsvpListener = null;
      }
      rsvpYes.className = '';
      rsvpNo.className = '';
    }
    
  3. Wywołuj funkcje z słuchacza uwierzytelniania.
    // ...
    // 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. Spróbuj zalogować się jako kilku użytkowników i zobacz, jak liczba rośnie po każdym kliknięciu przycisku TAK.

Podgląd aplikacji

zrzut ekranu z tego kroku

11. Gratulacje!

Udało Ci się utworzyć interaktywną aplikację internetową działającą w czasie rzeczywistym za pomocą Firebase.

Omówione zagadnienia

  • Uwierzytelnianie Firebase
  • FirebaseUI
  • Cloud Firestore
  • Reguły zabezpieczeń Firebase

Dalsze kroki

  • Chcesz dowiedzieć się więcej o procesie tworzenia aplikacji w Firebase? Zapoznaj się z ćwiczeniem z emulatorem Firebase, aby dowiedzieć się, jak testować i uruchamiać aplikację całkowicie lokalnie.
  • Chcesz dowiedzieć się więcej o innych usługach Firebase? Może chcesz przechowywać pliki graficzne przesyłane przez użytkowników? Czy chcesz wysyłać powiadomienia do użytkowników? Zapoznaj się z Codelab dotyczącym Firebase dla internetu, aby dowiedzieć się więcej o tej usłudze.
  • Chcesz dowiedzieć się więcej o Cloud Firestore? A może chcesz dowiedzieć się więcej o podkolekcjach i transakcjach? Więcej informacji o Cloud Firestore znajdziesz w internetowym Codelab Cloud Firestore. Aby dowiedzieć się więcej o Cloud Firestore, obejrzyj tę serię filmów w YouTube.

Więcej informacji

Jak poszło?

Chętnie poznamy Twoją opinię. Wypełnij (bardzo) krótki formularz tutaj.