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.
Czego się nauczysz
- Uwierzytelniaj użytkowników za pomocą Uwierzytelniania Firebase i FirebaseUI.
- Synchronizuj dane przy użyciu Cloud Firestore.
- Zapis reguł zabezpieczeń Firebase w celu zabezpieczenia bazy danych.
Czego potrzebujesz
- wybraną przeglądarkę, na przykład 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. Pozwoli Ci to korzystać z funkcji zaawansowanych w StackBlitz.
- Przykładowy kod z ćwiczeń w Codelabs. Aby dowiedzieć się, jak uzyskać kod, przejdź do następnego kroku.
2. Pobierz kod początkowy
W ramach tego ćwiczenia w programie utworzysz aplikację za pomocą StackBlitz – edytora online ze zintegrowanym kilkoma przepływami pracy Firebase. Stackblitz nie wymaga instalacji oprogramowania ani specjalnego konta StackBlitz.
StackBlitz umożliwia udostępnianie projektów innym osobom. Inne osoby, które znają adres URL Twojego projektu StackBlitz, mogą zobaczyć Twój kod i utworzyć rozwidlenie projektu, ale nie mogą edytować Twojego projektu w StackBlitz.
- Aby uzyskać kod początkowy, otwórz ten adres URL: https://stackblitz.com/edit/firebase-gtk-web-start.
- U góry strony StackBlitz kliknij Fork:
Masz teraz kopię kodu początkowego jako Twój projekt StackBlitz, który ma unikalną nazwę i unikalny URL. Wszystkie Twoje pliki i zmiany są zapisywane w tym projekcie StackBlitz.
3. Edytuj informacje o zdarzeniu
Materiały początkowe do tego ćwiczenia w Codelabs pokazują strukturę aplikacji internetowej, w tym niektóre arkusze stylów i kilka kontenerów HTML na potrzeby aplikacji. W dalszej części tego ćwiczenia w Codelabs podłączysz kontenery do Firebase.
Na początek zapoznaj się z interfejsem StackBlitz.
- W StackBlitz otwórz plik
index.html
. - Odszukaj
event-details-container
idescription-container
, a następnie spróbuj edytować niektóre szczegóły wydarzenia.
Gdy edytujesz tekst, automatyczne ponowne załadowanie strony w StackBlitz spowoduje wyświetlenie szczegółów nowego wydarzenia. Fajne, tak?
<!-- ... -->
<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
4. Tworzenie i konfigurowanie projektu Firebase
Wyświetlanie informacji o wydarzeniu jest przydatne dla gości, ale samo wyświetlanie wydarzeń nie jest dla nikogo szczególnie 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
- Zaloguj się w Firebase.
- W konsoli Firebase kliknij Dodaj projekt (lub Utwórz projekt), a potem nazwij projekt Firebase Firebase-Web-Codelab.
- 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 Firebase i interfejs Firebase ułatwiające użytkownikom logowanie się w Twojej aplikacji.
- Cloud Firestore pozwala zapisywać uporządkowane dane w chmurze i otrzymywać natychmiastowe powiadomienia o zmianach danych.
- Reguły zabezpieczeń Firebase, które zabezpieczą 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-mail 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:
- W panelu po lewej stronie w konsoli Firebase kliknij Kompilacja > Uwierzytelnianie. Następnie kliknij Get Started (Rozpocznij). Jesteś teraz w panelu uwierzytelniania, w którym możesz zobaczyć zarejestrowanych użytkowników, skonfigurować dostawców logowania i zarządzać ustawieniami.
- Wybierz kartę Metoda logowania (lub kliknij tutaj, aby przejść bezpośrednio do tej karty).
- W opcjach dostawcy kliknij E-mail/hasło, przestaw przełącznik na Włącz, a następnie kliknij Zapisz.
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:
- W panelu po lewej stronie konsoli Firebase rozwiń Build (Kompilacja), a potem wybierz Firestore database (Baza danych Firestore).
- Kliknij Utwórz bazę danych.
- Pozostaw wartość
(default)
w polu Identyfikator bazy danych. - Wybierz lokalizację bazy danych i kliknij Dalej.
W przypadku prawdziwej aplikacji musisz wybrać lokalizację znajdującą się w pobliżu użytkowników. - 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. - Kliknij Utwórz.
5. Dodawanie i konfigurowanie Firebase
Po utworzeniu projektu Firebase i włączeniu niektórych usług musisz wskazać kodowi, że chcesz używać Firebase, i wskazać projekt Firebase, którego chcesz użyć.
Dodawanie bibliotek Firebase
Aby Twoja aplikacja mogła korzystać z Firebase, musisz dodać do niej biblioteki Firebase. Można to zrobić na kilka sposobów zgodnie z dokumentacją Firebase. Możesz na przykład dodać biblioteki z sieci CDN Google lub zainstalować je lokalnie za pomocą npm, a następnie spakować je w aplikacji, jeśli używasz Browserify.
StackBlitz automatycznie scala się w pakiety, więc możesz dodawać biblioteki Firebase za pomocą instrukcji importowania. 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.
Aby utworzyć tę aplikację, użyj 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 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';
Dodawanie aplikacji internetowej Firebase do projektu Firebase
- W konsoli Firebase otwórz stronę przeglądu projektu, klikając w lewym górnym rogu Przegląd projektu.
- W środku strony przeglądu projektu kliknij ikonę sieci , aby utworzyć nową aplikację internetową Firebase.
- Zarejestruj aplikację pod pseudonimem Web App (Aplikacja internetowa).
- W przypadku tego ćwiczenia w programie NIE zaznaczaj pola Add set up Firebase Hosting for this app (Skonfiguruj także Hosting Firebase dla tej aplikacji). Na razie użyjesz panelu podglądu StackBlitz.
- Kliknij Zarejestruj aplikację.
- Skopiuj obiekt konfiguracyjny Firebase do schowka.
- Kliknij Przejdź do konsoli.Dodaj do swojej aplikacji obiekt konfiguracji Firebase:
- Wróć do StackBlitz i otwórz plik
index.js
. - Znajdź wiersz komentarza
Add Firebase project configuration object here
i wklej fragment kodu konfiguracji tuż pod komentarzem. - Dodaj wywołanie funkcji
initializeApp
, aby skonfigurować Firebase, korzystając z unikalnej konfiguracji projektu Firebase.// ... // Add Firebase project configuration object here const firebaseConfig = { apiKey: "random-unique-string", authDomain: "your-projectId.firebaseapp.com", databaseURL: "https://your-projectId.firebaseio.com", projectId: "your-projectId", storageBucket: "your-projectId.firebasestorage.app", messagingSenderId: "random-unique-string", appId: "random-unique-string", }; // Initialize Firebase initializeApp(firebaseConfig);
6. Dodaj logowanie użytkownika (odpowiedź)
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 przez e-maila i interfejsu FirebaseUI
Musisz mieć przycisk odpowiedzi, który powoduje wyświetlenie prośby o zalogowanie się za pomocą adresu e-mail użytkownika. Możesz to zrobić, łącząc FirebaseUI z przyciskiem Odpowiedz.FirebaseUI to biblioteka, która oprócz uwierzytelnienia Firebase zawiera gotowy interfejs użytkownika.
FirebaseUI wymaga konfiguracji (patrz opcje w dokumentacji), która spełnia 2 czynności:
- 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 odświeżać strony, ponieważ tworzysz aplikację internetową zawierającą jedną stronę.
Dodaj kod do inicjowania FirebaseUI Auth
- W StackBlitz otwórz plik
index.js
. - Na górze znajdź instrukcję importowania
firebase/auth
, a następnie dodajgetAuth
iEmailAuthProvider
w następujący sposób:// ... // Add the Firebase products and methods that you want to use import { getAuth, EmailAuthProvider } from 'firebase/auth'; import {} from 'firebase/firestore';
- Zapisz odwołanie do obiektu auth tuż po
initializeApp
, np. w ten sposób:initializeApp(firebaseConfig); auth = getAuth();
- Zwróć uwagę, że konfiguracja FirebaseUI znajduje się już w kodzie początkowym. Dostawca uwierzytelniania poczty e-mail jest już skonfigurowany.
- Na dole funkcji
main()
windex.js
dodaj instrukcję inicjowania FirebaseUI w następujący sposób:async function main() { // ... // Initialize the FirebaseUI widget using Firebase const ui = new firebaseui.auth.AuthUI(auth); } main();
Dodawanie przycisku odpowiedzi do kodu HTML
- W StackBlitz otwórz plik
index.html
. - Dodaj kod HTML przycisku odpowiedzi w miejscu
event-details-container
, jak pokazano w przykładzie poniżej.
Pamiętaj, aby użyć tych samych wartościid
co poniżej, ponieważ na potrzeby tego ćwiczenia z programowania w plikuindex.js
znajdują się już punkty zaczepienia dla tych konkretnych identyfikatorów.
Pamiętaj, że w plikuindex.html
znajduje się kontener o identyfikatorzefirebaseui-auth-container
. Jest to identyfikator, który przekażesz do FirebaseUI w celu przechowywania danych logowania. Podgląd aplikacji<!-- ... --> <section id="event-details-container"> <!-- ... --> <!-- ADD THE RSVP BUTTON HERE --> <button id="startRsvp">RSVP</button> </section> <hr> <section id="firebaseui-auth-container"></section> <!-- ... -->
- Skonfiguruj odbiornik na przycisku Odpowiedz i wywołaj funkcję uruchamiania FirebaseUI. To powoduje, że FirebaseUI wyświetla okno logowania.
Dodaj ten kod na końcu funkcjimain()
windex.js
:async function main() { // ... // Listen to RSVP button clicks startRsvpButton.addEventListener("click", () => { ui.start("#firebaseui-auth-container", uiConfig); }); } main();
Testowanie logowania się w aplikacji
- 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 pojawi się komunikat o błędzie
auth/operation-not-allowed
lubThe given sign-in provider is disabled for this Firebase project
, sprawdź, czy w konsoli Firebase jest włączona opcja E-mail/hasło.
- Otwórz panel Uwierzytelnianie w konsoli Firebase. Na karcie Użytkownicy powinny być widoczne informacje o koncie podane podczas logowania się w aplikacji.
Dodawanie stanu uwierzytelniania do interfejsu użytkownika
Następnie sprawdź, czy interfejs użytkownika odzwierciedla fakt, że jesteś zalogowany.
Wykorzystasz wywołanie zwrotne detektora stanu Uwierzytelniania Firebase, które jest powiadamiane o każdej zmianie stanu logowania użytkownika. Jeśli jest zalogowany użytkownik, aplikacja zmieni przycisk „Odpowiedz” na przycisk „Wyloguj”.
- W StackBlitz otwórz plik
index.js
. - U góry odszukaj instrukcję importowania
firebase/auth
, a potem dodajsignOut
ionAuthStateChanged
w ten sposób:// ... // Add the Firebase products and methods that you want to use import { getAuth, EmailAuthProvider, signOut, onAuthStateChanged } from 'firebase/auth'; import {} from 'firebase/firestore';
- 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();
- W słuchaczu przycisku sprawdź, czy jest obecny użytkownik, i wyloguj go. Aby to zrobić, zastąp bieżącą wersję
startRsvpButton.addEventListener
następującym:// ... // 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Ę i po kliknięciu powinien zmienić się na ODPOWIEDZ.
Podgląd aplikacji
7. Pisanie wiadomości do Cloud Firestore
Wiemy, że użytkownicy chętnie odwiedzają aplikację, ale warto dać gościom coś innego do zrobienia. Może mogliby zostawiać wiadomości w księdze gości? Mogą wyjaśnić, dlaczego chcą wziąć udział w wydarzeniu lub kogo mają nadzieję spotkać.
Do przechowywania wiadomości czatu, które użytkownicy piszą w aplikacji, będziesz używać Cloud Firestore.
Model danych
Cloud Firestore to baza danych NoSQL, a dane w niej przechowywane są podzielone na kolekcje, dokumenty, pola i podkolekcje. Każdą wiadomość na czacie będziesz przechowywać jako dokument w zbiorze najwyższego poziomu o nazwie guestbook
.
Dodawanie wiadomości do Firestore
W tej sekcji dodasz funkcję umożliwiającą użytkownikom zapisywanie nowych wiadomości w bazie danych. Najpierw dodajesz 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:
- W StackBlitz otwórz plik
index.html
. - Odszukaj element
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
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. W szczególności metoda addDoc
dodaje treść wiadomości do nowego dokumentu (z automatycznie generowanym identyfikatorem) do kolekcji guestbook
.
- W StackBlitz otwórz plik
index.js
. - Na górze znajdź instrukcję importowania
firebase/firestore
, a następnie dodajgetFirestore
,addDoc
icollection
w następujący 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';
- Teraz zapiszemy odwołanie do obiektu
db
Firestore zaraz poinitializeApp
:initializeApp(firebaseConfig); auth = getAuth(); db = getFirestore();
- U dołu funkcji
main()
dodaj ten kod.
Pamiętaj, żeauth.currentUser.uid
odnosi się 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();
Pokazuj księgę gości tylko zalogowanym użytkownikom
Nie chcesz, aby ktokolwiek mógł zobaczyć czat gości. Jedną z opcji, które możesz zrobić, aby zabezpieczyć czat, jest zezwolenie 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 ćwiczeń z programowania.
- W StackBlitz otwórz plik
index.js
. - Zmień listenera
onAuthStateChanged
, aby ukryć lub wyświetlić książkę 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
- Zaloguj się w aplikacji.
- Wpisz wiadomość, np. „Cześć!”, a potem kliknij WYŚLIJ.
To działanie zapisuje wiadomość w bazie danych Cloud Firestore. Nie zobaczysz jednak tej wiadomości w aplikacji internetowej, ponieważ musisz jeszcze zaimplementować pobieranie danych. Zrobisz to w następnej kolejności.
Możesz jednak zobaczyć nowo dodaną wiadomość w konsoli Firebase.
W konsoli Firebase, w panelu Baza danych Firestore powinna być widoczna kolekcja guestbook
z nowo dodaną wiadomością. Jeśli nadal będziesz wysyłać wiadomości, kolekcja księgi gości będzie zawierać wiele dokumentów, na przykład:
Konsola Firebase
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, w której będą wyświetlane wiadomości:
- W StackBlitz otwórz plik
index.html
. - W pliku
guestbook-container
dodaj nową sekcję o identyfikatorzeguestbook
.<!-- ... --> <section id="guestbook-container"> <h2>Discussion</h2> <form><!-- ... --></form> <section id="guestbook"></section> </section> <!-- ... -->
Następnie zarejestruj detektor, który nasłuchuje zmian wprowadzonych w danych:
- W StackBlitz otwórz plik
index.js
. - Na górze znajdź instrukcję importowania
firebase/firestore
, a następnie dodajquery
,orderBy
ionSnapshot
w następujący sposób:// ... import { getFirestore, addDoc, collection, query, orderBy, onSnapshot } from 'firebase/firestore';
- Na dole funkcji
main()
dodaj poniższy kod, aby przewijać wszystkie dokumenty (wiadomości księgi 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 nasłuchuje zmian w kolekcji guestbook
, w której są przechowywane wiadomości czatu. Wiadomości są też sortowane według daty, a użycie orderBy('timestamp', 'desc')
powoduje wyświetlenie na górze najnowszych wiadomości.
Funkcja onSnapshot
przyjmuje 2 parametry: zapytanie i funkcję wywołania zwrotnego. Funkcja wywołania zwrotnego jest wyzwalana po wprowadzeniu jakichkolwiek zmian w dokumentach, które pasują do zapytania. Może się tak zdarzyć, gdy 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ż pisać nowe wiadomości, które powinny pojawiać się natychmiast.
- Jeśli otworzysz obszar roboczy w wielu oknach lub kartach, wiadomości będą synchronizowane w czasie rzeczywistym między kartami.
- (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! Odczytujesz dokumenty z Cloud Firestore w swojej aplikacji.
Podgląd aplikacji
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. Z trybu testowego należy jednak korzystać tylko na bardzo wczesnych etapach programowania. 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ń pozwalają kontrolować dostęp do dokumentów i kolekcji w bazie danych. Elastyczna składnia reguł umożliwia tworzenie reguł, które dopasowują wszystko – od wszystkich zapisów przez całą bazę danych po operacje na określonym dokumencie.
Reguły zabezpieczeń dla Cloud Firestore możesz napisać w konsoli Firebase:
- W sekcji Tworzenie konsoli Firebase kliknij Firestore Database (Baza danych Firestore), a następnie wybierz kartę Rules (Reguły) (lub kliknij tutaj, aby przejść bezpośrednio do karty Reguły).
- Powinny się wyświetlić te domyślne reguły zabezpieczeń, które ograniczają dostęp do aplikacji przez kilka tygodni.
Rozpoznawanie kolekcji
Najpierw określ kolekcje, do których aplikacja zapisuje dane.
- Usuń istniejącą klauzulę
match /{document=**}
, aby Twoje reguły wyglądały tak:rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { } }
- W narzędziu
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ń
W każdym dokumencie w księdze gości używasz identyfikatora UID uwierzytelniania, więc możesz go pobrać i sprawdzić, czy każdy, kto próbuje zapisać w nim dane, ma zgodny identyfikator UID uwierzytelniania.
- 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; } } }
- Kliknij Opublikuj, aby wdrożyć nowe reguły.Teraz w przypadku księgi gości tylko zalogowani użytkownicy mogą czytać wiadomości (dowolne wiadomości), ale możesz utworzyć wiadomość tylko przy użyciu swojego identyfikatora użytkownika. Nie zezwalamy też na edytowanie ani usuwanie wiadomości.
Dodawanie reguł weryfikacji
- Dodaj walidację danych, aby mieć pewność, że w dokumencie znajdują się wszystkie oczekiwane pola:
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; } } }
- Aby wdrożyć nowe reguły, kliknij Opublikuj.
Resetowanie detektorów
Twoja aplikacja umożliwia teraz logowanie się tylko uwierzytelnionym użytkownikom, dlatego należy przenieść zapytanie firestore
księgi gości do detektora uwierzytelniania. W przeciwnym razie wystąpią błędy uprawnień, a aplikacja zostanie odłączona, gdy użytkownik się wyloguje.
- W StackBlitz otwórz plik
index.js
. - Pobierz detektor
onSnapshot
kolekcji księgi gości do nowej funkcji o nazwiesubscribeGuestbook
. Przypisz też wyniki funkcjionSnapshot
do zmiennejguestbookListener
.
DetektoronSnapshot
Firestore zwraca funkcję anulowania subskrypcji, której będzie można później użyć do anulowania detektora zrzutów.// ... // 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); }); }); }
- Dodaj pod nią nową funkcję o nazwie
unsubscribeGuestbook
. Sprawdź, czy zmiennaguestbookListener
nie ma wartości null, a następnie wywołaj funkcję, by anulować detektor.// ... // Unsubscribe from guestbook updates function unsubscribeGuestbook() { if (guestbookListener != null) { guestbookListener(); guestbookListener = null; } }
Na koniec dodaj nowe funkcje do wywołania zwrotnego onAuthStateChanged
.
- Dodaj
subscribeGuestbook()
na doleif (user)
. - Dodaj
unsubscribeGuestbook()
na dole instrukcjielse
.// ... // 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. Dodatkowy krok: ćwicz zdobytą wiedzę w praktyce
Nagrywanie stanu odpowiedzi uczestnika
Obecnie Twoja aplikacja umożliwia tylko rozpoczęcie rozmowy przez osoby zainteresowane wydarzeniem. O przyjeździe można się dowiedzieć tylko, gdy ktoś opublikuje tę wiadomość na czacie. Zorganizujmy się i powiadommy, ile osób weźmie udział.
Dodasz przełącznik, aby rejestrować osoby, które chcą wziąć udział w wydarzeniu, a następnie zliczać, ile osób się zgłasza.
- W StackBlitz otwórz plik
index.html
. - W
guestbook-container
dodaj zestaw przycisków TAK i NIE, np. w ten sposób:<!-- ... --> <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
Następnie zarejestruj odbiornik kliknięć przycisku. Jeśli użytkownik kliknie TAK, zapisz odpowiedź w bazie danych, korzystając z identyfikatora uwierzytelniania.
- W StackBlitz otwórz plik
index.js
. - U góry odszukaj instrukcję importu
firebase/firestore
, a potem dodajdoc
,setDoc
iwhere
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';
- Na dole funkcji
main()
dodaj ten kod, aby nasłuchiwać stanu odpowiedzi:async function main() { // ... // Listen to RSVP responses rsvpYes.onclick = async () => { }; rsvpNo.onclick = async () => { }; } main();
- Następnie utwórz nową kolekcję o nazwie
attendees
, a potem zarejestruj odniesienie do dokumentu po kliknięciu dowolnego przycisku odpowiedzi. Ustaw to odwołanie jakotrue
lubfalse
w zależności od tego, który przycisk został kliknięty.
Najpierw, w domeniersvpYes
: Następnie te same ustawienia dla elementu// ... // 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
, 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 dodawane za pomocą przycisków zostaną odrzucone.
Zezwalanie na dodawanie elementów do kolekcji attendees
Musisz zaktualizować reguły, aby zezwolić na dodawanie elementów do kolekcji attendees
.
- W przypadku kolekcji
attendees
, ponieważ jako nazwę dokumentu użyto identyfikatora uwierzytelniania UID, możesz go pobrać i sprawdzić, czyuid
nadawcy jest taki sam jak w dokumencie. Zezwalasz wszystkim na czytanie listy uczestników (ponieważ nie ma tam danych prywatnych), ale tylko twórca powinien mieć możliwość aktualizowania listy.rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { // ... // match /attendees/{userId} { allow read: if true; allow write: if request.auth.uid == userId; } } }
- Aby wdrożyć nowe reguły, kliknij Opublikuj.
Dodawanie reguł sprawdzania poprawności
- 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; } } }
- 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.
Odczytywanie stanu odpowiedzi
Teraz, gdy już masz nagrane odpowiedzi, sprawdźmy, kto będzie uczestniczyć w spotkaniu i jak to będzie widoczne w interfejsie.
- W StackBlitz otwórz plik
index.html
. - W
description-container
dodaj nowy element o identyfikatorzenumber-attending
.<!-- ... --> <section id="description-container"> <!-- ... --> <p id="number-attending"></p> </section> <!-- ... -->
Następnie zarejestruj detektor kolekcji attendees
i policz liczbę odpowiedzi TAK:
- W StackBlitz otwórz plik
index.js
. - U dołu funkcji
main()
dodaj ten kod, aby sprawdzać stan odpowiedzi na zaproszenie 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 zaznaczmy przycisk odpowiadający aktualnemu stanowi.
- Utwórz funkcję, która sprawdza, czy bieżący identyfikator UID uwierzytelniania zawiera wpis w kolekcji
attendees
, a następnie ustaw klasę przycisku naclicked
.// ... // 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'; } } }); }
- Utwórzmy też funkcję anulowania subskrypcji. Ta nazwa będzie używana, gdy użytkownik się wyloguje.
// ... function unsubscribeCurrentRSVP() { if (rsvpListener != null) { rsvpListener(); rsvpListener = null; } rsvpYes.className = ''; rsvpNo.className = ''; }
- Wywołaj funkcje z detektora 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(); } });
- 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
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 przepływie pracy programistów w Firebase? Zapoznaj się z ćwiczeniem z programowania w narzędziu emulator Firebase, aby dowiedzieć się, jak przetestować i całkowicie uruchomić aplikację lokalnie.
- Chcesz dowiedzieć się więcej o innych usługach Firebase? A może chcesz przechowywać pliki graficzne przesłane przez użytkowników? Czy chcesz wysyłać powiadomienia do użytkowników? Zapoznaj się z internetowymi ćwiczeniami z programowania Firebase. Znajdziesz w nich więcej informacji o wielu innych usługach internetowych Firebase.
- Chcesz dowiedzieć się więcej o Cloud Firestore? A może chcesz dowiedzieć się więcej o podkolekcjach i transakcjach? Przejdź do internetowych ćwiczeń z programowania w Cloud Firestore, gdzie znajdziesz więcej informacji o Cloud Firestore. Aby dowiedzieć się więcej o Cloud Firestore, obejrzyj tę serię filmów w YouTube.
Więcej informacji
- Witryna Firebase: firebase.google.com
- Kanał Firebase w YouTube
Jak poszło?
Chętnie poznamy Twoją opinię. Wypełnij (bardzo) krótki formularz tutaj.