首页 > 解决方案 > Firebase 无法创建新文档

问题描述

我有一个 firebase 项目,自我上次构建以来,它不会创建新文档。它将保存和修改文档,但不会创建新文档。

创建新文档的函数应该使用基于新创建的 uid 的键创建一个新文档,如下所示:

const sendInformationHandler = () => {
        const customerEmailCurrent = customerEmail.current.value
        const customerPassword = "password"
        if (checkUserEmailExists(customerEmailCurrent)) {
                createUser(
                    {
                        email: customerEmailCurrent,
                        password: customerPassword
                    }
                ).then(function(user) {
                    firebase
                    .firestore()
                    .collection('sessions')
                    .doc(user.data.uid).set(
                        {...context.state}
                    ).then(() => {
                        console.log("DATA SAVED SUCCESSFULLY!")
                    }).then(() => {
                        dispatch({ type: refreshContextFromCache, payload: INITIAL_CONTEXT})
                    }).then(() => {
                        push('/');
                    })
                }).catch(err => console.log("AN ERROR OCCURRED", err))
            } else {
                console.log("EMAIL ALREADY EXISTS!!!!!!")
            }
    };

我将 checkUserEmailExists 设置为始终返回 true。createUser 是云中的一个 firebase 函数,用于创建新用户。当这个函数被触发时,它正在重定向,然后出错。

该错误表示它是权限错误,但我的 firebase api 密钥没有更改,我可以修改现有记录。

我的数据库规则也没有改变并且基于令牌,但令牌仍在工作:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if request.auth.token.admin == true;
      }
    match /{document=**} {
      allow create: if request.auth.token.coach == true;
      }
    match /sessions/{userId} {
      allow read, write: if request.auth.token.customer == true && request.auth.uid == userId;
      }
  }
}

在本地,在我推送之前,我在 firebase cli 中为正确的项目调用了 firebase use,并在本地也使用 gcp 切换到了正确的项目。

我的 firebaserc 是这样的:

{
  "targets": {
    "prod": {
      "hosting": {
        "prod": [
          "prod-project"
        ]
      }
    },
    "develop": {
      "hosting": {
        "prod": [
          "prod-project"
        ]
      }
    },
    "prod-project": {
      "hosting": {
        "prod": [
          "prod-project"
        ]
      }
    },
    "ammonite-testing": {
      "hosting": {
        "prod": [
          "prod-project"
        ]
      }
    }
  },
  "projects": {
    "prod": "prod-project",
    "default": "prod-project"
  }
}

我的 firebase.json 就像:

{
  "functions": {
    "source": "functions"
  },
  "hosting": {
    "target": "prod",
    "public": "build",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "rewrites": [
      {
        "source": "**",
        "destination": "/index.html"
      }
    ]
  }
}

到底是怎么回事?如果firebase权限不起作用?为什么我还能保存?为什么它在这个最新的 ci 版本上坏了,而不是以前?

标签: javascriptfirebasegoogle-cloud-firestorefirebase-authentication

解决方案


正如 Renaud Tarnec 提到的,您的规则相互重叠。正如 Firestore文档中所解释的,当多个规则匹配一个文档时,如果其中任何一个是真实的,则允许请求。实际上应用于sessions集合中文档的规则是:

match /sessions/{userId} {
    allow read, write: if request.auth.token.admin == true or
                          request.auth.token.coach == true or
    }                     (request.auth.token.customer == true && request.auth.uid == userId)

至于为什么该应用程序以前可以工作而现在不能工作,我们无法给出答案。可能代码的某些部分发生了更改并显示了错误,这实际上意味着某些请求满足上述安全标准之一,而其他请求则不满足。

如果您想在此级别进行调试,一个选项可能是向此函数和 Firebase 函数添加日志记录代码,以查看发送了哪些声明(管理员、教练、用户 ID 等)。

另外,编写 Firestore 安全规则时的最佳做法是完全避免规则重叠,并尽可能以最细粒度的级别授予访问权限。这有助于保护数据并确保根据需要限制访问,意外的规则交互很容易错过。


推荐阅读