🖼️ Imágenes personalizadas con Firebase Cloud Functions y Gravatar.
Tags: firebase, programming, webdev, tutorial
Published: 2023-03-10 15:32:47

Firebase Authentication nos proporciona un número  de proveedores que nos permiten autenticar usuarios en nuestra aplicación rápidamente y sin tener que invertir tiempo en revisar la documentación de cada uno de ellos para entender cómo interactuar con sus API. Esto nos permite centrarnos más en desarrollar un producto más agradable para los usuarios y eficiente a nivel de performance y arquitectura aprovechando las bondades de la plataforma. 

Estos son los proveedores de identidad disponibles en Firebase hasta el momento de la publicación de este articulo


![Proveedores de Identidad de Firebase](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ufhwbuyvfmejk490cuib.png)

Cada uno de ellos nos proporcionará toda la información disponible  que el proveedor posee sobre ese usuario, cuando hablo de información estoy haciendo referencia a información básica  no sensible del usuario, como por ejemplo: 

- Nombre
- Correo electrónico.
- Imagen de perfil.
- entre otros…

Con toda la info podemos personalizar las sesiones de los usuarios y brindar una experiencia más agradable, con el fin de promover el uso de la aplicación, atraer mas usuarios y por ende incrementar las ventas. Pero, que pasa con aquellos proveedores que no retornan en su data información útil para nuestra causa?,  como por ejemplo una imagen de perfil. 

Un caso común de este escenario sería utilizar la creación de un nuevo usuario por [correo electrónico y contraseña](https://firebase.google.com/docs/auth/web/password-auth?hl=es). Para ello vamos a usar las [Firebase Cloud Functions](https://firebase.google.com/docs/functions/use-cases?hl=es_419), con los [triggers o disparadores de Autenticación](https://firebase.google.com/docs/functions/auth-events), más específicamente `onCreate()`. 

Según la documentación, este trigger se ejecutará cuando:

>
>- Un usuario crea una cuenta de correo electrónico y una contraseña.
>- Un usuario accede por primera vez con un proveedor de identidad federada.
>- El desarrollador crea una cuenta con el SDK de Firebase Admin.
>- Un usuario accede a una sesión de autenticación anónima por primera vez.
>
>Un evento Cloud Functions *no* se activa cuando un usuario accede por primera vez con un token personalizado

La función `onCreate` espera 2 argumentos como parámetros:

- **user,** de tipo [UserRecord](https://firebase.google.com/docs/reference/admin/node/firebase-admin.auth.userrecord), con el cual tendremos acceso a los atributos del usuario.
- **context**, de tipo [EventContext](https://firebase.google.com/docs/reference/functions/firebase-functions.eventcontext.md#eventcontext_interface), donde tendremos la información del contexto del evento en la función que se esta ejecutando.

```typescript
export const newUser = functions.auth.user().onCreate(async (user: UserRecord, context: EventContext) =>  {
   // Acá va la lógica 
});
```

Si bien la función espera 2 argumentos, en segundo,`context` es opcional.  Una vez que el `onCreate` se ejecuta tenemos que verificar si la propiedad `photoURL` dentro del para tiene algún valor o no para proceder a agregarle nuestra imagen por defecto. 


```typescript
export const newUser = functions.auth.user().onCreate(async (user: UserRecord, context: EventContext) =>  {
    logger.info('Usuario original',{user});
    try {
        let updateUserInfo;
        if(!user.photoURL) {
           // Acá va la lógica
        }

        logger.info('Se actualizo correctamente', {updateUserInfo});
    } catch (e) {
        logger.error('Hubo un error en la función newUser', e)
    }
    
});

```

Ahora, qué opciones tenemos?.

## Imagen estática de una CDN

Esta es la opción más utilizada y sencilla a la hora de agregar una imagen personalizada a un nuevo usuario. Lo único que debemos hacer es alojar la imagen que deseemos mostrar en alguna CDN y una vez que se creen un nuevo usuario, asignarle a la propiedad `photoUrl`, la direccción absoluta de la imagen alojado en la CDN.

```typescript
export const newUser = functions.auth.user().onCreate(async (user: UserRecord, context: EventContext) =>  {
    logger.info('Usuario original',{user});
    try {
        let updateUserInfo;
        if(!user.photoURL) {
            updateUserInfo = await admin.auth().updateUser(user.uid, {
                photoURL: 'https://firebase.google.com/static/images/homepage/home-icon-release_2x.png'
            });
        }

        logger.info('Se actualizo correctamente', {updateUserInfo});
    } catch (e) {
        logger.error('Hubo un error en la función newUser', e)
    }
    
});
```

Si queremos llevar nuestra experiencia de usuario al siguiente nivel podemos usar algunas opciones que nos da **[Gravatar](https://es.gravatar.com/)**

## Qué es Gravatar?

Según Wikipedia Gravatar: 

> Es un servicio que ofrece un avatar único globalmente
> 

Este permite asociar una dirección de correo electrónica a una imagen y así poder tener una misma imagen en distintas plataformas.

Esta plataforma nos permite crear imágenes aleatorias basadas en un hash [MD5](https://en.wikipedia.org/wiki/MD5) de un correo electrónico, brindando la libertad de elegir entre: 

- Siluetas
- Patrónes geométricos ([identicon](https://en.wikipedia.org/wiki/Identicon)).
- Mounstruos.
- Robots, entre otros.


![Tipos de imagenes aleatorias - Gravatar](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l7e34iqpqs0oefhheqhx.png)

Si quieres conocer cuales son todos los tipos de imágenes aleatoria que puedes usar te recomiendo [visitar este link](https://en.gravatar.com/site/implement/images/). El próximo paso seria implementar un tipo de estas imágenes en nuestra cloud function. 

## Imagen personalizadas con Gravatar + Cloud Functions

Para este ejemplo hemos decidido implementar los patrones geométricos o [Identicon](https://en.wikipedia.org/wiki/Identicon) a todos los usuarios que creemos en nuestra aplicación, y para ellos debemos armar una URL siguiendo el siguiente patron:

`https://www.gravatar.com/avatar/{hash-md5-email}.jpg?d={tipo-imagen}`

Para crear el hash md5 vamos a utilizar el paquete [ts-md5](https://www.npmjs.com/package/ts-md5) en NPM. En este ejemplo estamos usando ts-md5 porque he configurado mis cloud functions en typescript Si en tu proyecto no estás usando typescript puedes buscar una librería que mas te agrade o se ajuste a tus necesidades.

```typescript
export const newUser = functions.auth.user().onCreate(async (user: UserRecord, context: EventContext) =>  {
    logger.info('Usuario original',{user});
    try {
        let updateUserInfo;
        const hash = Md5.hashStr(`${user.email}`);
        if(!user.photoURL) {
            updateUserInfo = await admin.auth().updateUser(user.uid, {
                photoURL: `https://www.gravatar.com/avatar/${hash}.jpg?d=identicon`
            });
        }

        logger.info('Se actualizo correctamente', {updateUserInfo});
    } catch (e) {
        logger.error('Hubo un error en la función newUser', e)
    }
    
});

```

En la línea 5, se puede ver cómo se hace la creación del hash md5 basado en la dirección de correo del usuario. En la línea 8 le asignamos al campo `photoUrl` la url de siguiendo el patron que nos indica gravatar, con el hash del email y el tipo de imagen que deseamos crear. 

[En este link](https://gist.github.com/Villanuevand/2ff04d801fc2b551cb506cf9c5ada854) te voy a dejar el fragmento de código de la cloud function.


Cuentame como te fue en la implementación de esta funcionalidad. 

Si te gustó no olvides hacermelo saber con un like o compartiendo tus impresiones conmigo en twitter, donde me puedes conseguir como [@villanuevand](https://twitter.com/villanuevand) o enviando un mail a 
<a href="mailto:name@gmail.com"> heypana@villanuevand.dev</a> 


Nos vemos en el próximo post mis panas.