如果我在我的 firebase 云函数中将请求的模式设置为 'no-cors' 会发生什么?
What will happen if I set the request's mode to 'no-cors' in my firebase cloud function?
这是 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 问题,但没有答案。
查看可调用云函数的 documentation:
- 你不需要将它封装在
return new Promise((resolve, reject) => {})
;
- 您需要到return可以JSON编码的数据;
- 您需要通过抛出(或return拒绝承诺)
functions.https.HttpsError
的实例来正确管理错误;
- 您需要正确链接异步方法return所有的承诺。
我在下面尝试根据上述几点重新组织您的代码,但由于您的业务逻辑很复杂,我无法对其进行测试,并且可能有其他方法来管理所有情况...向上给你"polish"这第一次尝试!希望对您有所帮助。
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 的评论:
如果您希望能够区分 return 发送到前端的错误类型(特别是如果 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');
}
})
这是 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 问题,但没有答案。
查看可调用云函数的 documentation:
- 你不需要将它封装在
return new Promise((resolve, reject) => {})
; - 您需要到return可以JSON编码的数据;
- 您需要通过抛出(或return拒绝承诺)
functions.https.HttpsError
的实例来正确管理错误; - 您需要正确链接异步方法return所有的承诺。
我在下面尝试根据上述几点重新组织您的代码,但由于您的业务逻辑很复杂,我无法对其进行测试,并且可能有其他方法来管理所有情况...向上给你"polish"这第一次尝试!希望对您有所帮助。
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 的评论:
如果您希望能够区分 return 发送到前端的错误类型(特别是如果 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');
}
})