Codelab Framework Web Angular Firebase

1. Yang akan Anda buat

Dalam codelab ini, Anda akan membuat blog perjalanan dengan peta kolaboratif real-time menggunakan library Angular terbaru: AngularFire. Aplikasi web final akan terdiri dari blog perjalanan di mana Anda dapat mengunggah gambar ke setiap lokasi yang telah Anda kunjungi.

AngularFire akan digunakan untuk mem-build aplikasi web, Emulator Suite untuk pengujian lokal, Authentication untuk melacak data pengguna, Firestore dan Storage untuk mempertahankan data dan media, didukung oleh Cloud Functions, dan terakhir, Firebase Hosting untuk men-deploy aplikasi.

Yang akan Anda pelajari

  • Cara melakukan pengembangan dengan produk Firebase secara lokal menggunakan Emulator Suite
  • Cara meningkatkan kualitas aplikasi web Anda dengan AngularFire
  • Cara mempertahankan data di Firestore
  • Cara mempertahankan media di Penyimpanan
  • Cara men-deploy aplikasi Anda ke Firebase Hosting
  • Cara menggunakan Cloud Functions untuk berinteraksi dengan database dan API

Yang Anda butuhkan

  • Node.js versi 10 atau yang lebih baru
  • Akun Google untuk pembuatan dan pengelolaan Project Firebase Anda
  • Firebase CLI versi 11.14.2 atau yang lebih baru
  • Browser pilihan Anda, seperti Chrome
  • Pemahaman dasar tentang Angular dan JavaScript

2. Mendapatkan kode contoh

Clone repositori GitHub codelab dari command line:

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

Atau, jika belum menginstal git, Anda dapat mendownload repositori sebagai file ZIP.

Repositori GitHub berisi project contoh untuk beberapa platform.

Codelab ini hanya menggunakan repositori webframework:

  • 📊 webframework: Kode awal yang akan Anda buat selama codelab ini.

Menginstal dependensi

Setelah meng-clone, instal dependensi di folder root dan functions sebelum mem-build aplikasi web.

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

Instal Firebase CLI

Instal Firebase CLI menggunakan perintah ini di terminal:

npm install -g firebase-tools

Periksa kembali apakah versi Firebase CLI Anda lebih baru dari 11.14.2 menggunakan:

firebase  --version

Jika versi Anda lebih rendah dari 11.14.2, perbarui menggunakan:

npm update firebase-tools

3. Membuat dan menyiapkan project Firebase

Membuat project Firebase

  1. Login ke Firebase.
  2. Di Firebase console, klik Tambahkan Project, lalu beri nama project Firebase Anda <project-Anda>. Ingat project ID untuk project Firebase Anda.
  3. Klik Buat Project.

Penting: Project Firebase Anda akan diberi nama <your-project>, tetapi Firebase akan otomatis menetapkan Project ID unik untuk project tersebut dalam format <your-project>-1234. ID unik ini adalah cara project Anda sebenarnya diidentifikasi (termasuk di CLI), sedangkan <your-project> hanyalah nama tampilan.

Aplikasi yang akan kita bangun menggunakan produk Firebase yang tersedia untuk aplikasi web:

  • Firebase Authentication untuk memudahkan pengguna login ke aplikasi Anda.
  • Cloud Firestore untuk menyimpan data terstruktur di cloud dan mendapatkan notifikasi instan saat data berubah.
  • Cloud Storage for Firebase untuk menyimpan file di cloud.
  • Firebase Hosting untuk menghosting dan menayangkan aset Anda.
  • Fungsi untuk berinteraksi dengan API internal dan eksternal.

Beberapa produk ini memerlukan konfigurasi khusus atau perlu diaktifkan menggunakan Firebase console.

Menambahkan aplikasi web Firebase ke project

  1. Klik ikon web untuk membuat aplikasi web Firebase baru.
  2. Pada langkah berikutnya, Anda akan melihat objek konfigurasi. Salin konten objek ini ke dalam file environments/environment.ts.

Mengaktifkan login dengan Google untuk Firebase Authentication

Untuk mengizinkan pengguna login ke aplikasi web dengan akun Google mereka, kita akan menggunakan metode login Google.

Untuk mengaktifkan login dengan Google:

  1. Di Firebase console, cari bagian Build di panel kiri.
  2. Klik Authentication, lalu klik tab Sign-in method (atau klik di sini untuk langsung membukanya).
  3. Aktifkan penyedia login dengan Google, lalu klik Save.
  4. Tetapkan nama aplikasi yang dapat dilihat publik menjadi <nama-project-Anda> dan pilih Email dukungan project dari menu dropdown.

Mengaktifkan Cloud Firestore

  1. Di bagian Build Firebase console, klik Firestore Database.
  2. Klik Create database di panel Cloud Firestore.
  3. Tetapkan lokasi penyimpanan data Cloud Firestore. Anda dapat membiarkannya sebagai default atau memilih region yang dekat dengan Anda.

Mengaktifkan Cloud Storage

Aplikasi web menggunakan Cloud Storage for Firebase untuk menyimpan, mengupload, dan membagikan gambar.

  1. Di bagian Build Firebase console, klik Storage.
  2. Jika tidak ada tombol Mulai, berarti Cloud Storage sudah

aktif, dan tidak perlu mengikuti langkah-langkah di bawah.

  1. Klik Mulai.
  2. Baca pernyataan penyangkalan tentang aturan keamanan untuk project Firebase Anda, lalu klik Berikutnya.
  3. Lokasi Cloud Storage telah dipilih sebelumnya dengan region yang sama dengan yang Anda pilih untuk database Cloud Firestore. Klik Selesai untuk menyelesaikan penyiapan.

Dengan aturan keamanan default, setiap pengguna terautentikasi dapat menulis apa pun ke Cloud Storage. Kita akan membuat penyimpanan lebih aman nanti dalam codelab ini.

4. Menghubungkan ke project Firebase

Dengan antarmuka command line (CLI) Firebase, Anda dapat menggunakan Firebase Hosting untuk menyalurkan aplikasi web secara lokal, serta men-deploy aplikasi web ke project Firebase.

Pastikan command line mengakses direktori webframework lokal aplikasi Anda.

Hubungkan kode aplikasi web ke project Firebase Anda. Pertama, login ke Firebase CLI di command line:

firebase login

Selanjutnya, jalankan perintah berikut untuk membuat alias project. Ganti $YOUR_PROJECT_ID dengan ID project Firebase Anda.

firebase  use  $YOUR_PROJECT_ID

Menambahkan AngularFire

Untuk menambahkan AngularFire ke aplikasi, jalankan perintah:

ng add @angular/fire

Lalu, ikuti petunjuk command line, dan pilih fitur yang ada di project Firebase Anda.

Melakukan inisialisasi Firebase

Untuk menginisialisasi project Firebase, jalankan:

firebase init

Kemudian, dengan mengikuti perintah command line, pilih fitur dan emulator yang digunakan dalam project Firebase Anda.

Memulai emulator

Dari direktori webframework, jalankan perintah berikut untuk memulai emulator:

firebase  emulators:start

Pada akhirnya Anda akan melihat sesuatu seperti ini:

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

Setelah Anda melihat pesan ✔All emulators ready!, emulator siap digunakan.

Anda akan melihat UI aplikasi perjalanan, yang (belum!) berfungsi:

Sekarang, mari kita membangun!

5. Menghubungkan aplikasi web ke emulator

Berdasarkan tabel di log emulator, emulator Cloud Firestore memproses port 8080 dan emulator Authentication memproses port 9099.

Membuka EmulatorUI

Di browser web, buka http://127.0.0.1:4000/. Anda akan melihat UI Emulator Suite.

Merutekan aplikasi untuk menggunakan emulator

Di src/app/app.module.ts, tambahkan kode berikut ke daftar impor 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;
		}),
		...
	]

Aplikasi kini dikonfigurasi untuk menggunakan emulator lokal, sehingga pengujian dan pengembangan dapat dilakukan secara lokal.

6. Menambahkan Autentikasi

Setelah emulator disiapkan untuk aplikasi, kita dapat menambahkan fitur Authentication untuk memastikan setiap pengguna login sebelum mereka memposting pesan.

Untuk melakukannya, kita dapat mengimpor fungsi signin langsung dari AngularFire, dan melacak status autentikasi pengguna dengan fungsi authState. Ubah fungsi halaman login agar halaman memeriksa status autentikasi pengguna saat dimuat.

Memasukkan Auth AngularFire

Di src/app/pages/login-page/login-page.component.ts, impor Auth dari @angular/fire/auth, lalu masukkan ke LoginPageComponent. Penyedia autentikasi, seperti Google, dan fungsi seperti signin, signout juga dapat diimpor langsung dari paket yang sama, dan digunakan di aplikasi.

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

Sekarang halaman login berfungsi! Coba login, dan lihat hasilnya di Emulator Authentication.

7. Mengonfigurasi Firestore

Pada langkah ini, Anda akan menambahkan fungsi untuk memposting dan memperbarui postingan blog perjalanan yang disimpan di Firestore.

Mirip dengan Authentication, fungsi Firestore dikemas dari AngularFire. Setiap dokumen termasuk dalam koleksi, dan setiap dokumen juga dapat memiliki koleksi bertingkat. Anda harus memahami path dokumen di Firestore untuk membuat dan memperbarui postingan blog perjalanan.

Mengimplementasikan TravelService

Karena banyak halaman yang berbeda harus membaca dan memperbarui dokumen Firestore di aplikasi web, kita dapat mengimplementasikan fungsi di src/app/services/travel.service.ts, agar tidak berulang kali memasukkan fungsi AngularFire yang sama di setiap halaman.

Mulailah dengan memasukkan Auth, yang mirip dengan langkah sebelumnya, serta Firestore ke dalam layanan kita. Menentukan objek user$ yang dapat diamati yang memproses status autentikasi saat ini juga berguna.

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

Menambahkan postingan perjalanan

Postingan perjalanan akan menjadi dokumen yang disimpan di Firestore, dan karena dokumen harus ada di dalam koleksi, koleksi yang berisi semua postingan perjalanan akan diberi nama travels. Dengan demikian, jalur postingan perjalanan akan menjadi travels/

Dengan menggunakan fungsi addDoc dari AngularFire, objek dapat disisipkan ke dalam koleksi:

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;

	})
}

Memperbarui dan menghapus data

Dengan uid dari setiap postingan perjalanan, kita dapat menyimpulkan jalur dokumen yang disimpan di Firestore, yang kemudian dapat dibaca, diperbarui, atau dihapus menggunakan fungsi updateFoc dan 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)
}

Membaca data sebagai dapat diamati

Karena postingan dan perhentian perjalanan di sepanjang jalan dapat diubah setelah dibuat, akan lebih berguna jika objek dokumen dapat diobservasi sebagai objek yang dapat diobservasi, untuk mengikuti perubahan yang dibuat. Fungsi ini ditawarkan oleh fungsi docData dan collectionData dari @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[]>
}

Menambahkan perhentian ke postingan perjalanan

Setelah operasi pasca perjalanan disiapkan, sekarang saatnya mempertimbangkan perhentian, yang akan ada di subkoleksi postingan perjalanan seperti berikut: travels//stops/

Cara ini hampir sama dengan membuat postingan perjalanan, jadi tantang diri Anda untuk menerapkannya sendiri, atau lihat implementasinya di bawah ini:

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

Bagus! Fungsi Firestore telah diimplementasikan di layanan Travel, sehingga Anda kini dapat melihat cara kerjanya.

Menggunakan fungsi Firestore di aplikasi

Buka src/app/pages/my-travels/my-travels.component.ts dan masukkan TravelService untuk menggunakan fungsinya.

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

TravelService dipanggil dalam konstruktor untuk mendapatkan array Observable dari semua perjalanan.

Jika hanya perjalanan pengguna saat ini yang diperlukan, gunakan fungsi query.

Metode lain untuk memastikan keamanan mencakup penerapan aturan keamanan, atau penggunaan Cloud Functions dengan Firestore seperti yang dijelaskan dalam langkah-langkah opsional di bawah ini

Kemudian, cukup panggil fungsi yang diimplementasikan di TravelService.

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

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

Sekarang halaman Perjalanan Saya akan berfungsi. Lihat apa yang terjadi di emulator Firestore saat Anda membuat postingan perjalanan baru.

Kemudian, ulangi untuk fungsi update di /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. Mengonfigurasi Penyimpanan

Sekarang Anda akan mengimplementasikan Storage untuk menyimpan gambar dan jenis media lainnya.

Cloud Firestore paling baik digunakan untuk menyimpan data terstruktur, seperti objek JSON. Cloud Storage dirancang untuk menyimpan file atau blob. Di aplikasi ini, Anda akan menggunakannya untuk memungkinkan pengguna membagikan foto perjalanan mereka.

Demikian pula dengan Firestore, menyimpan dan memperbarui file dengan Storage memerlukan ID unik untuk setiap file.

Mari kita implementasikan fungsi di TraveService:

Mengupload file

Buka src/app/services/travel.service.ts dan masukkan Storage dari AngularFire:

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

Kemudian, implementasikan fungsi upload:

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

Perbedaan utama antara mengakses dokumen dari Firestore dan file dari Cloud Storage adalah, meskipun keduanya mengikuti jalur terstruktur folder, kombinasi URL dasar dan jalur diperoleh melalui getDownloadURL, yang kemudian dapat disimpan dan digunakan dalam file .

Menggunakan fungsi dalam aplikasi

Buka src/app/components/edit-stop/edit-stop.component.ts dan panggil fungsi upload menggunakan:

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

Saat gambar diupload, file media itu sendiri akan diupload ke penyimpanan, dan URL disimpan sebagaimana mestinya dalam dokumen di Firestore.

9. Men-deploy aplikasi

Sekarang kita siap men-deploy aplikasi.

Salin konfigurasi firebase dari src/environments/environment.ts ke src/environments/environment.prod.ts, lalu jalankan:

firebase deploy

Anda akan melihat sesuatu seperti ini:

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

Sekarang aplikasi Anda sudah lengkap dan di-deploy ke Firebase Hosting. Semua data dan analisis kini dapat diakses di Firebase Console Anda.

Untuk mengetahui fitur lainnya terkait AngularFire, Functions, dan aturan keamanan, jangan lupa membaca langkah opsional di bawah ini, serta Codelab Firebase lainnya.

11. Opsional: Pelindung autentikasi AngularFire

Bersama dengan Firebase Authentication, AngularFire juga menawarkan penjaga berbasis autentikasi pada rute, sehingga pengguna dengan akses yang tidak memadai dapat dialihkan. Hal ini membantu melindungi aplikasi dari pengguna yang mengakses data yang dilindungi.

Di src/app/app-routing.module.ts, impor

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

Anda kemudian dapat menentukan fungsi sebagai waktu dan tempat pengguna akan dialihkan pada halaman tertentu:

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

Kemudian, cukup tambahkan layanan tersebut ke rute Anda:

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. Opsional: aturan keamanan

Firestore dan Cloud Storage menggunakan aturan keamanan (firestore.rules dan security.rules) untuk menerapkan keamanan dan memvalidasi data.

Saat ini, data Firestore dan Storage memiliki akses terbuka untuk baca dan tulis, tetapi Anda tidak ingin orang-orang berpindah dari postingan orang lain. Anda dapat menggunakan aturan keamanan untuk membatasi akses ke koleksi dan dokumen.

Aturan Firestore

Agar hanya mengizinkan pengguna yang terautentikasi untuk melihat postingan perjalanan, buka file firestore.rules dan tambahkan:

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

Aturan keamanan juga dapat digunakan untuk memvalidasi data:

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

Aturan penyimpanan

Demikian pula, kita dapat menggunakan aturan keamanan untuk menerapkan akses ke database penyimpanan di storage.rules. Perhatikan bahwa kita juga dapat menggunakan fungsi untuk pemeriksaan yang lebih kompleks:

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