从Firebase的云功能中的Firestore触发器获取用户ID?

时间:2017-10-24 13:44:01

标签: firebase google-cloud-functions google-cloud-firestore

在下面的示例中,有没有办法获取写入'offers / {offerId}'的用户的用户ID(uid)?我尝试按照here所述进行操作,但它在Firestore中不起作用。

exports.onNewOffer = functions.firestore
  .document('offers/{offerId}')
  .onCreate(event => {
    ...
});

10 个答案:

答案 0 :(得分:16)

我在这方面挣扎了一段时间,最后联系了火力支援部门:

I was trying to achieve this.

在firestore数据库触发器的事件对象中未定义event.auth.uid。 (它适用于实时数据库触发器)

当我console.log(event)时,我在输出中找不到任何auth

官方支持回答:

  

抱歉,尚未在Firestore SDK中添加身份验证。我们将它列在下一个功能中。

     

请留意我们的发行说明,了解任何进一步的更新。

我希望这可以节省几个小时。

答案 1 :(得分:2)

在将此功能添加到firestore功能之前,解决方法是在创建文档时将user_id添加为字段,然后删除。然后,您可以在onCreate函数中获取它,然后在将其用于所需内容之后,在函数中,只需删除该文档中的字段。

答案 2 :(得分:2)

如上所述,解决方法是在数据本身中添加一个user_id字段,然后在服务器上读取它。

此方法的缺点是安全漏洞。由于我们没有在服务器上验证用户ID,因此其他任何用户都可以通过向其他用户发送其ID和数据来模拟其他用户。

对于安全性至关重要的应用程序,解决方案将是使用安全性规则来验证是否已将正确的user_id与数据一起发送

allow write: if resource.data.user_id == request.auth.uid;

答案 3 :(得分:2)

documentation明确指出context.auth参数仅在实时数据库中可用。

此字段仅用于实时数据库触发器和 可调用函数。对于未经身份验证的用户,此字段为null。 对于Firebase管理员用户和不提供用户的事件类型 信息,该字段不存在。

我个人意识到我的数据路径中已经有userId。

export const onCreate = functions.firestore.document('docs/{userId}/docs/{docId}')
    .onCreate((snapshot, context) => {
        const userId = context.params.userId;

答案 4 :(得分:0)

关于snap._fieldsProto.uid.stringValue

示例:

exports.hello = functions.firestore.document('hello/{worldId}').onCreate((snap, context) => {
   console.log(snap._fieldsProto.uid.stringValue)
});

答案 5 :(得分:0)

我如何解决此问题/可行的解决方案的摘要:

在客户端上

将登录的/当前用户的uid(例如,creatorId)添加到他们正在创建的实体中。通过将firebase.auth().onAuthStateChanged()用户对象存储在您的应用状态中来访问此uid。

在Firebase Firestore /数据库中

create添加一个安全规则,以验证客户端提供的creatorId值是否与经过身份验证的用户的uid相同;现在您知道客户端没有在欺骗creatorId,并且可以在其他地方信任此值。

例如

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

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

在Firebase功能中

向您创建的实体类型添加onCreate触发器,以使用客户端提供的,现已验证的creatorId来查找创建用户的个人资料信息,并将该信息关联/附加到新的实体文件

这可以通过以下方式完成:

  1. 在创建新帐户时创建users集合和单个user文档,并使用对应用有用的字段(例如user填充新的displayName文档)。这是必需的,因为Firebase身份验证系统公开的字段不足以供消费者应用使用(例如,未公开displayNameavatarURL),因此您不能仅依靠查找创建用户的信息这样。

    例如(使用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. 现在,您拥有一个经过验证的creatorId值和有用的user对象,请向您的实体类型(或所有创建的实体)添加一个onCreate触发器,以查找创建用户的信息并将其附加到创建的对象。
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 })
})

这显然会导致整个系统中出现大量重复的用户信息数据-并且您可以做一些清理工作(在上面的实现中,'creatorId'在创建的实体上是重复的)-但现在超级好了易于显示谁在您的整个应用程序中创建了东西,并且似乎是“ Firebase方式”。

希望这会有所帮助。我发现Firebase在某些方面非常出色,并且使一些通常容易的事情(像这样)比他们“应该”变得更难。总的来说,尽管我是一个主要的粉丝。

答案 6 :(得分:0)

这应该可以解决问题:

exports.newMessage = functions.firestore
        .document('groups/messages/{messageId}')
        .onCreate((snap, context) => {
            var fromId = snap.data().fromId;

答案 7 :(得分:0)

exports.f1 = functions.firestore
    .document('collectionname/{id}')
    .onCreate ((snap, context) => {
      const uid = snap.id;
...
exports.f2 = functions.firestore
    .document('collectionname/{id}')
    .onUpdate ((change, context) => {
      const uid = change.after.id;
...

答案 8 :(得分:0)

您可以通过Callable函数添加数据,从中可以访问当前用户ID:

exports.addNewOffer = functions.https.onCall(async (data, context) => {
  const uid = context.auth.uid
  const writeResult = await admin.firestore().collection('offers').add({ ... })
  ...
  return { id: writeResult.id, ... }
})

答案 9 :(得分:-1)

您可以通过在用户上调用getIdToken()来获取当前的登录用户tokenId:https://firebase.google.com/docs/reference/functions/functions.auth.UserInfo