Laboratorium kodowania frameworków Firebase Angular Web Framework

1. Co stworzysz

Podczas tych zajęć z programowania będziesz tworzyć podróżującego bloga z mapą współpracy w czasie rzeczywistym z najnowszą wersją naszej biblioteki Angular: AngularFire . Ostateczna aplikacja internetowa będzie składać się z bloga podróżniczego, na którym będziesz mógł przesyłać zdjęcia do każdego miejsca, do którego podróżowałeś.

AngularFire zostanie użyty do zbudowania aplikacji internetowej, Emulator Suite do lokalnych testów, uwierzytelnianie do śledzenia danych użytkownika, Firestore i Storage do utrwalania danych i multimediów, obsługiwane przez Cloud Functions, i wreszcie Firebase Hosting do wdrożenia aplikacji.

Czego się dowiesz

  • Jak rozwijać się lokalnie przy użyciu produktów Firebase za pomocą pakietu Emulator Suite
  • Jak ulepszyć swoją aplikację internetową za pomocą AngularFire
  • Jak zachować swoje dane w Firestore
  • Jak zachować multimedia w pamięci masowej
  • Jak wdrożyć aplikację w Hostingu Firebase
  • Jak używać Cloud Functions do interakcji z bazami danych i interfejsami API

Co będziesz potrzebował

  • Wersja Node.js 10 lub nowsza
  • Konto Google do tworzenia projektu Firebase i zarządzania nim
  • Firebase CLI w wersji 11.14.2 lub nowszej
  • Wybrana przeglądarka, np. Chrome
  • Podstawowa znajomość Angulara i JavaScriptu

2. Pobierz przykładowy kod

Sklonuj repozytorium GitHub Codelab z wiersza poleceń:

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

Alternatywnie, jeśli nie masz zainstalowanego gita, możesz pobrać repozytorium jako plik ZIP .

Repozytorium Github zawiera przykładowe projekty dla wielu platform.

To ćwiczenie z programowania korzysta wyłącznie z repozytorium webframework:

  • 📁 webframework : kod początkowy, na którym będziesz budować podczas tych zajęć z programowania.

Zainstaluj zależności

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

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

Zainstaluj interfejs wiersza polecenia Firebase

Zainstaluj Firebase CLI, używając tego polecenia w terminalu:

npm install -g firebase-tools

Sprawdź dokładnie, czy wersja Firebase CLI jest większa niż 11.14.2, używając:

firebase  --version

Jeśli Twoja wersja jest starsza niż 11.14.2, zaktualizuj ją za pomocą:

npm update firebase-tools

3. Utwórz i skonfiguruj projekt Firebase

Utwórz projekt Firebase

  1. Zaloguj się do Firebase .
  2. W konsoli Firebase kliknij Dodaj projekt i nazwij swój projekt Firebase <your-project> . Zapamiętaj identyfikator projektu Firebase.
  3. Kliknij opcję Utwórz projekt .

Ważne : Twój projekt Firebase zostanie nazwany <your-project> , ale Firebase automatycznie przypisze mu unikalny identyfikator projektu w postaci <your-project>-1234 . Ten unikalny identyfikator określa, w jaki sposób Twój projekt jest faktycznie identyfikowany (w tym w interfejsie CLI), podczas gdy <twój-projekt> to po prostu nazwa wyświetlana.

Aplikacja, którą będziemy budować, korzysta z produktów Firebase dostępnych dla aplikacji internetowych:

  • Uwierzytelnianie Firebase , aby umożliwić użytkownikom łatwe logowanie się do Twojej aplikacji.
  • Cloud Firestore do zapisywania uporządkowanych danych w chmurze i otrzymywania natychmiastowych powiadomień o zmianach danych.
  • Cloud Storage dla Firebase do zapisywania plików w chmurze.
  • Hosting Firebase do hostowania i obsługi Twoich zasobów.
  • Funkcje umożliwiające interakcję z wewnętrznymi i zewnętrznymi interfejsami API.

Niektóre z tych produktów wymagają specjalnej konfiguracji lub wymagają włączenia za pomocą konsoli Firebase.

Dodaj aplikację internetową Firebase do projektu

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

Włącz logowanie Google do uwierzytelniania Firebase

Aby umożliwić użytkownikom logowanie się do aplikacji internetowej przy użyciu kont Google, użyjemy metody logowania Google .

Aby włączyć logowanie Google :

  1. W konsoli Firebase znajdź sekcję Kompilacja w lewym panelu.
  2. Kliknij opcję Uwierzytelnianie , a następnie kliknij kartę Metoda logowania (lub kliknij tutaj , aby przejść bezpośrednio tam).
  3. Włącz dostawcę logowania Google , a następnie kliknij Zapisz .
  4. Ustaw publiczną nazwę swojej aplikacji na <nazwa-projektu> i wybierz adres e-mail pomocy technicznej projektu z menu rozwijanego.

Włącz Cloud Firestore

  1. W sekcji Kompilacja konsoli Firebase kliknij Baza danych Firestore .
  2. Kliknij opcję Utwórz bazę danych w panelu Cloud Firestore.
  3. Ustaw lokalizację, w której przechowywane są dane Cloud Firestore. Możesz pozostawić to ustawienie domyślne lub wybrać region blisko siebie.

Włącz przechowywanie w chmurze

Aplikacja internetowa korzysta z Cloud Storage dla Firebase do przechowywania, przesyłania i udostępniania zdjęć.

  1. W sekcji Kompilacja konsoli Firebase kliknij opcję Pamięć .
  2. Jeśli nie ma przycisku Rozpocznij , oznacza to, że miejsce w chmurze już jest dostępne

włączone i nie musisz wykonywać poniższych kroków.

  1. Kliknij opcję Rozpocznij .
  2. Przeczytaj zastrzeżenie dotyczące reguł bezpieczeństwa Twojego projektu Firebase, a następnie kliknij Dalej .
  3. Lokalizacja Cloud Storage jest wstępnie wybrana z tym samym regionem, który wybrałeś dla swojej bazy danych Cloud Firestore. Kliknij Gotowe, aby zakończyć konfigurację.

Przy domyślnych regułach bezpieczeństwa każdy uwierzytelniony użytkownik może zapisywać wszystko w Cloud Storage. W dalszej części tego ćwiczenia z programowania zadbamy o większe bezpieczeństwo naszego magazynu.

4. Połącz się ze swoim projektem Firebase

Interfejs wiersza poleceń Firebase (CLI) umożliwia używanie Firebase Hosting do lokalnego udostępniania aplikacji internetowej, a także wdrażania aplikacji internetowej w projekcie Firebase.

Upewnij się, że wiersz poleceń uzyskuje dostęp do lokalnego katalogu webframework Twojej aplikacji.

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

firebase login

Następnie uruchom następujące polecenie, aby utworzyć alias projektu. Zamień $YOUR_PROJECT_ID na identyfikator swojego projektu Firebase.

firebase  use  $YOUR_PROJECT_ID

Dodaj AngularFire

Aby dodać AngularFire do aplikacji, uruchom polecenie:

ng add @angular/fire

Następnie postępuj zgodnie z instrukcjami wiersza poleceń i wybierz funkcje istniejące w projekcie Firebase.

Zainicjuj Firebase

Aby zainicjować projekt Firebase, uruchom:

firebase init

Następnie, postępując zgodnie z monitami wiersza poleceń, wybierz funkcje i emulatory, które zostały użyte w projekcie Firebase.

Uruchom emulatory

Z katalogu webframework uruchom następującą komendę, aby uruchomić emulatory:

firebase  emulators:start

Ostatecznie powinieneś zobaczyć 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, że ✔All emulators ready! komunikat, emulatory są gotowe do użycia.

Powinieneś zobaczyć interfejs użytkownika aplikacji podróżniczej, który (jeszcze!) nie działa:

A teraz zacznijmy budować!

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

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

Otwórz interfejs emulatora

W przeglądarce internetowej przejdź pod adres http://127.0.0.1:4000/ . Powinieneś zobaczyć interfejs użytkownika pakietu emulatorów.

Skieruj aplikację tak, aby korzystała z emulatorów

W src/app/app.module.ts dodaj następujący kod do listy importów 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. Dodanie uwierzytelnienia

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 uwierzytelnienia użytkownika za pomocą funkcji authState . Zmodyfikuj funkcje strony logowania tak, aby strona sprawdzała stan autoryzacji użytkownika podczas ładowania.

Wstrzykiwanie uwierzytelniania AngularFire

W src/app/pages/login-page/login-page.component.ts zaimportuj Auth z @angular/fire/auth i wstrzyknij go do LoginPageComponent . Dostawców uwierzytelniania, takich jak Google, oraz funkcje takie jak signin i signout można również 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);
		})
	}
}

Teraz strona logowania działa! Spróbuj się zalogować i sprawdź wyniki w emulatorze uwierzytelniania.

7. Konfiguracja Firestore

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

Podobnie jak w przypadku uwierzytelniania, funkcje Firestore są dostarczane z AngularFire. Każdy dokument należy do kolekcji i każdy dokument może mieć także zagnieżdżone kolekcje. Do utworzenia i aktualizacji wpisu na blogu podróżniczym wymagana jest znajomość path dokumentu w Firestore.

Wdrażanie usługi Travel Service

Ponieważ wiele różnych stron będzie musiało czytać i aktualizować dokumenty Firestore w aplikacji internetowej, możemy zaimplementować funkcje w src/app/services/travel.service.ts , aby powstrzymać się od 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 również zdefiniowanie obserwowalnego obiektu user$ , który nasłuchuje bieżącego stanu uwierzytelnienia.

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

Dodanie wpisu podróżniczego

Wpisy z podróży będą istnieć jako dokumenty przechowywane w Firestore, a ponieważ dokumenty muszą istnieć w kolekcjach, kolekcja zawierająca wszystkie wpisy z podróży będzie nosiła nazwę travels . Zatem ścieżką dowolnego postu podróżniczego będą travels/

Korzystając z funkcji addDoc z AngularFire, obiekt można wstawić 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

Biorąc pod uwagę identyfikator UID dowolnego wpisu podróżniczego, można wydedukować ścieżkę dokumentu przechowywanego w Firestore, który można następnie odczytać, zaktualizować lub usunąć za pomocą funkcji updateFoc i deleteDoc 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 obserwowalnych

Ponieważ wpisy dotyczące podróży i przystanki na trasie można modyfikować po utworzeniu, bardziej przydatne byłoby uzyskanie obiektów dokumentu jako obiektów obserwowalnych, aby subskrybować wszelkie wprowadzone zmiany. Ta funkcjonalność jest oferowana przez funkcje docData i collectionData z @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 wpisu podróżniczego

Teraz, gdy operacje na postach podróżniczych są już skonfigurowane, czas rozważyć przystanki, które będą istniały w podkolekcji postów podróżniczych, takich jak: travels/ /stops/ travels/ /stops/

Jest to prawie identyczne z tworzeniem wpisu podróżniczego, więc podejmij wyzwanie, aby wdrożyć go samodzielnie lub sprawdź implementację poniżej:

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

Ładny! W serwisie Travel zaimplementowano funkcje Firestore, dzięki czemu teraz możesz zobaczyć je w akcji.

Korzystanie z funkcji Firestore w aplikacji

Przejdź do src/app/pages/my-travels/my-travels.component.ts i wstrzyknij TravelService , aby skorzystać z jego funkcji.

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

W konstruktorze wywoływana jest TravelService w celu uzyskania tablicy Observable obejmującej wszystkie podróże.

W przypadku gdy potrzebne są jedynie podróże aktualnego użytkownika należy skorzystać z funkcji query .

Inne metody zapewnienia bezpieczeństwa obejmują wdrażanie reguł bezpieczeństwa lub korzystanie z Cloud Functions w Firestore, jak opisano w opcjonalnych krokach poniżej

Następnie wystarczy wywołać funkcje zaimplementowane w TravelService .

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

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

Teraz strona Moje podróże powinna działać! Sprawdź, co dzieje się w emulatorze Firestore, gdy tworzysz nowy post podróżniczy.

Następnie powtórz dla 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. Konfiguracja pamięci

Teraz zaimplementujesz usługę Storage do przechowywania obrazów i innych typów multimediów.

Cloud Firestore najlepiej nadaje się do przechowywania danych strukturalnych, takich jak obiekty JSON. Cloud Storage jest przeznaczony do przechowywania plików lub obiektów BLOB. W tej aplikacji będziesz jej używać, aby umożliwić użytkownikom udostępnianie zdjęć z podróży.

Podobnie w przypadku Firestore przechowywanie i aktualizowanie plików za pomocą Storage wymaga unikalnego identyfikatora dla każdego pliku.

Zaimplementujmy funkcje w TraveService :

Przesyłanie pliku

Przejdź do src/app/services/travel.service.ts i wstrzyknij Storage z AngularFire:

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

I 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;
}

Podstawowa różnica między dostępem do dokumentów z Firestore a plikami z Cloud Storage polega na tym, że chociaż oba korzystają ze ścieżek o strukturze folderów, podstawowy adres URL i kombinacja ścieżki są uzyskiwane poprzez getDownloadURL , który można następnie zapisać i wykorzystać w plik.

Korzystanie z funkcji w aplikacji

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

	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 adres URL zostanie odpowiednio zapisany w dokumencie w Firestore.

9. Wdrażanie aplikacji

Teraz jesteśmy gotowi do wdrożenia aplikacji!

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

firebase deploy

Powinieneś zobaczyć coś takiego:

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

Teraz Twoja aplikacja powinna być kompletna i wdrożona w Hostingu Firebase! Wszystkie dane i analizy będą teraz dostępne w konsoli Firebase.

Aby uzyskać więcej funkcji dotyczących AngularFire, funkcji i reguł bezpieczeństwa, nie zapomnij sprawdzić opcjonalnych kroków poniżej, a także innych ćwiczeń Firebase Codelab !

11. Opcjonalnie: Strażnicy autoryzacji AngularFire

Oprócz uwierzytelniania Firebase, AngularFire oferuje również ochronę tras opartą na uwierzytelnianiu, dzięki czemu użytkownicy z niewystarczającym dostępem mogą zostać przekierowani. 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'

Można wówczas zdefiniować funkcje określające, kiedy i dokąd użytkownicy mają być przekierowywani na określonych stronach:

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

Następnie po prostu dodaj je do swoich 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: zasady bezpieczeństwa

Zarówno Firestore, jak i Cloud Storage korzystają z reguł bezpieczeństwa (odpowiednio firestore.rules i security.rules ) w celu egzekwowania bezpieczeństwa i sprawdzania poprawności danych.

W tej chwili dane Firestore i Storage mają otwarty dostęp do odczytu i zapisu, ale nie chcesz, aby ludzie zmieniali posty innych! Możesz użyć reguł bezpieczeństwa, aby ograniczyć dostęp do swoich kolekcji i dokumentów.

Regulamin Firestore'a

Aby zezwolić tylko uwierzytelnionym użytkownikom na przeglądanie wpisów podróżniczych, przejdź do pliku 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 bezpieczeństwa można również wykorzystać do walidacji 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;
	}
}

Zasady przechowywania

Podobnie możemy użyć reguł bezpieczeństwa, aby wymusić dostęp do baz danych pamięci masowej w storage.rules . Pamiętaj, że funkcji możemy używać również do bardziej złożonych kontroli:

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