Ćwiczenie z programowania w Firebase Angular Web Frameworks

1. Co utworzysz

W tym ćwiczeniu z programowania utworzysz blog podróżniczy z mapą do współpracy w czasie rzeczywistym, korzystając z najnowszych funkcji naszej biblioteki Angular: AngularFire. Gotowa aplikacja internetowa będzie blogiem podróżniczym, na którym możesz przesyłać zdjęcia z każdego odwiedzonego miejsca.

Do tworzenia aplikacji internetowej użyjemy AngularFire, do testowania lokalnego – Pakietu emulatorów, do śledzenia danych użytkowników – Uwierzytelniania, do przechowywania danych i multimediów – Firestore i Storage (zasilanych przez Cloud Functions), a do wdrażania aplikacji – Hostingu Firebase.

Czego się nauczysz

  • Jak lokalnie tworzyć aplikacje z użyciem usług Firebase za pomocą Pakietu emulatorów
  • Jak ulepszyć aplikację internetową za pomocą AngularFire
  • Jak utrwalać dane w Firestore
  • Jak trwale przechowywać multimedia w usłudze Storage
  • Jak wdrożyć aplikację w Hostingu Firebase
  • Jak używać Cloud Functions do interakcji z bazami danych i interfejsami API

Czego potrzebujesz

  • Node.js w wersji 10 lub nowszej
  • konto Google do tworzenia projektu Firebase i zarządzania nim;
  • Wiersz poleceń Firebase w wersji 11.14.2 lub nowszej
  • wybraną przeglądarkę, np. Chrome;
  • Podstawowa znajomość Angulara i JavaScriptu

2. Pobieranie przykładowego kodu

Sklonuj repozytorium GitHub z poziomu wiersza poleceń:

git clone https://github.com/firebase/codelab-friendlychat-web

Jeśli nie masz zainstalowanego narzędzia git, możesz pobrać repozytorium jako plik ZIP.

Repozytorium GitHub zawiera przykładowe projekty na różne platformy.

W tym laboratorium kodu używamy tylko repozytorium webframework:

  • 📁 webframework: kod początkowy, na którym będziesz pracować w tym ćwiczeniu.

Instalowanie zależności

Po sklonowaniu zainstaluj zależności w folderze głównym i functions przed skompilowaniem aplikacji internetowej.

cd webframework && npm install
cd functions && npm install

Zainstaluj wiersz poleceń Firebase

Zainstaluj wiersz poleceń Firebase, wpisując w terminalu to polecenie:

npm install -g firebase-tools

Sprawdź, czy wersja wiersza poleceń Firebase jest nowsza niż 11.14.2, używając tego polecenia:

firebase  --version

Jeśli Twoja wersja jest starsza niż 11.14.2, zaktualizuj ją, wykonując te czynności:

npm update firebase-tools

3. Tworzenie i konfigurowanie projektu Firebase

Tworzenie projektu Firebase

  1. Zaloguj się w konsoli Firebase, korzystając ze swojego konta Google.
  2. Kliknij przycisk, aby utworzyć nowy projekt, a potem wpisz jego nazwę (np. FriendlyChat).
  3. Kliknij Dalej.
  4. Po wyświetleniu monitu przeczytaj i zaakceptuj warunki usługi Firebase, a potem kliknij Dalej.
  5. (Opcjonalnie) Włącz w konsoli Firebase pomoc AI (nazywaną „Gemini w Firebase”).
  6. W tym samouczku nie potrzebujesz Google Analytics, więc wyłącz opcję Google Analytics.
  7. Kliknij Utwórz projekt, poczekaj, aż projekt zostanie udostępniony, a następnie kliknij Dalej.

Dodawanie aplikacji internetowej Firebase do projektu

  1. Kliknij ikonę internetu, aby utworzyć nową aplikację internetową Firebase.
  2. W następnym kroku zobaczysz obiekt konfiguracji. Skopiuj zawartość tego obiektu do pliku environments/environment.ts.

Konfigurowanie usług Firebase

Aplikacja, którą zamierzamy utworzyć, korzysta z usług Firebase dostępnych w przypadku aplikacji internetowych:

  • Uwierzytelnianie Firebase, aby umożliwić użytkownikom łatwe logowanie się w aplikacji.
  • Cloud Firestore – zapisywanie danych strukturalnych w chmurze i otrzymywanie natychmiastowych powiadomień o zmianach danych.
  • Cloud Storage dla Firebase do zapisywania plików w chmurze.
  • Hosting Firebase do hostowania i obsługi zasobów.
  • Funkcje do interakcji z wewnętrznymi i zewnętrznymi interfejsami API.

Niektóre z tych usług wymagają specjalnej konfiguracji lub włączenia w konsoli Firebase.

Włącz logowanie przez Google w usłudze Uwierzytelnianie Firebase

Aby umożliwić użytkownikom logowanie się w aplikacji internetowej za pomocą kont Google, użyjemy metody logowania Google.

Aby włączyć logowanie się za pomocą Google:

  1. W konsoli Firebase w panelu po lewej stronie znajdź sekcję Kompilacja.
  2. Kliknij Uwierzytelnianie, a następnie kartę Metoda logowania (lub kliknij tutaj, aby przejść bezpośrednio do tej karty).
  3. Włącz dostawcę logowania Google, a następnie kliknij Zapisz.
  4. Ustaw publiczną nazwę aplikacji na <your-project-name> i wybierz adres e-mail pomocy dotyczącej projektu z menu.

Włącz Cloud Firestore

  1. W sekcji Kompilacja w konsoli Firebase kliknij Baza danych Firestore.
  2. W panelu Cloud Firestore kliknij Utwórz bazę danych.
  3. Ustaw lokalizację, w której będą przechowywane dane Cloud Firestore. Możesz pozostawić ustawienie domyślne lub wybrać region znajdujący się w pobliżu.

Włączanie Cloud Storage

Aplikacja internetowa używa Cloud Storage dla Firebase do przechowywania, przesyłania i udostępniania zdjęć.

  1. W sekcji Kompilacja w konsoli Firebase kliknij Storage.
  2. Jeśli nie widzisz przycisku Rozpocznij, oznacza to, że Cloud Storage jest już

jest włączona i nie musisz wykonywać czynności opisanych poniżej.

  1. Kliknij Rozpocznij.
  2. Przeczytaj wyłączenie odpowiedzialności dotyczące reguł zabezpieczeń projektu Firebase, a potem kliknij Dalej.
  3. Lokalizacja Cloud Storage jest wstępnie wybrana w tym samym regionie, który został wybrany dla bazy danych Cloud Firestore. Aby zakończyć konfigurację, kliknij Gotowe.

Domyślne reguły bezpieczeństwa zezwalają każdemu uwierzytelnionemu użytkownikowi na zapisywanie dowolnych danych w Cloud Storage. W dalszej części tego laboratorium kodowania zwiększymy bezpieczeństwo pamięci.

4. Łączenie z projektem Firebase

Interfejs wiersza poleceń Firebase umożliwia korzystanie z Hostingu Firebase do lokalnego udostępniania aplikacji internetowej, a także wdrażanie aplikacji internetowej w projekcie Firebase.

Sprawdź, czy wiersz poleceń ma dostęp do lokalnego katalogu webframework aplikacji.

Połącz kod aplikacji internetowej z projektem Firebase. Najpierw zaloguj się w wierszu poleceń Firebase:

firebase login

Następnie uruchom to polecenie, aby utworzyć alias projektu. Zastąp $YOUR_PROJECT_ID identyfikatorem projektu Firebase.

firebase  use  $YOUR_PROJECT_ID

Dodawanie AngularFire

Aby dodać AngularFire do aplikacji, uruchom to polecenie:

ng add @angular/fire

Następnie postępuj zgodnie z instrukcjami wiersza poleceń i wybierz funkcje, które są dostępne w Twoim projekcie Firebase.

Inicjowanie Firebase

Aby zainicjować projekt Firebase, uruchom to polecenie:

firebase init

Następnie, postępując zgodnie z instrukcjami w wierszu poleceń, wybierz funkcje i emulatory używane w projekcie Firebase.

Uruchamianie emulatorów

Z poziomu katalogu webframework uruchom to polecenie, aby uruchomić emulatory:

firebase  emulators:start

W końcu zobaczysz coś takiego:

$  firebase  emulators:start

i  emulators:  Starting  emulators:  auth,  functions,  firestore,  hosting,  functions

i  firestore:  Firestore  Emulator  logging  to  firestore-debug.log

i  hosting:  Serving  hosting  files  from:  public

  hosting:  Local  server:  http://localhost:5000

i  ui:  Emulator  UI  logging  to  ui-debug.log

i  functions:  Watching  "/functions"  for  Cloud  Functions...

  functions[updateMap]:  firestore  function  initialized.

  

┌─────────────────────────────────────────────────────────────┐

    All  emulators  ready!  It  is  now  safe  to  connect  your  app.  

  i  View  Emulator  UI  at  http://localhost:4000  

└─────────────────────────────────────────────────────────────┘

  

┌────────────────┬────────────────┬─────────────────────────────────┐

  Emulator    Host:Port    View  in  Emulator  UI  

├────────────────┼────────────────┼─────────────────────────────────┤

  Authentication    localhost:9099    http://localhost:4000/auth  

├────────────────┼────────────────┼─────────────────────────────────┤

  Functions    localhost:5001    http://localhost:4000/functions  

├────────────────┼────────────────┼─────────────────────────────────┤

  Firestore    localhost:8080    http://localhost:4000/firestore  

├────────────────┼────────────────┼─────────────────────────────────┤

  Hosting    localhost:5000    n/a  

└────────────────┴────────────────┴─────────────────────────────────┘

Emulator  Hub  running  at  localhost:4400

Other  reserved  ports:  4500

  

Issues?  Report  them  at  https://github.com/firebase/firebase-tools/issues  and  attach  the  *-debug.log  files.

Gdy zobaczysz komunikat ✔All emulators ready!, emulatory będą gotowe do użycia.

Powinien pojawić się interfejs aplikacji podróżniczej, który (jeszcze!) nie działa:

Zaczynajmy!

5. Połącz aplikację internetową z emulatorami

Z tabeli w logach emulatora wynika, że emulator Cloud Firestore nasłuchuje na porcie 8080, a emulator uwierzytelniania na porcie 9099.

Otwieranie interfejsu EmulatorUI

W przeglądarce otwórz http://127.0.0.1:4000/. Powinien pojawić się interfejs Pakietu emulatorów.

Kierowanie aplikacji do korzystania z emulatorów

W pliku src/app/app.module.ts dodaj ten kod do listy instrukcji importu w pliku AppModule:

@NgModule({
	declarations: [...],
	imports: [
		provideFirebaseApp(() =>  initializeApp(environment.firebase)),

		provideAuth(() => {
			const  auth = getAuth();
			if (location.hostname === 'localhost') {
				connectAuthEmulator(auth, 'http://127.0.0.1:9099', { disableWarnings:  true });
			}
			return  auth;
		}),

		provideFirestore(() => {
			const  firestore = getFirestore();
			if (location.hostname === 'localhost') {
				connectFirestoreEmulator(firestore, '127.0.0.1', 8080);
			}
			return  firestore;
		}),

		provideFunctions(() => {
			const  functions = getFunctions();
			if (location.hostname === 'localhost') {
				connectFunctionsEmulator(functions, '127.0.0.1', 5001);
			}
			return  functions;
		}),

		provideStorage(() => {
			const  storage = getStorage();
			if (location.hostname === 'localhost') {
				connectStorageEmulator(storage, '127.0.0.1', 5001);
			}
			return  storage;
		}),
		...
	]

Aplikacja jest teraz skonfigurowana do korzystania z lokalnych emulatorów, co umożliwia lokalne testowanie i programowanie.

6. Dodawanie uwierzytelniania

Teraz, gdy emulatory są skonfigurowane dla aplikacji, możemy dodać funkcje uwierzytelniania, aby mieć pewność, że każdy użytkownik jest zalogowany przed opublikowaniem wiadomości.

Aby to zrobić, możemy zaimportować funkcje signin bezpośrednio z AngularFire i śledzić stan uwierzytelniania użytkownika za pomocą funkcji authState. Zmodyfikuj funkcje strony logowania, aby przy wczytywaniu sprawdzała stan uwierzytelniania użytkownika.

Wstrzykiwanie uwierzytelniania AngularFire

W usłudze src/app/pages/login-page/login-page.component.ts zaimportuj Auth z usługi @angular/fire/auth i wstaw go do LoginPageComponent. Dostawców uwierzytelniania, takich jak Google, oraz funkcje, takie jaksignin, signout, można też bezpośrednio importować z tego samego pakietu i używać w aplikacji.

import { Auth, GoogleAuthProvider, signInWithPopup, signOut, user } from  '@angular/fire/auth';

export  class  LoginPageComponent  implements  OnInit {
	private  auth: Auth = inject(Auth);
	private  provider = new  GoogleAuthProvider();
	user$ = user(this.auth);
	constructor() {}  

	ngOnInit(): void {} 

	login() {
		signInWithPopup(this.auth, this.provider).then((result) => {
			const  credential = GoogleAuthProvider.credentialFromResult(result);
			return  credential;
		})
	}

	logout() {
		signOut(this.auth).then(() => {
			console.log('signed out');}).catch((error) => {
				console.log('sign out error: ' + error);
		})
	}
}

Strona logowania jest już funkcjonalna. Spróbuj się zalogować i sprawdź wyniki w emulatorze uwierzytelniania.

7. Konfigurowanie Firestore

W tym kroku dodasz funkcję publikowania i aktualizowania postów na blogu podróżniczym przechowywanych w Firestore.

Podobnie jak w przypadku uwierzytelniania, funkcje Firestore są dostarczane w pakiecie z AngularFire. Każdy dokument należy do kolekcji i może mieć też kolekcje zagnieżdżone. Znajomość path dokumentu w Firestore jest wymagana do tworzenia i aktualizowania postu na blogu podróżniczym.

Implementowanie usługi TravelService

W aplikacji internetowej wiele różnych stron będzie musiało odczytywać i aktualizować dokumenty Firestore, dlatego możemy zaimplementować funkcje w src/app/services/travel.service.ts, aby uniknąć wielokrotnego wstrzykiwania tych samych funkcji AngularFire na każdej stronie.

Zacznij od wstrzyknięcia Auth, podobnie jak w poprzednim kroku, a także Firestore do naszej usługi. Przydatne jest też zdefiniowanie obiektu obserwowalnego user$, który nasłuchuje bieżącego stanu uwierzytelniania.

import { doc, docData, DocumentReference, Firestore, getDoc, setDoc, updateDoc, collection, addDoc, deleteDoc, collectionData, Timestamp } from  "@angular/fire/firestore";

export  class  TravelService {
	firestore: Firestore = inject(Firestore);
	auth: Auth = inject(Auth);
	user$ = authState(this.auth).pipe(filter(user  =>  user !== null), map(user  =>  user!));
	router: Router = inject(Router);

Dodawanie posta o podróży

Posty o podróżach będą przechowywane w Firestore jako dokumenty. Dokumenty muszą znajdować się w kolekcjach, więc kolekcja zawierająca wszystkie posty o podróżach będzie nosić nazwę travels. Ścieżka każdego posta o tematyce podróżniczej będzie więc wyglądać tak: travels/

Za pomocą funkcji addDoc z AngularFire można wstawić obiekt do kolekcji:

async  addEmptyTravel(userId: String) {
	...
	addDoc(collection(this.firestore, 'travels'), travelData).then((travelRef) => {
		collection(this.firestore, `travels/${travelRef.id}/stops`);
		setDoc(travelRef, {... travelData, id:  travelRef.id})
		this.router.navigate(['edit', `${travelRef.id}`]);
		return  travelRef;

	})
}

Aktualizowanie i usuwanie danych

Znając identyfikator UID dowolnego posta o podróżach, można wywnioskować ścieżkę dokumentu przechowywanego w Firestore, który można następnie odczytać, zaktualizować lub usunąć za pomocą funkcji updateFocdeleteDoc AngularFire:

async  updateData(path: string, data: Partial<Travel | Stop>) {
	await  updateDoc(doc(this.firestore, path), data)
}

async  deleteData(path: string) {
	const  ref = doc(this.firestore, path);
	await  deleteDoc(ref)
}

Odczytywanie danych jako obiektu obserwowalnego

Posty z podróży i przystanki po drodze można modyfikować po utworzeniu, dlatego bardziej przydatne byłoby otrzymywanie obiektów dokumentów jako obiektów obserwowalnych, aby subskrybować wszelkie wprowadzane zmiany. Ta funkcja jest oferowana przez funkcje docDatacollectionData@angular/fire/firestore.

getDocData(path: string) {
	return  docData(doc(this.firestore, path), {idField:  'id'}) as  Observable<Travel | Stop>
}

  
getCollectionData(path: string) {
	return  collectionData(collection(this.firestore, path), {idField:  'id'}) as  Observable<Travel[] | Stop[]>
}

Dodawanie przystanków do posta o podróży

Po skonfigurowaniu operacji na postach o podróżach czas pomyśleć o przystankach, które będą znajdować się w podkolekcji postu o podróżach, np. tak: travels//stops/

Jest to niemal identyczne z tworzeniem posta o podróżach, więc spróbuj samodzielnie wdrożyć tę funkcję lub zapoznaj się z poniższym opisem:

async  addStop(travelId: string) {
	...
	const  ref = await  addDoc(collection(this.firestore, `travels/${travelId}/stops`), stopData)
	setDoc(ref, {...stopData, id:  ref.id})
}

Świetnie! Funkcje Firestore zostały zaimplementowane w usłudze Travel, więc możesz teraz zobaczyć, jak działają.

Używanie funkcji Firestore w aplikacji

Otwórz src/app/pages/my-travels/my-travels.component.ts i wstaw TravelService, aby korzystać z jego funkcji.

travelService = inject(TravelService);
travelsData$: Observable<Travel[]>;
stopsList$!: Observable<Stop[]>;
constructor() {
	this.travelsData$ = this.travelService.getCollectionData(`travels`) as  Observable<Travel[]>
}

Metoda TravelService jest wywoływana w konstruktorze, aby uzyskać tablicę Observable wszystkich podróży.

Jeśli potrzebne są tylko podróże bieżącego użytkownika, użyj query funkcji.

Inne metody zapewniania bezpieczeństwa to wdrożenie reguł zabezpieczeń lub używanie Cloud Functions z Firestore, jak opisano w opcjonalnych krokach poniżej.

Następnie po prostu wywołaj funkcje zaimplementowane w TravelService.

async  createTravel(userId: String) {
	this.travelService.addEmptyTravel(userId);
}

deleteTravel(travelId: String) {
	this.travelService.deleteData(`travels/${travelId}`)
}

Strona Moje podróże powinna teraz działać. Sprawdź, co się dzieje w emulatorze Firestore, gdy tworzysz nowy post o podróżach.

Następnie powtórz te czynności w przypadku funkcji aktualizacji w /src/app/pages/edit-travels/edit-travels.component.ts :

travelService: TravelService = inject(TravelService)
travelId = this.activatedRoute.snapshot.paramMap.get('travelId');
travelData$: Observable<Travel>;
stopsData$: Observable<Stop[]>;

constructor() {
	this.travelData$ = this.travelService.getDocData(`travels/${this.travelId}`) as  Observable<Travel>
	this.stopsData$ = this.travelService.getCollectionData(`travels/${this.travelId}/stops`) as  Observable<Stop[]>
}

updateCurrentTravel(travel: Partial<Travel>) {
	this.travelService.updateData(`travels${this.travelId}`, travel)
}

  

updateCurrentStop(stop: Partial<Stop>) {
	stop.type = stop.type?.toString();
	this.travelService.updateData(`travels${this.travelId}/stops/${stop.id}`, stop)
}

  

addStop() {
	if (!this.travelId) return;
	this.travelService.addStop(this.travelId);
}

deleteStop(stopId: string) {
	if (!this.travelId || !stopId) {
		return;
	}
	this.travelService.deleteData(`travels${this.travelId}/stops/${stopId}`)
	this.stopsData$ = this.travelService.getCollectionData(`travels${this.travelId}/stops`) as  Observable<Stop[]>

}

8. Konfigurowanie pamięci

Teraz zaimplementujesz Storage, aby przechowywać obrazy i inne typy multimediów.

Cloud Firestore najlepiej nadaje się do przechowywania danych strukturalnych, takich jak obiekty JSON. Cloud Storage służy do przechowywania plików lub obiektów binarnych. W tej aplikacji użyjesz go, aby umożliwić użytkownikom udostępnianie zdjęć z podróży.

Podobnie jak w przypadku Firestore, przechowywanie i aktualizowanie plików w Storage wymaga unikalnego identyfikatora każdego pliku.

Zaimplementujmy funkcje w TraveService:

Przesyłanie pliku

Otwórz src/app/services/travel.service.ts i wstaw Storage z AngularFire:

export  class  TravelService {
firestore: Firestore = inject(Firestore);
auth: Auth = inject(Auth);
storage: Storage = inject(Storage);

Następnie zaimplementuj funkcję przesyłania:

async  uploadToStorage(path: string, input: HTMLInputElement, contentType: any) {
	if (!input.files) return  null
	const  files: FileList = input.files;
		for (let  i = 0; i  <  files.length; i++) {
			const  file = files.item(i);
			if (file) {
				const  imagePath = `${path}/${file.name}`
				const  storageRef = ref(this.storage, imagePath);
				await  uploadBytesResumable(storageRef, file, contentType);
				return  await  getDownloadURL(storageRef);
			}
		}
	return  null;
}

Główna różnica między dostępem do dokumentów z Firestore a plików z Cloud Storage polega na tym, że chociaż oba typy danych mają ścieżki o strukturze folderów, kombinację adresu URL i ścieżki uzyskuje się za pomocą funkcji getDownloadURL, którą można następnie zapisać i użyć w pliku .

Korzystanie z funkcji w aplikacji

Przejdź do src/app/components/edit-stop/edit-stop.component.ts i wywołaj funkcję przesyłania za pomocą tego kodu:

	async  uploadFile(file: HTMLInputElement, stop: Partial<Stop>) {
	const  path = `/travels/${this.travelId}/stops/${stop.id}`
	const  url = await  this.travelService.uploadToStorage(path, file, {contentType:  'image/png'});
	stop.image = url ? url : '';
	this.travelService.updateData(path, stop);
}

Po przesłaniu obrazu sam plik multimedialny zostanie przesłany do pamięci, a jego adres URL zostanie odpowiednio zapisany w dokumencie w Firestore.

9. Wdrożenie aplikacji

Teraz możemy wdrożyć aplikację.

Skopiuj konfiguracje firebasesrc/environments/environment.ts do src/environments/environment.prod.ts i uruchom:

firebase deploy

Powinien pojawić się ekran podobny do tego:

 Browser application bundle generation complete.
 Copying assets complete.
 Index html generation complete.

=== Deploying to 'friendly-travels-b6a4b'...

i  deploying storage, firestore, hosting
i  firebase.storage: checking storage.rules for compilation errors...
  firebase.storage: rules file storage.rules compiled successfully
i  firestore: reading indexes from firestore.indexes.json...
i  cloud.firestore: checking firestore.rules for compilation errors...
  cloud.firestore: rules file firestore.rules compiled successfully
i  storage: latest version of storage.rules already up to date, skipping upload...
i  firestore: deploying indexes...
i  firestore: latest version of firestore.rules already up to date, skipping upload...
  firestore: deployed indexes in firestore.indexes.json successfully for (default) database
i  hosting[friendly-travels-b6a4b]: beginning deploy...
i  hosting[friendly-travels-b6a4b]: found 6 files in .firebase/friendly-travels-b6a4b/hosting
  hosting[friendly-travels-b6a4b]: file upload complete
  storage: released rules storage.rules to firebase.storage
  firestore: released rules firestore.rules to cloud.firestore
i  hosting[friendly-travels-b6a4b]: finalizing version...
  hosting[friendly-travels-b6a4b]: version finalized
i  hosting[friendly-travels-b6a4b]: releasing new version...
  hosting[friendly-travels-b6a4b]: release complete

  Deploy complete!

Project Console: https://console.firebase.google.com/project/friendly-travels-b6a4b/overview
Hosting URL: https://friendly-travels-b6a4b.web.app

10. Gratulacje!

Aplikacja powinna być teraz gotowa i wdrożona w Hostingu Firebase. Wszystkie dane i statystyki będą teraz dostępne w konsoli Firebase.

Aby poznać więcej funkcji AngularFire, Functions i reguł bezpieczeństwa, nie zapomnij zapoznać się z opcjonalnymi krokami poniżej oraz innymi samouczkami Firebase.

11. Opcjonalnie: strażnicy uwierzytelniania AngularFire

Oprócz uwierzytelniania Firebase AngularFire oferuje też ochronę tras na podstawie uwierzytelniania, dzięki czemu użytkownicy z niewystarczającym dostępem mogą być przekierowywani. Pomaga to chronić aplikację przed dostępem użytkowników do chronionych danych.

W src/app/app-routing.module.ts zaimportuj

import {AuthGuard, redirectLoggedInTo, redirectUnauthorizedTo} from  '@angular/fire/auth-guard'

Następnie możesz zdefiniować funkcje określające, kiedy i gdzie użytkownicy powinni być przekierowywani na określonych stronach:

const  redirectUnauthorizedToLogin = () =>  redirectUnauthorizedTo(['signin']);
const  redirectLoggedInToTravels = () =>  redirectLoggedInTo(['my-travels']);

Następnie po prostu dodaj je do tras:

const  routes: Routes = [
	{path:  '', component:  LoginPageComponent, canActivate: [AuthGuard], data: {authGuardPipe:  redirectLoggedInToTravels}},
	{path:  'signin', component:  LoginPageComponent, canActivate: [AuthGuard], data: {authGuardPipe:  redirectLoggedInToTravels}},
	{path:  'my-travels', component:  MyTravelsComponent, canActivate: [AuthGuard], data: {authGuardPipe:  redirectUnauthorizedToLogin}},
	{path:  'edit/:travelId', component:  EditTravelsComponent, canActivate: [AuthGuard], data: {authGuardPipe:  redirectUnauthorizedToLogin}},
];

12. Opcjonalnie: reguły zabezpieczeń

Zarówno Firestore, jak i Cloud Storage używają reguł zabezpieczeń (firestore.rules i security.rules odpowiednio) do egzekwowania zabezpieczeń i weryfikowania danych.

Obecnie dane Firestore i Storage mają otwarty dostęp do odczytu i zapisu, ale nie chcesz, aby ludzie zmieniali posty innych osób. Za pomocą reguł zabezpieczeń możesz ograniczyć dostęp do kolekcji i dokumentów.

Reguły Firestore

Aby zezwolić na wyświetlanie postów o podróżach tylko uwierzytelnionym użytkownikom, otwórz plik firestore.rules i dodaj:

rules_version  =  '2';
service  cloud.firestore  {
	match  /databases/{database}/travels  {
		allow  read:  if  request.auth.uid  !=  null;
		allow  write:
		if  request.auth.uid  ==  request.resource.data.userId;
	}
}

Reguły zabezpieczeń mogą też służyć do weryfikacji danych:

rules_version  =  '2';
service  cloud.firestore  {
	match  /databases/{database}/posts  {
		allow  read:  if  request.auth.uid  !=  null;
		allow  write:
		if  request.auth.uid  ==  request.resource.data.userId;
		&&  "author"  in  request.resource.data
		&&  "text"  in  request.resource.data
		&&  "timestamp"  in  request.resource.data;
	}
}

Reguły przechowywania

Podobnie możemy używać reguł zabezpieczeń do egzekwowania dostępu do baz danych pamięci masowej w storage.rules. Pamiętaj, że możemy też używać funkcji do bardziej złożonych sprawdzeń:

rules_version  =  '2';

function  isImageBelowMaxSize(maxSizeMB)  {
	return  request.resource.size  <  maxSizeMB  *  1024  *  1024
		&&  request.resource.contentType.matches('image/.*');
}

 service  firebase.storage  {
	match  /b/{bucket}/o  {
		match  /{userId}/{postId}/{filename}  {
			allow  write:  if  request.auth  !=  null
			&&  request.auth.uid  ==  userId  &&  isImageBelowMaxSize(5);
			allow  read;
		}
	}
}