¿Obtener la identificación de usuario de un activador de Firestore en Cloud Functions para Firebase?

Resuelto Gabriel Bessa asked hace 54 años • 10 respuestas

En el siguiente ejemplo, ¿hay alguna manera de obtener la identificación de usuario (uid) del usuario que escribió en 'ofertas/{offerId}'? Intenté hacer lo que se describe aquí pero no funciona en Firestore.

exports.onNewOffer = functions.firestore
  .document('offers/{offerId}')
  .onCreate(event => {
    ...
});
Gabriel Bessa avatar Jan 01 '70 08:01 Gabriel Bessa
Aceptado

Estuve luchando con esto por un tiempo y finalmente me comuniqué con el soporte de Firebase:

Estaba tratando de lograr esto.

No event.auth.uidestá definido en el objeto de evento para los activadores de la base de datos de Firestore. (Funciona para los activadores de bases de datos en tiempo real)

Cuando console.log(event)no puedo encontrar ninguno authen la salida.

La respuesta oficial de soporte:

Lo sentimos, la autenticación aún no se ha agregado en el SDK de Firestore. Lo tenemos enumerado en las siguientes características.

Esté atento a nuestras notas de la versión para obtener más actualizaciones.

Espero que esto le ahorre a alguien unas horas.

ACTUALIZAR:

El problema se solucionó y la función nunca se implementará:

Hola a todos de nuevo. Otra actualización. Se ha decidido que, lamentablemente, el soporte nativo para context.auth para los activadores de Firestore no se implementará debido a limitaciones técnicas. Sin embargo, se está trabajando en una solución diferente que, con suerte, satisfará su caso de uso, pero no puedo compartir detalles. En este foro generalmente mantenemos abiertos solo los problemas que se pueden resolver dentro del propio SDK de funciones. He mantenido este abierto porque parecía importante y quería proporcionar algunas actualizaciones sobre los errores internos que rastrean este trabajo. Ahora que se ha tomado una decisión, voy a cerrar esto. Gracias de nuevo por la paciencia de todos y lamento no tener mejores noticias. Utilice la solución alternativa a la que se hace referencia aquí .

Tim avatar Nov 29 '2017 17:11 Tim

Resumen de cómo resolví esto/una solución viable:

En cliente

Agregue el uid del usuario registrado/actual (por ejemplo, como creatorId) a la entidad que están creando. Acceda a este uid almacenando el firebase.auth().onAuthStateChanged()objeto Usuario en el estado de su aplicación.

En Firebase Firestore/Base de datos

Agregue una regla de seguridad para createvalidar que el valor proporcionado por el cliente creatorIdsea el mismo que el uid del usuario autenticado; Ahora sabes que el cliente no está falsificando creatorIdy puede confiar en este valor en otra parte.

p.ej

match /entity/{entityId} {
  allow create: if madeBySelf();
}

function madeBySelf() {
  return request.auth.uid == request.resource.data.creatorId;
}

En funciones de Firebase

Agregue un onCreateactivador a su tipo de entidad creado para usar la información proporcionada por el cliente y ahora validada creatorIdpara buscar la información del perfil del usuario creador y asociar/agregar esta información al nuevo documento de entidad.

Esto se puede lograr mediante:

  1. Crear una userscolección y userdocumentos individuales cuando se crean nuevas cuentas y completar el nuevo userdocumento con campos útiles para la aplicación (por ejemplo displayName). Esto es necesario porque los campos expuestos por el sistema de autenticación de Firebase son insuficientes para los usos de las aplicaciones del consumidor (por ejemplo, displayNamey avatarURLno están expuestos), por lo que no puede confiar simplemente en buscar la información del usuario creador de esa manera.

    por ejemplo (usando ES6)

import * as functions from 'firebase-functions'
import * as admin from 'firebase-admin'

const APP = admin.initializeApp()

export const createUserRecord = functions.auth.user()
  .onCreate(async (userRecord, context) => {
    const userDoc = {
      id: userRecord.uid,
      displayName: userRecord.displayName || "No Name",
      avatarURL: userRecord.photoURL || '',
    }
    return APP.firestore().collection('users').doc(userRecord.uid).set(userDoc)
  })
  1. Ahora que tiene un creatorIdvalor validado y userobjetos útiles, agregue un onCreateactivador a su tipo de entidad (o a todas sus entidades creadas) para buscar la información del usuario creador y agregarla al objeto creado.
export const addCreatorToDatabaseEntry = functions.firestore
  .document('<your entity type here>/{entityId}')
  .onCreate(async (snapshot, context) => {
    const userDoc = await APP.firestore().collection('users').doc(snapshot.data().creatorId).get()
    return snapshot.ref.set({ creator: userDoc.data() }, { merge: true })
})

Esto claramente conduce a una gran cantidad de datos de información de usuario duplicados en todo su sistema, y ​​hay un poco de limpieza que puede hacer ('creatorId` está duplicado en la entidad creada en la implementación anterior), pero ahora es muy fácil de mostrar. quién creó qué en toda su aplicación, y parece ser "al estilo Firebase".

Espero que esto ayude. Descubrí que Firebase es súper sorprendente en algunos aspectos y hace que algunas cosas normalmente fáciles (como esta) sean más difíciles de lo que "deberían" ser; A fin de cuentas, soy un gran admirador.

Ethan avatar May 01 '2019 20:05 Ethan