如果在Firebase云功能中将请求的模式设置为“ no-cors”,将会发生什么?

时间:2019-12-18 13:06:41

标签: javascript firebase cors google-cloud-functions es6-promise

这是对this问题的跟进。我有一个Firebase函数,该函数应该进行OTP验证,然后根据密码是否正确来更改用户密码(由于某些原因,我无法使用Firebase的内置密码重置功能)。以下是我的功能:

exports.resetPassword = functions.https.onCall((data, context) => {
    return new Promise((resolve, reject) => {
        if(data.sesId && data.otp){
            admin.firestore().collection('verification').doc(data.sesId).get().then(verSnp => {
                if(verSnp.data().attempt != 'verified'){
                    var now = new Date().getTime()
                    if(verSnp.data().expiring > now){
                        if(data.email == verSnp.data().email){
                            if(verSnp.data().attempt > 0){
                                if(data.otp == verSnp.data().otp){
                                    admin.auth().getUserByEmail(data.email).then(user => {
                                        admin.auth().updateUser(user.uid,{
                                            password: data.password
                                        }).then(() => {
                                            admin.firestore().collection('verification').doc(data.sesId).update({
                                                attempt: 'verified'
                                            }).then(() => {
                                                Promise.resolve()
                                            }).catch(() => {
                                                throw new Error('Error updating the database.')
                                            })
                                        }).catch(() => {
                                            throw new Error('Error updating the password. Please try again.')
                                        })
                                    }).catch(() => {
                                        throw new Error('Incorrect email. How did you get here?')
                                    })
                                } else {
                                    var redAttempt = verSnp.data().attempt - 1
                                    admin.firestore().collection('verification').doc(data.sesId).update({
                                        attempt: redAttempt
                                    }).then(() => {
                                        throw new Error(`Incorrect OTP. You have ${redAttempt} attempts remaining.`)
                                    }).catch(() => {
                                        throw new Error('Wrong OTP, try again.')
                                    })
                                }
                            } else {
                                throw new Error('Incorrect OTP. You have exhausted your attempts. Please request a new OTP.')
                            }
                        } else {
                            throw new Error('Incorrect email. How did you get here?')
                        }
                    } else {
                        throw new Error('OTP is expired. Please request a new OTP.')
                    }
                } else {
                    throw new Error('OTP is invalid. Please request a new OTP.')
                }
            }).catch(() => {
                throw new Error('Invalid session id. Please request the OTP through Forgot Password.')
            })
        } else {
            throw new Error('Enter OTP')
        }
    })
})

当我运行该函数时,它会被执行,因为我可以在控制台语句中看到它,但是我的客户端出现了以下错误。

Access to fetch at 'https://us-central1-project-name.cloudfunctions.net/functionName' from origin 'http://localhost:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

当我记录从该函数收到的响应时,它显示{"code":"internal"}

什么是cors软件包?我该如何解决这个问题?


第2部分(不相关)

此外,在函数的第11和12行上,我正在使用

admin.auth().getUserByEmail(data.email).then(user => {
  admin.auth().updateUser(user.uid, {password: data.password})
})

这正确吗?


对于第1部分,我提到了this问题,但没有答案。

1 个答案:

答案 0 :(得分:1)

看看documentation中可调用的云函数:

  1. 不需要将其封装在return new Promise((resolve, reject) => {})中;
  2. 需要返回可以JSON编码的数据;
  3. 需要通过抛出(或返回被拒绝的Promise)实例functions.https.HttpsError来正确管理错误;
  4. 需要正确链接异步方法返回的所有promise。

下面我根据上面的观点尝试重新组织了您的代码,但是由于您的业务逻辑很复杂,因此我无法对其进行测试,并且可能会有其他方法来管理所有情况...由您决定来“抛光”这第一次尝试!希望会有所帮助。

exports.resetPassword = functions.https.onCall((data, context) => {

        if(data.sesId && data.otp){

            let dataOptCorresponds = true;

            return admin.firestore().collection('verification').doc(data.sesId).get()
            .then(verSnp => {
                if(verSnp.data().attempt != 'verified'){

                    var now = new Date().getTime()

                    if(verSnp.data().expiring > now){
                        if(data.email == verSnp.data().email){
                            if(verSnp.data().attempt > 0){
                                if(data.otp == verSnp.data().otp){
                                    return admin.auth().getUserByEmail(data.email);
                                } else {
                                    dataOptCorresponds = false;
                                    var redAttempt = verSnp.data().attempt - 1
                                    return admin.firestore().collection('verification').doc(data.sesId).update({
                                        attempt: redAttempt
                                    })
                                }
                            } else {
                                throw new Error('Incorrect OTP. You have exhausted your attempts. Please request a new OTP.')
                            }
                        } else {
                            throw new Error('Incorrect email. How did you get here?')
                        }
                    } else {
                        throw new Error('OTP is expired. Please request a new OTP.')
                    }
                } else {
                    throw new Error('OTP is invalid. Please request a new OTP.')
                }
            })
            .then(user => {
                if(dataOptCorresponds) {
                    return admin.auth().updateUser(user.uid,{
                        password: data.password
                    })
                } else {
                    throw new Error(`Incorrect OTP. You have xxxx attempts remaining.`)
                }
            })
            .then(() => {
                return admin.firestore().collection('verification').doc(data.sesId).update({
                    attempt: 'verified'
                })
            .then(() => {
                return {result: "success"}                      
            })          
            .catch(error => {
                throw new functions.https.HttpsError('internal', error.message);

            })

        } else {

            throw new functions.https.HttpsError('invalid-argument', 'Enter OTP');
        }

})

更新以下Bergi的评论:

如果您希望能够区分返回到前端的错误类型(特别是如果OTP错误,无效或已过期,或者如果电子邮件是电子邮件,则发回invalid-argument HttpsError是不正确的),您可以在then()方法中使用第二个参数。

exports.resetPassword = functions.https.onCall((data, context) => {

        if(data.sesId && data.otp){

            let dataOptCorresponds = true;

            return admin.firestore().collection('verification').doc(data.sesId).get()
            .then(

                verSnp => {
                    if(verSnp.data().attempt != 'verified'){

                        var now = new Date().getTime()

                        if(verSnp.data().expiring > now){
                            if(data.email == verSnp.data().email){
                                if(verSnp.data().attempt > 0){
                                    if(data.otp == verSnp.data().otp){
                                        return admin.auth().getUserByEmail(data.email);
                                    } else {
                                        dataOptCorresponds = false;
                                        var redAttempt = verSnp.data().attempt - 1
                                        return admin.firestore().collection('verification').doc(data.sesId).update({
                                            attempt: redAttempt
                                        })
                                    }
                                } else {
                                    throw new Error('Incorrect OTP. You have exhausted your attempts. Please request a new OTP.')
                                }
                            } else {
                                throw new Error('Incorrect email. How did you get here?')
                            }
                        } else {
                            throw new Error('OTP is expired. Please request a new OTP.')
                        }
                    } else {
                        throw new Error('OTP is invalid. Please request a new OTP.')
                    }
                },

                error => {

                    throw new functions.https.HttpsError('invalid-argument', error.message);

                }

            )
            .then(user => {
                if(dataOptCorresponds) {
                    return admin.auth().updateUser(user.uid,{
                        password: data.password
                    })
                } else {
                    throw new Error(`Incorrect OTP. You have xxxx attempts remaining.`)
                }
            })
            .then(() => {
                return admin.firestore().collection('verification').doc(data.sesId).update({
                    attempt: 'verified'
                })
            .then(() => {
                return {result: "success"}                      
            })          
            .catch(error => {
                throw new functions.https.HttpsError('internal', error.message);

            })

        } else {

            throw new functions.https.HttpsError('invalid-argument', 'Enter OTP');
        }

})