Codelab Firebase Angular Web Frameworks

1. Qué crearás

En este codelab, compilarás un blog de viajes con un mapa colaborativo en tiempo real con lo más reciente de nuestra biblioteca de Angular: AngularFire. La aplicación web final constará de un blog de viajes en el que podrás subir imágenes a cada ubicación a la que hayas viajado.

Se usará AngularFire para compilar la app web, Emulator Suite para pruebas locales, Authentication para hacer un seguimiento de los datos del usuario, Firestore y Storage para conservar datos y contenido multimedia, con la tecnología de Cloud Functions, y, por último, Firebase Hosting para implementar la app.

Qué aprenderás

  • Cómo desarrollar con productos de Firebase de forma local mediante Emulator Suite
  • Cómo mejorar tu aplicación web con AngularFire
  • Cómo conservar tus datos en Firestore
  • Cómo conservar contenido multimedia en Storage
  • Cómo implementar tu app en Firebase Hosting
  • Cómo usar Cloud Functions para interactuar con tus bases de datos y APIs

Requisitos

  • Node.js (versión 10 o una posterior)
  • Una Cuenta de Google para la creación y administración de tu proyecto de Firebase
  • Versión 11.14.2 o posterior de Firebase CLI
  • Un navegador de tu elección, como Chrome
  • Conocimientos básicos de Angular y JavaScript

2. Obtén el código de muestra

Clona el repositorio de GitHub del codelab desde la línea de comandos:

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

Como alternativa, si no tienes Git instalado, puedes descargar el repositorio como archivo ZIP.

El repositorio de GitHub contiene proyectos de muestra para varias plataformas.

En este codelab, solo se usa el repositorio del framework web:

  • consulta webframework: Es el código de inicio que usarás para compilar durante este codelab.

Instala dependencias

Después de la clonación, instala las dependencias en la carpeta raíz y functions antes de compilar la app web.

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

Instala Firebase CLI

Instala Firebase CLI con este comando en una terminal:

npm install -g firebase-tools

Vuelve a verificar que tu versión de Firebase CLI sea superior a 11.14.2 mediante lo siguiente:

firebase  --version

Si tu versión es anterior a la 11.14.2, actualízala con:

npm update firebase-tools

3. Crea y configura un proyecto de Firebase

Crea un proyecto de Firebase

  1. Accede a Firebase.
  2. En Firebase console, haz clic en Agregar proyecto y asígnale el nombre <your-project>. Recuerda el ID del proyecto de Firebase.
  3. Haz clic en Crear proyecto.

Importante: El nombre de tu proyecto de Firebase será <your-project>, pero Firebase le asignará automáticamente un ID único del proyecto con el formato <your-project>-1234. Este identificador único es la forma en que se identifica realmente tu proyecto (incluso en la CLI), mientras que <your-project> es simplemente un nombre visible.

La aplicación que compilaremos usa productos de Firebase disponibles para las aplicaciones web:

  • Firebase Authentication, a fin de permitir que los usuarios accedan a tu app con facilidad
  • Cloud Firestore, a fin de guardar datos estructurados en la nube y recibir notificaciones al instante cuando se modifiquen los datos
  • Cloud Storage para Firebase, a fin de guardar archivos en la nube
  • Firebase Hosting, a fin de alojar y entregar sus recursos
  • Funciones para interactuar con APIs internas y externas.

Algunos de estos productos necesitan configuraciones especiales o se deben habilitar mediante Firebase console.

Agregar una app web de Firebase al proyecto

  1. Haga clic en el ícono de Web para crear una nueva aplicación web de Firebase.
  2. En el siguiente paso, verás un objeto de configuración. Copia el contenido de este objeto en el archivo environments/environment.ts.

Habilita el acceso de Google para Firebase Authentication.

Para permitir que los usuarios accedan a la app web con sus Cuentas de Google, usaremos el método de acceso de Google.

Para habilitar el acceso con Google, haz lo siguiente:

  1. En Firebase console, localiza la sección Compilación en el panel izquierdo.
  2. Haz clic en Authentication y, luego, en la pestaña Sign-in method (o haz clic aquí para ir directamente allí).
  3. Habilita el proveedor de acceso de Google y, luego, haz clic en Guardar.
  4. Configura el nombre público de tu app como <your-project-name> y elige un Correo electrónico de asistencia del proyecto en el menú desplegable.

Habilitar Cloud Firestore

  1. En la sección Compilación de Firebase console, haz clic en Base de datos de Firestore.
  2. Haz clic en Crear base de datos en el panel de Cloud Firestore.
  3. Configura la ubicación en la que se almacenan tus datos de Cloud Firestore. Puedes dejar esta opción como predeterminada o elegir una región cercana.

Habilita Cloud Storage

La aplicación web usa Cloud Storage para Firebase para almacenar, subir y compartir imágenes.

  1. En la sección Compilación de Firebase console, haz clic en Almacenamiento.
  2. Si no ves el botón Comenzar, significa que Cloud Storage ya está

y no es necesario que sigas los pasos que se indican a continuación.

  1. Haz clic en Comenzar.
  2. Lee la renuncia de responsabilidad sobre las reglas de seguridad para el proyecto de Firebase y, luego, haz clic en Siguiente.
  3. La ubicación de Cloud Storage está preseleccionada con la misma región que elegiste para la base de datos de Cloud Firestore. Haz clic en Listo para completar la configuración.

Con las reglas de seguridad predeterminadas, cualquier usuario autenticado puede escribir cualquier cosa en Cloud Storage. Más adelante en este codelab, aumentaremos la seguridad del almacenamiento.

4. Conéctate a tu proyecto de Firebase

La interfaz de línea de comandos (CLI) de Firebase te permite usar Firebase Hosting para entregar tu app web de manera local y también implementarla en tu proyecto de Firebase.

Asegúrate de que la línea de comandos acceda al directorio local webframework de tu app.

Conecta el código de la aplicación web a tu proyecto de Firebase. Primero, accede a Firebase CLI en la línea de comandos:

firebase login

Luego, ejecuta el comando siguiente para crear un alias del proyecto. Reemplaza $YOUR_PROJECT_ID por el ID del proyecto de Firebase.

firebase  use  $YOUR_PROJECT_ID

Agregar AngularFire

Para agregar AngularFire a la app, ejecuta el siguiente comando:

ng add @angular/fire

Luego, sigue las instrucciones de la línea de comandos y selecciona las funciones que existen en tu proyecto de Firebase.

Inicializa Firebase

Para inicializar el proyecto de Firebase, ejecuta el siguiente comando:

firebase init

Luego, sigue las indicaciones de la línea de comandos y selecciona las funciones y los emuladores que se usaron en tu proyecto de Firebase.

Inicia los emuladores

Desde el directorio webframework, ejecuta el siguiente comando para iniciar los emuladores:

firebase  emulators:start

Con el tiempo, deberías ver algo como esto:

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

Una vez que veas el mensaje ✔All emulators ready!, los emuladores estarán listos para usar.

Deberías ver la IU de tu app de viajes, que (aún) no funciona:

¡Ahora comencemos a desarrollar!

5. Conecta la app web a los emuladores

Según la tabla de los registros del emulador, el emulador de Cloud Firestore escucha en el puerto 8080 y el emulador de Authentication en el puerto 9099.

Cómo abrir EmulatorUI

En tu navegador web, ve a http://127.0.0.1:4000/. Deberías ver la IU de Emulator Suite.

Cómo enrutar la app para usar los emuladores

En src/app/app.module.ts, agrega el siguiente código a la lista de importaciones de 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;
		}),
		...
	]

Ahora, la app está configurada para usar emuladores locales, lo que permite que las pruebas y el desarrollo se realicen de forma local.

6. Agrega autenticación

Ahora que los emuladores están configurados para la app, podemos agregar funciones de Authentication para garantizar que cada usuario acceda antes de publicar mensajes.

Para ello, podemos importar funciones signin directamente desde AngularFire y realizar un seguimiento del estado de autenticación del usuario con la función authState. Modifica las funciones de la página de acceso para que la página verifique el estado de autenticación del usuario durante la carga.

Cómo insertar la autenticación de AngularFire

En src/app/pages/login-page/login-page.component.ts, importa Auth desde @angular/fire/auth y, luego, insértalo en el LoginPageComponent. Los proveedores de autenticación, como Google, y funciones como signin y signout también pueden importarse directamente desde el mismo paquete y usarse en la app.

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

Ahora la página de acceso funciona. Intenta acceder y consulta los resultados en el emulador de Authentication.

7. Configura Firestore

En este paso, agregarás funcionalidad para publicar y actualizar entradas de blog de viajes almacenadas en Firestore.

Al igual que Authentication, las funciones de Firestore vienen empaquetadas previamente desde AngularFire. Cada documento pertenece a una colección y cada documento también puede tener colecciones anidadas. Es necesario conocer el path del documento en Firestore para crear y actualizar una entrada de blog de viajes.

Cómo implementar TravelService

Dado que muchas páginas diferentes necesitarán leer y actualizar documentos de Firestore en la app web, podemos implementar las funciones en src/app/services/travel.service.ts para abstenernos de insertar repetidamente las mismas funciones de AngularFire en cada página.

Comienza por insertar Auth, de forma similar al paso anterior, así como Firestore en nuestro servicio. Definir un objeto user$ observable que escucha el estado de autenticación actual también es útil.

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

Agregar una publicación de viajes

Las publicaciones de viajes existirán como documentos que se almacenan en Firestore y, como los documentos deben existir en las colecciones, la colección que contiene todas las publicaciones de viajes se llamará travels. Por lo tanto, la ruta de cualquier publicación de viaje será travels/

Con la función addDoc de AngularFire, se puede insertar un objeto en una colección:

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;

	})
}

Actualiza y borra datos

Según el UID de cualquier publicación de viaje, se puede deducir la ruta del documento almacenado en Firestore, que luego se puede leer, actualizar o borrar con las funciones updateFoc y deleteDoc de 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)
}

Lectura de datos como un elemento observable

Dado que las publicaciones de viajes y las paradas a lo largo del camino se pueden modificar después de su creación, sería más útil obtener los objetos del documento como observables para suscribirse a cualquier cambio que se hiciera. Esta funcionalidad la ofrecen las funciones docData y 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[]>
}

Cómo agregar paradas a una publicación de viajes

Ahora que ya se establecieron las operaciones posteriores a un viaje, es momento de considerar las paradas, que aparecerán en una subcolección de un puesto de viaje como este: travels//stops/

Esto es casi idéntico a crear una publicación de viaje, así que anímate a implementarlo por tu cuenta, o bien consulta la implementación a continuación:

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

¡Genial! Las funciones de Firestore se implementaron en el servicio de viajes, por lo que ahora puedes verlas en acción.

Usa funciones de Firestore en la app

Navega a src/app/pages/my-travels/my-travels.component.ts y, luego, inserta TravelService para usar sus funciones.

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

Se llama a TravelService en el constructor para obtener un array observable de todos los viajes.

En el caso en que solo se necesiten los viajes del usuario actual, usa la función query.

Otros métodos para garantizar la seguridad incluyen implementar reglas de seguridad o usar Cloud Functions con Firestore, como se explora en los pasos opcionales a continuación

Luego, simplemente llama a las funciones implementadas en TravelService.

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

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

Ahora la página Mis viajes debería funcionar. Descubre lo que sucede en el emulador de Firestore cuando creas una nueva publicación de viajes.

Luego, repite el proceso para las funciones de actualización en /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. Configuración del almacenamiento

Ahora, implementarás Storage para almacenar imágenes y otros tipos de contenido multimedia.

Cloud Firestore se usa mejor para almacenar datos estructurados, como objetos JSON. Cloud Storage está diseñado para almacenar archivos o BLOB. En esta app, la usarás para permitir que los usuarios compartan sus fotos de viajes.

Del mismo modo con Firestore, almacenar y actualizar archivos con Storage requiere un identificador único para cada archivo.

Implementaremos las funciones en TraveService:

Carga un archivo

Navega a src/app/services/travel.service.ts y, luego, inserta Storage desde AngularFire:

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

Implementa la función de carga:

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 diferencia principal entre acceder a documentos desde Firestore y archivos desde Cloud Storage es que, aunque ambos siguen rutas estructuradas de carpetas, la combinación de URL base y ruta de acceso se obtiene a través de getDownloadURL, que luego se puede almacenar y usar en un archivo .

Cómo usar la función en la app

Navega a src/app/components/edit-stop/edit-stop.component.ts y llama a la función de carga con el siguiente comando:

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

Cuando se suba la imagen, el archivo multimedia se subirá al almacenamiento, y la URL, según corresponda, en el documento en Firestore.

9. Implementa la aplicación

Ya está todo listo para implementar la aplicación.

Copia los parámetros de configuración firebase de src/environments/environment.ts a src/environments/environment.prod.ts y ejecuta lo siguiente:

firebase deploy

Deberías ver algo como esto:

✔ 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. ¡Felicitaciones!

Ahora tu aplicación debería estar completa y, luego, implementada en Firebase Hosting. Ahora podrás acceder a todos los datos y estadísticas en Firebase console.

Para obtener más funciones relacionadas con AngularFire, Functions y reglas de seguridad, no olvides revisar los pasos opcionales que se indican a continuación, así como otros Codelabs de Firebase.

11. Opcional: protecciones de autenticación de AngularFire

Junto con Firebase Authentication, AngularFire también ofrece protecciones basadas en la autenticación en las rutas, para que los usuarios con acceso insuficiente puedan ser redirigidos. Esto ayuda a proteger la app de los usuarios que acceden a datos protegidos.

En src/app/app-routing.module.ts, importa

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

Luego, puedes definir funciones sobre cuándo y a dónde se les debería redireccionar a los usuarios en determinadas páginas:

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

Luego, simplemente agrégalos a tus rutas:

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. Reglas de seguridad (opcional)

Firestore y Cloud Storage usan reglas de seguridad (firestore.rules y security.rules respectivamente) para aplicar la seguridad y validar los datos.

Por el momento, los datos de Firestore y Storage tienen acceso abierto para las operaciones de lectura y escritura, pero no querrás que las personas cambien las publicaciones de los demás. Puedes usar reglas de seguridad para restringir el acceso a tus colecciones y documentos.

Reglas de Firestore

Para permitir que solo los usuarios autenticados vean publicaciones de viajes, ve al archivo firestore.rules y agrega lo siguiente:

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

Las reglas de seguridad también se pueden usar para validar datos:

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

Reglas de almacenamiento

Del mismo modo, podemos usar reglas de seguridad para aplicar de manera forzosa el acceso a las bases de datos de almacenamiento en storage.rules. Ten en cuenta que también podemos usar funciones para verificaciones más complejas:

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