Angular & Firebase – CRUD & Login, cz. I

Moja pierwsza styczność z biblioteką AngularFire raczej była dość przykra – często zmieniające się API z kolejnymi wersjami czy tutoriale niskiej jakości. To wszystko skłoniło mnie do napisania tego artykułu, w którym chciałbym Ci przedstawić, jak wykonać logowanie za pomocą maila oraz jak konsumować dane z Firebase.  W części pierwszej tutoriala, skupimy się na logowaniu, rejestracji oraz ochronie ścieżek dostępu poprzez Guard CanActivate. Przykład jest wykonany dla Angulara w wersji 6.0.0, AngularFire 5.0.0-rc.9 oraz Firebase 5.0.2.

Możesz również od razu spojrzeć na demo:
https://stackblitz.com/edit/angularfire-v6-qyrrf8

Firebase

Firebase to tzw. BaaS (Backend as a Service ), który umożliwia min. przechowywanie danych w formacie JSON oraz plików binarnych (np. jpg, mp4). Firebase dostarcza nam real-time database, gdzie komunikacja z serwerem jest oparta o Websockets, dzięki czemu po aktualizacji danych, klient automatycznie dostaje najświeższe dane. Obsługa jest banalnie prosta, w podstawowym zakresie można niemalże wszystko wyklikać z panelu użytkownika! Super rozwiązanie zwłaszcza dla osób, które nie mają wiedzy backendowej, a chcą postawić w szybkim czasie serwer z danymi.

Tyle na temat Firebase, jeśli chcesz lepiej poznać to narzędzie, musisz to zrobić we własnym zakresie. Natomiast w tym artykule, skupię na komunikacji z Firebase za pomocą biblioteki AngularFire.

Tworzymy backend!

Zanim rozpoczniemy komunikację z serwerem, musimy oczywiście sobie go wcześniej przygotować. Rozpoczynamy od odwiedzenia strony www.firebase.com, założenia konta, a następnie po zalogowaniu klikamy przycisk „OTWÓRZ KONSOLĘ” w prawym górnym rogu:

Następnie w kolejnym widoku, klikamy „UTWÓRZ PROJEKT”:

W okienku podajemy nazwę projektu, akceptujemy regulamin i klikamy „UTWÓRZ PROJEKT” i czekamy cierpliwie na powstanie projektu.

Po utworzeniu projektu, w lewym menu przechodzimy do zakładki „AUTHENTICATION”, a następnie klikamy tab „METODA LOGOWANIA”:

Z listy klikamy na pierwszą pozycję – EMAIL / HASŁO i przestawiamy na „WŁĄCZ”:

Oczywiście możesz poeksperymentować z innymi metodami logowania. Zapisujemy ustawienia… i na ten moment to tyle! mamy już przygotowany serwer z możliwością przechowywania i rejestracji użytkowników, czyż to nie piękne?:)

AngularFire

Czas skomunikować się z Firebase. Z pomocą przychodzi nam dedykowana biblioteka, główny bohater artykułu – AngularFire, który jest wrapperem na blibliotekę firebase.jsPozwoli nam się zsynchronizować z danymi w czasie rzeczywistym, oraz dostarcza bardzo dobre API do logowania i monitorowania uwierzytelniania użytkownika.

Rozpoczynamy od instalacji paczki:

Po instalacji, wracamy do panelu Firebase i przechodzimy do ustawień projektu, klikając na zębatkę obok „PROJECT OVERVIEW” w lewym menu:

Scrollujemy  nieco w dół i klikamy „Dodaj Firebase do swojej aplikacji internetowej”. Pojawia się okienko z danymi projektu:

Kopiujemy sam obiekt przypisany do „var config”. Reszta nas nie interesuje.

Podpięcie się pod Firebase

Wracamy do aplikacji angularowej i wklejamy plik konfiguracyjny do plików environment.ts oraz environment.prod.ts w katalogu src/environments. Jest to całkiem dobre miejsce na trzymanie takich globalnych ustawień. Obiekt możemy przypisać np. do pola „firebaseConfig”:

 

Następnie przechodzimy do app.module.ts i importujemy następujące moduły (AngularFireAuthModule i AngularFireModule):

Zwróć uwagę na wywołanie metody initializeApp z obiektem konfiguracyjnym, który zapisaliśmy w pliku environment.ts i environment.prod.ts. Teraz nasza aplikacja staje się świadoma backendu dostarczonego przez Firebase.

AuthService

Stworzymy teraz usługę, która pozwoli nam rejestrować i logować użytkowników:

Właściwie wystarczy wstrzyknąć do konstruktora usługę AngularFireAuth, a reszta dosłownie dzieje się sama! Trzeba tylko wołać odpowiednie metody. Myślę, że nie ma sensu tłumaczyć co robią dane metody należące do fireAuth.auth, ich nazwy mówią wszystko. Możesz o nich więcej poczytać w dokumentacji. Warto natomiast zwrócić uwagę na linię:

AuthState jest strumieniem, który emituje zalogowanego użytkownika. Jeśli użytkownik zostaje wylogowany, strumień wyemituje null.

Obiekt użytkownika jest przechowuje również w polu currentUser:

Także jak na tacy mamy wszystko co trzeba.

Persistence.LOCAL, SESSION, NONE

Warto wiedzieć, że możemy manipulować stanem uwierzytelnienia w różnych scenariuszach, takich jak np. zamknięcie karty i powrót (wylogować użytkownika automatycznie czy może nie?). Otrzymujemy możliwość zmiany właściwości PERSISTENCE, w poniższy sposób:

Możliwe 3 opcje do wyboru:

  • LOCAL (DOMYŚLNE) –  użytkownik nadal zostaje zalogowany po zamknięciu karty, trzeba jawnie użyć metody signOut aby wyczyścić stan zalogowania. Przydatne, jeśli po zamknięciu karty i ponownym powrocie, chcemy użytkownikowi pozwolić pozostać zalogowanym.
  • SESSION – stan zalogowanego użytkownika jest aktywny wyłącznie dla aktualnej sesji i zostanie wyczyszczony w przypadku zamknięcia okna/karty. Przydatne np. w aplikacjach, które są publicznie dostępne na komputerach, z których korzysta wielu użytkowników (np. w bibliotece).
  • NONE – stan zalogowania jest przetrzymywany w pamięci i zostanie wyczyszczony po odświeżeniu okna.

Wspomnę, że w Firebase 4.12.0 nastąpiła migracja przetrzymywania stanu użytkownika dla LOCAL PERSISTENCE z localStorage do IndexedDB, min. z takich powodów jak:

  • użycie indexedDB umożliwi używanie Firebase Auth wraz z Service Workers i Web Workers
  • indexedDB ma lepsze wsparcie w środowiskach takich jak np.  Ionic/Cordova,  lub aplikacje Chrome

Podgląd zarejestrowanych użytkowników

Po rejestracji, możemy zobaczyć założone konta w zakładce AUTHENTICATION:

Można również ręcznie dodać użytkownika, klikając „Dodaj użytkownika”.

 

AuthGuard

Obecnie w naszej aplikacji, gdy użytkownik odświeży stronę, to otrzymuje użytkownika z wartością null, gdyż currentUser będzie zaraz po odświeżeniu przechowywał wartość null, mimo, że stan uwierzytelnienia został zachowany.

Użytkownik może również przejść od razu na daną ścieżkę dowolnego widoku z pominięciem etapu logowania, oczywiście jeśli zna ścieżkę(za wiele mu to i tak nie da, bo bez zalogowania dane i tak nie zostanę pobrane).

Oba problemy może rozwiązać za pomocą guarda CanActivate. Podczas przejścia na widok inny niż login, sprawdzimy czy authState przechowuje stan użytkownika, jeśli tak, to go przepuścimy, natomiast jeśli wyemituje null, no to cofniemy go do widoku loginu:

Guard canActivate zwraca strumień z true/false, w zależności czy authState$ wyemitował stan użytkownika (emisja true) czy wyemitował null (emisja false).

Strumień jest już obsługiwany przez mechanizm routingu w Angularze, także nie musimy się martwić o manualną subskrypcję w żadnym miejscu. Można oczywiście użytkownika przekierować np. na widok z informacją, że nie jest autoryzowany i prosimy o zalogowanie. Decyzja należy do Ciebie, pokazałem najprostszy przykład.

Teraz naszego guarda musimy nałożyć na odpowiednie ścieżki, np. na cały dashboard, który będzie sprawdzał również wszystkie ścieżki zawarte w „children”:

Teraz wszystko jest po bożemu, użytkownik jest sprawdzany na etapie przechodzenia między ścieżkami, oraz nie ma problemu, że użytkownik jest równy null na widoku po odświeżeniu aplikacji.

 

DEMO:

https://angularfire-v6-qyrrf8.stackblitz.io

PEŁNY KOD:

https://stackblitz.com/edit/angularfire-v6-qyrrf8

W kolejnej części artykułu, omówię jak konsumować dane – pobierać, dodawać, edytować, usuwać. Wykonamy jakiś fancy przykład, na pewno coś ciekawszego niż TodoList :).

Bardzo polecam Firebase początkującym developerom, którzy chcą stworzyć realny projekt do portfolio 🙂

 

4 Comments

  1. Mikolaj

    Ja naleze do grupy poczatkujacych developerow, ktorzy kojarza Firebase, pracuja z Angularem i maja w planach zrobic cos w wolnym czasie z tymi technologiami, wiec czekam na inspiracje w kolejnych artykulach!
    Ps: bez polskich znakow, bo nadaje z zagranicy

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *