Ćwiczenie z programowania w Firebase Angular Web Frameworks

Ćwiczenie z programowania w Firebase Angular Web Frameworks

Informacje o tym ćwiczeniu (w Codelabs)

subjectOstatnia aktualizacja: maj 10, 2023
account_circleDokument stworzony przez pracownika Google

1. Co utworzysz

W ramach tego ćwiczenia w programie utworzysz podróżniczego bloga, na którym możesz w czasie rzeczywistym współpracować nad mapą z najnowszymi informacjami z naszej biblioteki Angular: AngularFire. Końcowa aplikacja internetowa powstanie bloga podróżniczego, w którym możesz przesyłać zdjęcia do wszystkich odwiedzonych miejsc.

AngularFire będzie używany do tworzenia aplikacji internetowej, Pakietu emulatorów do testów lokalnych, uwierzytelniania do śledzenia danych użytkowników, Firestore i przechowywania danych do przechowywania danych i multimediów przy użyciu Cloud Functions, a na koniec do wdrożenia aplikacji w Hostingu Firebase.

Czego się nauczysz

  • Jak programować lokalnie przy użyciu usług Firebase przy użyciu Pakietu emulatorów
  • Jak ulepszyć aplikację internetową za pomocą AngularFire
  • Jak zachować 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;

Czego potrzebujesz

  • Node.js w wersji 10 lub nowszej.
  • Konto Google do tworzenia projektu Firebase i do zarządzania nim
  • interfejs wiersza poleceń Firebase w wersji 11.14.2 lub nowszej.
  • wybraną przeglądarkę, np. Chrome;
  • Podstawowa znajomość języka Angular i JavaScriptu

2. Pobieranie przykładowego kodu

Skopiuj repozytorium GitHub ćwiczenia z programowania za pomocą wiersza poleceń:

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

Jeśli nie masz zainstalowanej aplikacji git, możesz pobrać repozytorium jako plik ZIP.

Repozytorium GitHub zawiera przykładowe projekty na wiele platform.

To ćwiczenie w Codelabs korzysta tylko z repozytorium platformy internetowej:

  • 📁 webframework: kod początkowy, który opracujesz w trakcie tego ćwiczenia z programowania.

Instalowanie zależności

Po sklonowaniu zainstaluj zależności w katalogu głównym i folderze functions, zanim utworzysz aplikację internetową.

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

Zainstaluj wiersz poleceń Firebase

Zainstaluj interfejs wiersza poleceń Firebase, używając tego polecenia w terminalu:

npm install -g firebase-tools

Dokładnie sprawdź, czy wersja wiersza poleceń Firebase jest w wersji nowszej niż 11.14.2 za pomocą:

firebase  --version

Jeśli Twoja wersja jest starsza niż 11.14.2, zaktualizuj ją, używając:

npm update firebase-tools

3. Tworzenie i konfigurowanie projektu Firebase

Tworzenie projektu Firebase

  1. Zaloguj się w Firebase.
  2. W konsoli Firebase kliknij Dodaj projekt i nazwij projekt Firebase <Twój-projekt>. Zapamiętaj identyfikator projektu Firebase.
  3. Kliknij Utwórz projekt.

Ważne: projekt Firebase będzie miał nazwę <Twój-projekt>, ale Firebase automatycznie przypisze mu unikalny identyfikator w formacie <Twój-projekt>-1234. Ten unikalny identyfikator jest identyfikowany przez projekt (również w interfejsie wiersza poleceń), a <Twój-projekt> to po prostu wyświetlana nazwa.

Aplikacja, którą utworzymy, korzysta z usług Firebase dostępnych dla aplikacji internetowych:

  • Uwierzytelnianie Firebase, które ułatwia użytkownikom logowanie się w Twojej aplikacji.
  • Cloud Firestore pozwala zapisywać uporządkowane dane w chmurze i otrzymywać natychmiastowe powiadomienia o zmianach danych.
  • Cloud Storage dla Firebase, aby zapisywać pliki w chmurze.
  • Hosting Firebase do hostowania i wyświetlania zasobów.
  • funkcje umożliwiające interakcję z wewnętrznymi i zewnętrznymi interfejsami API;

Niektóre z tych usług wymagają specjalnych konfiguracji lub trzeba włączyć je w konsoli Firebase.

Dodaj aplikację internetową Firebase do projektu

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

włączyć logowanie się przez Google w Uwierzytelnianiu Firebase,

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

Aby włączyć logowanie przez Google:

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

Włączanie Cloud Firestore

  1. W sekcji Tworzenie konsoli Firebase kliknij Baza danych Firestore.
  2. W panelu Cloud Firestore kliknij Utwórz bazę danych.
  3. Ustaw lokalizację przechowywania danych Cloud Firestore. Możesz pozostawić to ustawienie domyślne lub wybrać region w pobliżu.

Włącz Cloud Storage

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

  1. W sekcji Kompilacja konsoli Firebase kliknij Miejsce na dane.
  2. Jeśli nie widzisz przycisku Rozpocznij, oznacza to, że usługa Cloud Storage jest już używana.

i nie musisz wykonywać czynności opisanych poniżej.

  1. Kliknij Rozpocznij.
  2. Przeczytaj wyłączenie odpowiedzialności dotyczące reguł zabezpieczeń projektu Firebase i kliknij Dalej.
  3. Wstępnie wybrana lokalizacja w Cloud Storage zawiera ten sam region, który został wybrany dla bazy danych Cloud Firestore. Kliknij Gotowe, aby zakończyć konfigurację.

Zgodnie z domyślnymi regułami zabezpieczeń każdy uwierzytelniony użytkownik może zapisywać w Cloud Storage dowolne informacje. W dalszej części tego ćwiczenia z programowania zwiększymy bezpieczeństwo naszego miejsca na dane.

4. Połącz z projektem Firebase

Interfejs wiersza poleceń Firebase (CLI) umożliwia korzystanie z Hostingu Firebase do lokalnego udostępniania aplikacji internetowej oraz wdrażania aplikacji internetowej w projekcie Firebase.

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

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

firebase login

Następnie uruchom poniższe polecenie, aby utworzyć alias projektu. Zastąp $YOUR_PROJECT_ID identyfikatorem 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 dostępne w Twoim projekcie Firebase.

Zainicjuj Firebase

Aby zainicjować projekt Firebase, uruchom polecenie:

firebase init

Następnie, zgodnie z wierszami poleceń, wybierz funkcje i emulatory używane w Twoim projekcie Firebase.

Uruchom emulatory

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

Zobaczysz interfejs aplikacji turystycznej, który jeszcze nie działa:

A teraz do roboty!

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 nasłuchuje na porcie 9099.

Otwórz EmulatorUI.

W przeglądarce otwórz stronę http://127.0.0.1:4000/. Powinien wyświetlić się interfejs użytkownika Pakietu emulatorów.

Kieruj aplikację, aby używać emulatorów

W programie src/app/app.module.ts dodaj ten kod do listy importów usługi 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 używania lokalnych emulatorów, co umożliwia lokalne testowanie i programowanie.

6. Dodawanie uwierzytelniania

Po skonfigurowaniu emulatorów aplikacji możemy dodać funkcje uwierzytelniania, aby mieć pewność, że każdy użytkownik jest zalogowany przed opublikowaniem wiadomości.

W tym celu możemy zaimportować funkcje signin bezpośrednio z AngularFire i śledzić stan uwierzytelniania użytkownika za pomocą funkcji authState. Zmodyfikuj funkcje strony logowania, tak aby podczas jej wczytywania strona sprawdzała stan uwierzytelniania użytkownika.

Wstrzykiwanie uwierzytelniania AngularFire

W programie src/app/pages/login-page/login-page.component.ts zaimportuj Auth z usługi @angular/fire/auth i wstrzyknij go w komponencie LoginPageComponent. Dostawcy uwierzytelniania, tacy jak Google, i funkcje takie jak signin, signout również można zaimportować bezpośrednio z tego samego pakietu i użyć ich 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 już działa. Zaloguj się i sprawdź wyniki w emulatorze uwierzytelniania.

7. Konfigurowanie Firestore

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

Podobnie jak uwierzytelnianie, funkcje Firestore są gotowe do użycia z AngularFire. Każdy dokument należy do kolekcji, a każdy dokument może też mieć kolekcje zagnieżdżone. Znajomość path dokumentu w Firestore jest wymagana do utworzenia i zaktualizowania posta na blogu podróżniczego.

Wdrażanie usługi TravelService

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

Zacznij od wstrzykiwania Auth, podobnie jak w poprzednim kroku, oraz Firestore do naszej usługi. Warto też zdefiniować obserwowany obiekt 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 wpisu o podróży

Posty dotyczące podróży będą istnieć jako dokumenty przechowywane w Firestore, a ponieważ dokumenty muszą znajdować się w kolekcjach, kolekcja zawierająca wszystkie posty o podróżach będzie nosić nazwę travels. Dlatego ścieżka każdego słupka podróżnego będzie mieć postać travels/.

Za pomocą funkcji addDoc z AngularFire możesz 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

Biorąc pod uwagę identyfikator UID dowolnego posta o podróży, można wywnioskować ścieżkę dokumentu zapisanego w Firestore, który następnie można 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 dostrzegalnych

Posty i przystanki na drodze można modyfikować po utworzeniu, więc lepiej byłoby pobrać obiekty dokumentu jako obiekty obserwacyjne, aby zasubskrybować wszelkie wprowadzane zmiany. Ta funkcja jest dostępna w ramach funkcji docData i collectionData z usługi @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 o podróży

Skoro działania związane z podróżą masz już skonfigurowane, czas pomyśleć o przystankach, które będą dostępne w podkolekcji poświęconej podróżowi: travels//stops/

Działa to niemal tak samo jak tworzenie posta o podróży, więc musisz samodzielnie zaimplementować go lub sprawdzić to poniżej:

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 je teraz zobaczyć w akcji.

Korzystanie z funkcji Firestore w aplikacji

Przejdź do elementu src/app/pages/my-travels/my-travels.component.ts i wstrzyknij TravelService, aby używać jego funkcji.

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

Funkcja TravelService jest wywoływana w konstruktorze w celu uzyskania tablicy dostrzegalnej dla wszystkich podróży.

Jeśli potrzebna jest tylko podróż bieżącego użytkownika, użyj funkcji query.

Inne metody zapewniania bezpieczeństwa to m.in. wdrożenie reguł zabezpieczeń lub używanie Cloud Functions z Firestore, co 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 już działać. Sprawdź, co się dzieje w emulatorze Firestore, gdy utworzysz nowy wpis o podróży.

Następnie powtórz te czynności w przypadku funkcji aktualizacji w komponencie /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 masowej

Teraz wdrożysz Cloud Storage, aby przechowywać obrazy i inne rodzaje multimediów.

Cloud Firestore najlepiej nadaje się do przechowywania uporządkowanych danych, takich jak obiekty JSON. Usługa Cloud Storage jest przeznaczona do przechowywania plików lub obiektów blob. W tej aplikacji umożliwisz użytkownikom udostępnianie zdjęć z podróży.

Podobnie w Firestore przechowywanie i aktualizowanie plików w pamięci masowej wymaga unikalnego identyfikatora każdego pliku.

Zaimplementujmy funkcje w komórce 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);

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 do plików z Cloud Storage polega na tym, że chociaż oba te procesy przebiegają według struktury folderów, jednak bazowa kombinacja adresu URL i ścieżki jest uzyskiwana za pomocą funkcji getDownloadURL, którą można zapisać i wykorzystać w pliku .

Korzystanie z funkcji w aplikacji

Przejdź do src/app/components/edit-stop/edit-stop.component.ts i wywołaj funkcję przesyłania, używając:

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

9. Wdrożenie aplikacji

Teraz możemy wdrożyć aplikację.

Skopiuj konfigurację firebase z src/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!

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

Aby dowiedzieć się więcej o AngularFire, funkcjach i regułach zabezpieczeń, zapoznaj się z opcjonalnymi krokami poniżej oraz z innymi ćwiczeniami z programowania Firebase.

11. Opcjonalnie: zabezpieczenia uwierzytelniania AngularFire

Oprócz uwierzytelniania Firebase AngularFire oferuje też zabezpieczenia oparte na uwierzytelnianiu, dzięki czemu możliwe jest przekierowanie użytkowników z niewystarczającym dostępem. Pomaga to chronić aplikację przed użytkownikami uzyskującymi dostęp do danych chronionych.

Zaimportuj w src/app/app-routing.module.ts

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

Następnie możesz zdefiniować funkcje określające, kiedy i gdzie 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: reguły zabezpieczeń

Firestore i Cloud Storage używają reguł zabezpieczeń (odpowiednio firestore.rules i security.rules), aby egzekwować bezpieczeństwo i weryfikować dane.

W tej chwili dane Firestore i Storage mają otwarty dostęp do odczytu i zapisu, ale nie chcesz, aby użytkownicy zmieniali uprawnienia innych osób postów! Możesz użyć reguł zabezpieczeń, aby ograniczyć dostęp do kolekcji i dokumentów.

Reguły Firestore

Aby zezwolić tylko uwierzytelnionym użytkownikom na wyświetlanie postów o podróżach, 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 weryfikowania 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

W podobny sposób możemy wykorzystać reguły zabezpieczeń, aby wymusić dostęp do baz danych pamięci masowej w storage.rules. Pamiętaj, że w przypadku bardziej złożonych testów możemy też użyć funkcji:

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