【问题标题】:Firebase Functions won't read document on FirestoreFirebase 函数不会读取 Firestore 上的文档
【发布时间】:2021-03-24 21:57:29
【问题描述】:

您好,我正在尝试使用 Firebase 函数读取存储在 Firestore 中的用户文档。每个用户都有一个独特的文档,其中包含无法存储在 Firebase Auth 上的额外数据。文档名称是用户 UID。 但是当我试图在我的可调用函数上阅读它时,我无法访问它。

创建用户时创建文档的代码:

exports.createdacc = functions.auth.user().onCreate(user => {

console.log('User created', user.phoneNumber);
return admin.firestore().collection('users').doc(user.uid).set({
    number: user.phoneNumber,
    verified: false,
});

});

读取该文档的可调用函数,以便我做出一些决定

exports.checkVerification = functions.https.onCall((data, context) => {
if (!context.auth){
    throw new functions.https.HttpsError('unauthenticated');
}
console.log('user is ', context.auth.uid);
const user = admin.firestore().collection('users').doc(context.auth.uid);
user.get().then(doc => {    
    //temp code -- Not working 
    console.log('data read');
    if (doc.get().verified){
        console.log('verified');
    } else {
        console.log('not verified');
    }
    return "success";
}).catch(error => {
    throw new functions.https.HttpsError('internal');
});
});

为什么我看不懂文档?里面什么都没有执行。

【问题讨论】:

  • 您是否在firebase控制台中检查过文档是否已创建
  • @development-ninja 是的,文档存在。我什至可以使用库从 android 访问它。
  • 好的,你在可调用函数中得到了正确的 context.auth.uid 吗?
  • @development-ninja 是的,uid 匹配。

标签: node.js firebase google-cloud-firestore google-cloud-functions


【解决方案1】:

我有时看到,通过上下文和数据进入函数的信息实际上是 JSON,而不是严格标准的 Javascript 对象。在类似的匹配问题中(在我的例子中,context.auth.token 上的 customClaim),我必须做类似的事情:

JSON.parse(JSON.stringify(context.auth.token.customCLaim))

它们表现像一个对象(即我可以调用/分配 context.auth.token.customClaim),但来自 console.log 的结果不同。

console.log(context.auth.token.customCLaim);
//prints {"userID": "1234567890"}

console.log(JSON.parse(JSON.stringify(context.auth.token.customClaim)));
//prints {userID: "1234567890"}

微妙,但它在一些身份验证案例中让我感到困惑。

【讨论】:

    【解决方案2】:

    你没有返回user.get().then(...);返回的promise:你的Cloud Function可能在异步工作完成和响应发送回前端之前被清理干净。

    注意doc.get().verified是不正确的:正如你将在doc中看到的,你需要将特定字段的字段路径传递给这个方法。所以要么你做doc.get("verified"),要么你可以做doc.data().verified;。

    因此以下应该起作用:

    exports.checkVerification = functions.https.onCall((data, context) => {
        if (!context.auth) {
            throw new functions.https.HttpsError('unauthenticated');
        }
        console.log('user is ', context.auth.uid);
        const user = admin.firestore().collection('users').doc(context.auth.uid);
    
        return user.get().then(doc => {
    
            console.log('data read');
            if (doc.get("verified") {
                console.log('verified');
            } else {
                console.log('not verified');
            }
            return "success";
        }).catch(error => {
            throw new functions.https.HttpsError('internal');
        });
    });
    

    另外注意,如果用户文档不存在可能会抛出一个错误,返回一个特定的错误给前端,即不是通用的internal一个(可能是not-found,见list of possible codes )。

    【讨论】:

    • 我不建议使用 doc.get().verified。请参阅我发布的代码。 doc.get() 返回 promise,我们应该使用 data() 来获取 doc 的值。我在最近的项目中一直使用这些。
    • @development-ninja 我没有写到您建议使用doc.get().verified :-) 我实际上将您的回答解释为指出执行doc.get().verified 是不正确的。对不起,如果不是这样的话。我将删除任何提及您的答案的内容。
    • @DininduPerera 您好,您有时间查看建议的解决方案吗?
    【解决方案3】:

    尝试在 user.get() 的回调中使用 data()

    user.get().then(doc => {    
        //you get user doc value by using data()
        const userData = doc.data();
        // then you can use all properties from userData
        const verified = userData.verified;
    });
    

    【讨论】:

    • 我发现了问题。如果我使用 context.auth.uid 它不起作用。但是,如果我直接将字符串值放在括号内,它就可以工作。问题是它们都是相同的。
    • 很好的解决方案,干得好
    • 但我仍然需要使用 Context.Auth.Uid 因为我无法将用户 ID 硬编码到代码中
    • 你的意思是这不应该?常量 uid =context.auth.uid; const user = admin.firestore().collection('users').doc(uid)
    猜你喜欢
    • 2021-09-25
    • 2021-11-18
    • 1970-01-01
    • 2020-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-05
    相关资源
    最近更新 更多