首页 > 解决方案 > Firebase:云功能更改 Firestore 中的数据 - 资源项目的权限被拒绝 [X:YYYYYYYYYY:web:KKKKKKKKKKKK]

问题描述

我正在尝试通过 firebase 云功能将数据添加到我的 firestore 集合中。但是,执行该功能时会出现以下错误。

我的云功能代码是:

import * as functions from "firebase-functions";
import * as admin from "firebase-admin";

admin.initializeApp();
const Firestore = require("@google-cloud/firestore");
const PROJECTID = "[...]";

const firestore = new Firestore({
  projectId: PROJECTID,
  timestampsInSnapshots: true,
});
exports.createNewChat = functions.region("europe-west1")
    .https.onRequest((request, response) => {
      console.log("!!!!!!");
      console.log("THe BodY: " + request);
      console.log("THe BodY: " + request.rawBody);
      console.log("THe BodY: " + request.body);
      try {
        const groupName = request.body.groupName;
        const members: string[] = request.body.members;
        firestore.collection("chats").add({
          groupName: groupName,
          members: members,
          lastMessage: new Date(),
          messages: [],
        }).then((doc: any) => {
          const chatId = doc.id;
          members.forEach((member) => {
            firestore.collection("myChats/" + member).add({
              chatKey: chatId,
            });
          });
          return response.status(200).send(doc);
        });
      } catch (e) {
        functions.logger.log("catch clause " + e);
        response.status(500).send(e);
      }
    });

我的邮递员请求如下所示:

抛出的异常是:

!已请求 Google API!

  • 网址:“https://oauth2.googleapis.com/token”
  • 请注意,这可能是生产服务。(节点:23224)UnhandledPromiseRejectionWarning:错误:7 PERMISSION_DENIED:资源项目的权限被拒绝[...]。在 Object.callErrorFromStatus (E:\Workspaces\cloudFunctions\functions\node_modules@grpc\grpc-js\build\src\call.js:31:26) 在 Object.onReceiveStatus (E:\Workspaces\cloudFunctions\functions\node_modules@ grpc\grpc-js\build\src\client.js:179:52) 在 Object.onReceiveStatus (E:\Workspaces\cloudFunctions\functions\node_modules@grpc\grpc-js\build\src\client-interceptors.js: 336:141) 在 Object.onReceiveStatus (E:\Workspaces\cloudFunctions\functions\node_modules@grpc\grpc-js\build\src\client-interceptors.js:299:181) 在 E:\Workspaces\cloudFunctions\functions\ node_modules@grpc\grpc-js\build\src\call-stream.js:145:78 at processTicksAndRejections (internal/process/task_queues.js:79:11) 原因:\Users\XXXXX\AppData\Roaming\npm\node_modules\firebase-tools\lib\emulator\functionsEmulatorRuntime.js:479:23) 在 Layer.handle [as handle_request] (C:\Users\XXXXX\AppData\Roaming\npm \node_modules\firebase-tools\node_modules\express\lib\router\layer.js:95:5) 在下一个 (C:\Users\XXXXX\AppData\Roaming\npm\node_modules\firebase-tools\node_modules\express\lib \router\route.js:137:13) (node:23224) UnhandledPromiseRejectionWarning: 未处理的承诺拒绝。此错误源于在没有 catch 块的情况下抛出异步函数内部,或拒绝未使用 .catch() 处理的承诺。要在未处理的 Promise 拒绝时终止节点进程,请使用 CLI 标志 \Users\XXXXX\AppData\Roaming\npm\node_modules\firebase-tools\node_modules\express\lib\router\layer.js:95:5) 在下一个 (C:\Users\XXXXX\AppData\Roaming\npm\node_modules \firebase-tools\node_modules\express\lib\router\route.js:137:13) (node:23224) UnhandledPromiseRejectionWarning:未处理的承诺拒绝。此错误源于在没有 catch 块的情况下抛出异步函数内部,或拒绝未使用 .catch() 处理的承诺。要在未处理的 Promise 拒绝时终止节点进程,请使用 CLI 标志 \Users\XXXXX\AppData\Roaming\npm\node_modules\firebase-tools\node_modules\express\lib\router\layer.js:95:5) 在下一个 (C:\Users\XXXXX\AppData\Roaming\npm\node_modules \firebase-tools\node_modules\express\lib\router\route.js:137:13) (node:23224) UnhandledPromiseRejectionWarning:未处理的承诺拒绝。此错误源于在没有 catch 块的情况下抛出异步函数内部,或拒绝未使用 .catch() 处理的承诺。要在未处理的 Promise 拒绝时终止节点进程,请使用 CLI 标志 此错误源于在没有 catch 块的情况下抛出异步函数内部,或拒绝未使用 .catch() 处理的承诺。要在未处理的 Promise 拒绝时终止节点进程,请使用 CLI 标志 此错误源于在没有 catch 块的情况下抛出异步函数内部,或拒绝未使用 .catch() 处理的承诺。要在未处理的 Promise 拒绝时终止节点进程,请使用 CLI 标志--unhandled-rejections=strict(见https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode)。(拒绝 ID:3)(节点:23224)[DEP0018] DeprecationWarning:不推荐使用未处理的承诺拒绝。将来,未处理的 Promise 拒绝将使用非零退出代码终止 Node.js 进程。

标签: firebasegoogle-cloud-firestoregoogle-cloud-functions

解决方案


在 Cloud Function for Firebase 中,您应该使用Node.js 的 Admin SDK,而不是标准的 JS SDK。

此外,您需要使用在循环中并行执行对异步方法Promise.all()的调用。add()forEach()

因此,以下一组改编应该可以解决您的问题:

import * as functions from "firebase-functions";
import * as admin from "firebase-admin";

admin.initializeApp();

exports.createNewChat = functions.region("europe-west1")
    .https.onRequest((request, response) => {
      
        const groupName = request.body.groupName;
        const members: string[] = request.body.members;
        const db = admin.firestore();

        db.collection("chats").add({
          groupName: groupName,
          members: members,
          lastMessage: new Date(),
          messages: [],
        }).then((doc: any) => {
          const chatId = doc.id;
          const promises = [];
          members.forEach((member) => {
            promises.push(db.collection("myChats/" + member).add({
              chatKey: chatId,
            }));
          });
          return Promise.all(promises);
        })
        .then(() => {
          response.status(200).send(JSON.stringify(doc));
        })
        .catch(e => {
           functions.logger.log("catch clause " + e);
           response.status(500).send(JSON.stringify(e));
        });
    });

推荐阅读