Firestore规则:属性在对象上未定义

时间:2020-06-14 10:19:29

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

在使用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)。.

为了证明我已定义并可用了managers属性,如果将规则更改为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" })
            })
    }, [])

2 个答案:

答案 0 :(得分:1)

起初,您可以尝试 <form method="post" action="<?=$_SERVER['PHP_SELF'];?>"> 吗?

第二,您是否将db.collection("businesses").get("VzaU8rX8HOgejk0fyOFK");array-containsin用作array-contains-any方法比较操作?

如果没有,请问您尝试以下代码吗?

例如

where()

答案 1 :(得分:1)

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

查询必须显式具有规则所要求的过滤器。您的规则要求查询仅对当前用户位于managers数组字段中的文档进行过滤。因此,查询必须更像这样:

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

uid是当前用户的uid。

相关问题