我如何解决这个问题的总结/一个可行的解决方案:
在客户端
将登录/当前用户的 uid(例如 creatorId)添加到他们正在创建的实体中。通过将firebase.auth().onAuthStateChanged() User 对象存储在您的应用状态中来访问此 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 来查找创建用户的个人资料信息,并将此信息关联/附加到新实体文档。
这可以通过以下方式完成:
-
在创建新帐户时创建users 集合和单独的user 文档,并使用应用程序有用的字段(例如displayName)填充新的user 文档。这是必需的,因为 Firebase 身份验证系统公开的字段不足以供消费者应用程序使用(例如,displayName 和 avatarURL 未公开),因此您不能仅仅依靠以这种方式查找创建用户的信息。
例如(使用 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)
})
- 现在您已经拥有经过验证的
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 在某些方面非常令人惊叹,并且让一些通常容易的事情(比如这样)变得比他们“应该”更难;总的来说,虽然我是一个主要的粉丝。