Atelier de programmation des frameworks Web angulaires Firebase

1. Ce que vous allez créer

Dans cet atelier de programmation, vous créerez un blog itinérant avec une carte collaborative en temps réel avec la dernière version de notre bibliothèque Angular : AngularFire . L'application Web finale consistera en un blog de voyage sur lequel vous pourrez télécharger des images sur chaque endroit où vous avez voyagé.

AngularFire sera utilisé pour créer l'application Web, Emulator Suite pour les tests locaux, l'authentification pour garder une trace des données utilisateur, Firestore et Storage pour conserver les données et les médias, alimentés par Cloud Functions, et enfin, Firebase Hosting pour déployer l'application.

Ce que vous apprendrez

  • Comment développer localement des produits Firebase avec Emulator Suite
  • Comment améliorer votre application Web avec AngularFire
  • Comment conserver vos données dans Firestore
  • Comment conserver les médias dans le stockage
  • Comment déployer votre application sur Firebase Hosting
  • Comment utiliser Cloud Functions pour interagir avec vos bases de données et API

Ce dont vous aurez besoin

  • Node.js version 10 ou supérieure
  • Un compte Google pour la création et la gestion de votre projet Firebase
  • La CLI Firebase version 11.14.2 ou ultérieure
  • Un navigateur de votre choix, tel que Chrome
  • Compréhension de base d'Angular et de Javascript

2. Obtenez l'exemple de code

Clonez le dépôt GitHub de l'atelier de programmation à partir de la ligne de commande :

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

Alternativement, si git n'est pas installé, vous pouvez télécharger le référentiel sous forme de fichier ZIP .

Le référentiel Github contient des exemples de projets pour plusieurs plates-formes.

Cet atelier de programmation utilise uniquement le dépôt webframework :

  • 📁 webframework : Le code de départ sur lequel vous construirez au cours de cet atelier de programmation.

Installer les dépendances

Après le clonage, installez les dépendances dans le dossier racine et functions avant de créer l'application Web.

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

Installer la CLI Firebase

Installez Firebase CLI à l'aide de cette commande dans un terminal :

npm install -g firebase-tools

Vérifiez à nouveau que votre version de Firebase CLI est supérieure à 11.14.2 en utilisant :

firebase  --version

Si votre version est inférieure à 11.14.2, veuillez mettre à jour en utilisant :

npm update firebase-tools

3. Créez et configurez un projet Firebase

Créer un projet Firebase

  1. Connectez-vous à Firebase .
  2. Dans la console Firebase, cliquez sur Ajouter un projet , puis nommez votre projet Firebase <your-project> . N'oubliez pas l'ID de votre projet Firebase.
  3. Cliquez sur Créer un projet .

Important : Votre projet Firebase sera nommé <your-project> , mais Firebase lui attribuera automatiquement un ID de projet unique sous la forme <your-project>-1234 . Cet identifiant unique est la façon dont votre projet est réellement identifié (y compris dans la CLI), alors que <votre-projet> est simplement un nom d'affichage.

L'application que nous allons créer utilise les produits Firebase disponibles pour les applications Web :

  • Authentification Firebase pour permettre à vos utilisateurs de se connecter facilement à votre application.
  • Cloud Firestore pour enregistrer des données structurées sur le cloud et recevoir une notification instantanée lorsque les données changent.
  • Cloud Storage pour Firebase pour enregistrer des fichiers dans le cloud.
  • Firebase Hosting pour héberger et servir vos actifs.
  • Fonctions pour interagir avec les API internes et externes.

Certains de ces produits nécessitent des configurations spéciales ou doivent être activés à l'aide de la console Firebase.

Ajouter une application Web Firebase au projet

  1. Cliquez sur l'icône Web pour créer une nouvelle application Web Firebase.
  2. À l'étape suivante, vous verrez un objet de configuration. Copiez le contenu de cet objet dans le fichier environments/environment.ts .

Activer la connexion Google pour l'authentification Firebase

Pour permettre aux utilisateurs de se connecter à l'application Web avec leurs comptes Google, nous utiliserons la méthode de connexion Google .

Pour activer la connexion Google :

  1. Dans la console Firebase, localisez la section Build dans le panneau de gauche.
  2. Cliquez sur Authentification , puis cliquez sur l'onglet Méthode de connexion (ou cliquez ici pour y accéder directement).
  3. Activez le fournisseur de connexion Google , puis cliquez sur Enregistrer .
  4. Définissez le nom public de votre application sur <your-project-name> et choisissez un e-mail de support de projet dans le menu déroulant.

Activer Cloud Firestore

  1. Dans la section Build de la console Firebase, cliquez sur Firestore Database .
  2. Cliquez sur Créer une base de données dans le volet Cloud Firestore.
  3. Définissez l'emplacement où vos données Cloud Firestore sont stockées. Vous pouvez laisser cela par défaut ou choisir une région proche de chez vous.

Activer le stockage cloud

L'application Web utilise Cloud Storage pour Firebase pour stocker, télécharger et partager des images.

  1. Dans la section Build de la console Firebase, cliquez sur Storage .
  2. S'il n'y a pas de bouton Commencer , cela signifie que le stockage Cloud est déjà

activé et vous n'avez pas besoin de suivre les étapes ci-dessous.

  1. Cliquez sur Commencer .
  2. Lisez l'avertissement concernant les règles de sécurité de votre projet Firebase, puis cliquez sur Suivant .
  3. L'emplacement Cloud Storage est présélectionné avec la même région que celle que vous avez choisie pour votre base de données Cloud Firestore. Cliquez sur Terminé pour terminer la configuration.

Avec les règles de sécurité par défaut, tout utilisateur authentifié peut écrire n'importe quoi sur Cloud Storage. Nous rendrons notre stockage plus sécurisé plus tard dans cet atelier de programmation.

4. Connectez-vous à votre projet Firebase

L'interface de ligne de commande (CLI) Firebase vous permet d'utiliser Firebase Hosting pour servir votre application Web localement, ainsi que pour déployer votre application Web sur votre projet Firebase.

Assurez-vous que votre ligne de commande accède au répertoire webframework local de votre application.

Connectez le code de l'application Web à votre projet Firebase. Tout d’abord, connectez-vous à la CLI Firebase en ligne de commande :

firebase login

Exécutez ensuite la commande suivante pour créer un alias de projet. Remplacez $YOUR_PROJECT_ID par l'ID de votre projet Firebase.

firebase  use  $YOUR_PROJECT_ID

Ajouter AngularFire

Pour ajouter AngularFire à l'application, exécutez la commande :

ng add @angular/fire

Suivez ensuite les instructions de la ligne de commande et sélectionnez les fonctionnalités qui existent dans votre projet Firebase.

Initialiser Firebase

Pour initialiser le projet Firebase, exécutez :

firebase init

Ensuite, en suivant les invites de la ligne de commande, sélectionnez les fonctionnalités et les émulateurs utilisés dans votre projet Firebase.

Démarrez les émulateurs

Depuis le répertoire webframework , exécutez la commande suivante pour démarrer les émulateurs :

firebase  emulators:start

Finalement, vous devriez voir quelque chose comme ceci :

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

Une fois que vous voyez les ✔All emulators ready! message, les émulateurs sont prêts à être utilisés.

Vous devriez voir l'interface utilisateur de votre application de voyage, qui ne fonctionne pas (encore !) :

Maintenant, passons à la construction !

5. Connectez l'application Web aux émulateurs

D'après le tableau des journaux de l'émulateur, l'émulateur Cloud Firestore écoute sur le port 8080 et l'émulateur d'authentification écoute sur le port 9099.

Ouvrez l'interface utilisateur de l'émulateur

Dans votre navigateur Web, accédez à http://127.0.0.1:4000/ . Vous devriez voir l’interface utilisateur d’Emulator Suite.

Acheminez l'application pour utiliser les émulateurs

Dans src/app/app.module.ts , ajoutez le code suivant à la liste des importations d' 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;
		}),
		...
	]

L'application est désormais configurée pour utiliser des émulateurs locaux, permettant ainsi d'effectuer des tests et du développement localement.

6. Ajout d'une authentification

Maintenant que les émulateurs sont configurés pour l'application, nous pouvons ajouter des fonctionnalités d'authentification pour garantir que chaque utilisateur est connecté avant de publier des messages.

Pour ce faire, nous pouvons importer des fonctions signin directement depuis AngularFire et suivre l'état d'authentification de votre utilisateur avec la fonction authState . Modifiez les fonctions de la page de connexion afin que la page vérifie l'état d'authentification de l'utilisateur au chargement.

Injection d'authentification AngularFire

Dans src/app/pages/login-page/login-page.component.ts , importez Auth depuis @angular/fire/auth et injectez-le dans LoginPageComponent . Les fournisseurs d'authentification, tels que Google, et les fonctions telles que signin et signout peuvent également être directement importés à partir du même package et utilisés dans l'application.

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

La page de connexion est désormais fonctionnelle ! Essayez de vous connecter et consultez les résultats dans l'émulateur d'authentification.

7. Configuration de Firestore

Au cours de cette étape, vous allez ajouter des fonctionnalités permettant de publier et de mettre à jour les articles de blog de voyage stockés dans Firestore.

Semblables à l'authentification, les fonctions Firestore sont préemballées par AngularFire. Chaque document appartient à une collection et chaque document peut également avoir des collections imbriquées. Connaître le path du document dans Firestore est nécessaire pour créer et mettre à jour un article de blog de voyage.

Implémentation de TravelService

Étant donné que de nombreuses pages différentes devront lire et mettre à jour les documents Firestore dans l'application Web, nous pouvons implémenter les fonctions dans src/app/services/travel.service.ts , pour éviter d'injecter à plusieurs reprises les mêmes fonctions AngularFire à chaque page.

Commencez par injecter Auth , comme à l'étape précédente, ainsi que Firestore dans notre service. Définir un objet user$ observable qui écoute l'état d'authentification actuel est également utile.

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

Ajouter un article de voyage

Les articles de voyage existeront sous forme de documents stockés dans Firestore, et comme les documents doivent exister dans les collections, la collection qui contient tous les articles de voyage sera nommée travels . Ainsi, le chemin de tout poste de voyage sera travels/

Grâce à la fonction addDoc d'AngularFire, un objet peut être inséré dans une collection :

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;

	})
}

Mise à jour et suppression de données

Étant donné l'uid de n'importe quel message de voyage, on peut déduire le chemin du document stocké dans Firestore, qui peut ensuite être lu, mis à jour ou supprimé à l'aide des fonctions updateFoc et deleteDoc d'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)
}

Lire des données comme observables

Étant donné que les messages de voyage et les arrêts en cours de route peuvent être modifiés après la création, il serait plus utile d'obtenir des objets document en tant qu'observables, pour s'abonner à toutes les modifications apportées. Cette fonctionnalité est offerte par les fonctions docData et collectionData de @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[]>
}

Ajouter des arrêts à un article de voyage

Maintenant que les opérations des postes de voyage sont configurées, il est temps de considérer les arrêts, qui existeront sous une sous-collection d'un poste de voyage comme ceci : travels/ /stops/ travels/ /stops/

C'est presque identique à la création d'un article de voyage, alors mettez-vous au défi de le mettre en œuvre vous-même, ou consultez la mise en œuvre ci-dessous :

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

Bon! Les fonctions Firestore ont été implémentées dans le service Travel, vous pouvez donc désormais les voir en action.

Utiliser les fonctions Firestore dans l'application

Accédez à src/app/pages/my-travels/my-travels.component.ts et injectez TravelService pour utiliser ses fonctions.

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

TravelService est appelé dans le constructeur pour obtenir un tableau observable de tous les voyages.

Dans le cas où seuls les déplacements de l'utilisateur actuel sont nécessaires, utilisez la fonction query .

D'autres méthodes pour garantir la sécurité incluent la mise en œuvre de règles de sécurité ou l'utilisation de Cloud Functions avec Firestore, comme expliqué dans les étapes facultatives ci-dessous.

Ensuite, appelez simplement les fonctions implémentées dans TravelService .

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

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

La page Mes voyages devrait désormais être fonctionnelle ! Découvrez ce qui se passe dans votre émulateur Firestore lorsque vous créez une nouvelle publication de voyage.

Ensuite, répétez pour les fonctions de mise à jour dans /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. Configuration du stockage

Vous allez maintenant implémenter Storage pour stocker des images et d’autres types de médias.

Cloud Firestore est mieux utilisé pour stocker des données structurées, telles que des objets JSON. Cloud Storage est conçu pour stocker des fichiers ou des blobs. Dans cette application, vous l'utiliserez pour permettre aux utilisateurs de partager leurs photos de voyage.

De même avec Firestore, le stockage et la mise à jour des fichiers avec Storage nécessitent un identifiant unique pour chaque fichier.

Implémentons les fonctions dans TraveService :

Télécharger un fichier

Accédez à src/app/services/travel.service.ts et injectez le stockage depuis AngularFire :

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

Et implémentez la fonction de téléchargement :

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

La principale différence entre l'accès aux documents depuis Firestore et aux fichiers depuis Cloud Storage est que, bien qu'ils suivent tous deux des chemins structurés par dossiers, la combinaison de l'URL de base et du chemin est obtenue via getDownloadURL , qui peut ensuite être stockée et utilisée dans un fichier. déposer.

Utiliser la fonction dans l'application

Accédez à src/app/components/edit-stop/edit-stop.component.ts et appelez la fonction de téléchargement en utilisant :

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

Lorsque l'image est téléchargée, le fichier multimédia lui-même sera téléchargé vers le stockage et l'URL sera stockée en conséquence dans le document dans Firestore.

9. Déploiement de l'application

Nous sommes maintenant prêts à déployer l'application !

Copiez les configurations firebase de src/environments/environment.ts vers src/environments/environment.prod.ts et exécutez :

firebase deploy

Vous devriez voir quelque chose comme ceci :

✔ 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. Félicitations !

Votre application devrait maintenant être complète et déployée sur Firebase Hosting ! Toutes les données et analyses seront désormais accessibles dans votre console Firebase.

Pour plus de fonctionnalités concernant AngularFire, les fonctions, les règles de sécurité, n'oubliez pas de consulter les étapes facultatives ci-dessous, ainsi que d'autres Firebase Codelabs !

11. Facultatif : gardes d'authentification AngularFire

Outre l'authentification Firebase, AngularFire propose également des gardes basées sur l'authentification sur les routes, afin que les utilisateurs ayant un accès insuffisant puissent être redirigés. Cela permet de protéger l'application des utilisateurs accédant aux données protégées.

Dans src/app/app-routing.module.ts , importez

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

Vous pouvez ensuite définir des fonctions indiquant quand et où les utilisateurs doivent être redirigés sur certaines pages :

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

Ajoutez-les ensuite simplement à vos itinéraires :

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. Facultatif : règles de sécurité

Firestore et Cloud Storage utilisent des règles de sécurité ( firestore.rules et security.rules respectivement) pour renforcer la sécurité et valider les données.

Pour le moment, les données Firestore et Storage ont un accès ouvert pour les lectures et les écritures, mais vous ne voulez pas que les gens modifient les publications des autres ! Vous pouvez utiliser des règles de sécurité pour restreindre l'accès à vos collections et documents.

Règles Firestore

Pour autoriser uniquement les utilisateurs authentifiés à consulter les publications de voyage, accédez au fichier firestore.rules et ajoutez :

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

Des règles de sécurité peuvent également être utilisées pour valider les données :

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

Règles de stockage

De même, nous pouvons utiliser des règles de sécurité pour imposer l'accès aux bases de données de stockage dans storage.rules . Notez que nous pouvons également utiliser des fonctions pour des contrôles plus complexes :

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