【问题标题】:Firestore Rules : Property is undefined on objectFirestore 规则:对象上的属性未定义
【发布时间】:2023-03-22 06:41:02
【问题描述】:

在我使用 firebase 模拟器的本地环境中,我有以下规则会引发 FirebaseError: Property managers is undefined on object. for 'list'

rules_version = '2';
service cloud.firestore {
    match /databases/{database}/documents {
        match /businesses/{business} {
            allow read: if request.auth != null && request.auth.uid in resource.data.managers;
        }
    }
}

如果我在规则 Playground 上测试相同的规则,它可以正常工作 (Simulated read allowed)..

为了证明我已经定义了 manager 属性并且可用,如果我将规则更改为 if true,我可以使用以下本地数据在列表上循环:

// code
...
.then((snap) => snap.forEach((doc) => console.log(doc.id, " => ", doc.data())))

// output
VzaU8rX8HOgejk0fyOFK  =>  {..., managers: Array(1)}

我做错了什么?

谢谢!

更新

这是我希望应用规则的代码:

    useEffect(() => {
        db.collection("businesses")
            .where("slug", "==", params.slug)
            .get()
            .then((snap) => {
                if (!snap.empty) {
                    // slug is supposed to be unique, so I retrieve the first and only element
                    const doc = snap.docs[0]
                    setBusiness({ id: doc.id, data: doc.data() })
                    setState({ ...state, loading: false, data: true })
                } else {
                    setState({ ...state, loading: false, error: "Business not found" })
                }
            })
            .catch((error) => {
                console.log("Error getting document:", error)
                setState({ ...state, loading: false, error: "Error getting document" })
            })
    }, [])

【问题讨论】:

    标签: firebase google-cloud-firestore firebase-security


    【解决方案1】:

    您的规则在控制台模拟器中有效,因为它一次只测试单个文档的读取。但是,您的客户端代码正在执行对多个文档的查询,这是不同的。要知道的一件非常重要的事情是security rules are not filters(一定要阅读它和this)。如果规则拒绝文档,则安全规则不会从结果集中删除文档。相反,查询必须能够获取规则允许的所有文档,否则规则将完全拒绝查询。

    查询必须明确具有与规则要求相同的过滤器。您的规则要求查询仅过滤当前用户在管理器数组字段中的文档。因此,查询必须更像这样:

    db.collection("businesses")
        .where("slug", "==", params.slug)
        .where("managers", "array-contains", uid)
    

    uid 是当前用户的 uid。

    【讨论】:

      【解决方案2】:

      首先,你可以试试db.collection("businesses").get("VzaU8rX8HOgejk0fyOFK");吗?

      其次,你有没有使用array-containsin或者array-contains-any作为where()的方法比较操作?

      如果没有,你可以试试下面的代码吗?

      例如。

      db.collection("businesses").where("managers", "in", uid)
          .get()
          .then(function(querySnapshot) {
              querySnapshot.forEach(function(doc) {
                  console.log(doc.id, " => ", doc.data());
              });
          })
          .catch(function(error) {
              console.log("Error getting documents: ", error);
          });
      

      【讨论】:

      • 您好@zkohi,我自己检索数据没有问题,而是使用安全规则限制访问。你确定你的建议会对我有帮助吗?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-07
      • 2019-01-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多