我正在为 Firebase 编写一个云函数,它应该更改我的网络应用程序上的用户密码。一切工作正常,但我只是想知道我的代码是否经过优化且编写良好,因为糟糕的编码可能会导致 Firebase 本身产生意外的成本。 这是我的功能:
export const setNewPassword = v2.https
.onRequest({cors: true}, async (request, response) => {
// Se non è una richiesta POST
if (request.method != "POST") {
console.log("Wrong request method");
response.status(400).send({code: "bad-request", message: "POST-required"});
return;
}
// Recupero il body e lo convalido
const body = request.body;
if (!body) {
console.log("Missing body");
response.status(400).send({code: "bad-request", message: "missing-body"});
return;
}
// Decifro il messaggio
const message = CryptoJS.AES.decrypt(body, "key");
const decryptedData = JSON.parse(message.toString(CryptoJS.enc.Utf8));
// Ottengo i dati
const newPassWord = decryptedData.newPass;
const resetCode = decryptedData.resetCode;
// Validazione dei dati
if (newPassWord.length < 8) {
response.status(500).send({code: "invalid-password", message: "too-short"});
return;
} else if (resetCode.length != 16) {
response.status(500).send({code: "invalid-code", message: "code-length"});
return;
} else {
// Recupero il documento firestore con il codice di reset associato alla mail
const resetDoc = await firestore.collection("password-reset")
.where("resetCode", "==", resetCode)
.get();
// Validazione del documento
// Se esiste più di un documento
if (!resetDoc) {
console.log(`Code '${resetCode}' not found`);
response.status(500).send({code: "invalid-code", message: "user-not-found"});
return;
}
// Se il codice è duplicato
if (resetDoc.docs.length > 1) {
console.log(`Code '${resetCode}' is duplicated`);
response.status(500).send({code: "invalid-code", message: "ambiguos-code"});
return;
}
// Nel caso restante esiste solo un documento
// Recupero la mail dell'utente
const userMail = resetDoc.docs[0].data().email;
// Recupero l'oggetto utente
const user = await admin.auth().getUserByEmail(userMail);
// Aggiorno la password
admin.auth().updateUser(user.uid, {password: newPassWord})
.then(() => {
// Elimino il documento con il resetCode
resetDoc.forEach((doc) => {
doc.ref.delete();
});
console.log(`User '${userMail}' updated his password`);
response.status(200).send({result: "password-updated"});
})
.catch((error) => {
console.log(`Error '${error}' while updating password for user '${userMail}'`);
response.status(500).send({error: error});
});
}
});
我首先关心的是代码的每个检查点是否正确返回。我打算让 HTTPS 函数以
res.send()
终止,但我注意到,如果我只是在其后没有 return
的情况下放置它,我会收到错误“错误 [ERR_HTTP_HEADERS_SENT]:在将标头发送到客户端后无法设置标头”
那么,我这样做正确吗?
我已经调整了你的代码。主要问题是您对异步 delete()
方法
并行执行了未确定数量的调用,而没有正确等待所有这些执行完成。您可以使用
Promise.all()
,如下面的代码(或写入批处理)所示。
我删除了多余的
return;
不必要的行。
我还在
await
中使用了await admin.auth().updateUser()
而不是then()
。这些变化用 // <== Change here
标识
export const setNewPassword = v2.https.onRequest(
{ cors: true },
async (request, response) => {
try {
// Se non è una richiesta POST
if (request.method != "POST") {
console.log("Wrong request method");
response
.status(400)
.send({ code: "bad-request", message: "POST-required" });
}
// Recupero il body e lo convalido
const body = request.body;
if (!body) {
console.log("Missing body");
response
.status(400)
.send({ code: "bad-request", message: "missing-body" });
}
// Decifro il messaggio
const message = CryptoJS.AES.decrypt(body, "key");
const decryptedData = JSON.parse(message.toString(CryptoJS.enc.Utf8));
// Ottengo i dati
const newPassWord = decryptedData.newPass;
const resetCode = decryptedData.resetCode;
// Validazione dei dati
if (newPassWord.length < 8) {
response
.status(500)
.send({ code: "invalid-password", message: "too-short" });
} else if (resetCode.length != 16) {
response
.status(500)
.send({ code: "invalid-code", message: "code-length" });
} else {
// Recupero il documento firestore con il codice di reset associato alla mail
const resetDoc = await firestore
.collection("password-reset")
.where("resetCode", "==", resetCode)
.get();
// Validazione del documento
// Se esiste più di un documento
if (resetDoc.empty) {. // <== Change here
console.log(`Code '${resetCode}' not found`);
response
.status(500)
.send({ code: "invalid-code", message: "user-not-found" });
}
// Se il codice è duplicato
if (resetDoc.docs.length > 1) {
console.log(`Code '${resetCode}' is duplicated`);
response
.status(500)
.send({ code: "invalid-code", message: "ambiguos-code" });
}
// Nel caso restante esiste solo un documento
// Recupero la mail dell'utente
const userMail = resetDoc.docs[0].data().email;
// Recupero l'oggetto utente
const user = await admin.auth().getUserByEmail(userMail);
// Aggiorno la password
await admin.auth().updateUser(user.uid, { password: newPassWord }); // <== Change here
const promises = []; // <== Change here
resetDoc.forEach((doc) => {
promises.push(doc.ref.delete()); // <== Change here
});
await Promise.all(promises); // <== Change here
console.log(`User '${userMail}' updated his password`);
response.status(200).send({ result: "password-updated" });
}
} catch (error) {
console.log(
`Error '${error}' while updating password for user '${userMail}'`
);
response.status(500).send({ error: error });
}
}
);