我希望我的 flutter 应用程序中的用户能够访问其他用户的食谱(如果其他用户允许)。我使用 Firebase Cloud Firestore 作为数据库。因此,如果当前用户是请求的用户 usersAllowedToRead 集合的一部分,那么他们还可以访问其他用户的食谱。
match /databases/{database}/documents {
match /users/{userId} {
// Allow the user to read and write their own document
allow read, write: if request.auth != null && request.auth.uid == userId;
match /recipes/{recipeId} {
// Allow read access if the user is authenticated and either is the user document owner
// or is listed in the 'usersAllowedToRead' subcollection of the user document
allow read: if request.auth != null && (request.auth.uid == userId || exists(/databases/$(database)/documents/users/$(userId)/usersAllowedToRead/$(request.auth.uid)));
// Allow write access only if the user is authenticated and is the user document owner
allow write: if request.auth != null && request.auth.uid == userId;
}
}
}
但我总是收到一条错误消息,指出访问被拒绝。当我在 firebase 规则游乐场中测试它时,即使当前用户存在于其他用户的 usersAllowedToRead 集合中,存在也会评估为 false。
这条路径存在于我的数据库中:
/users/VJ1DcW.../usersAllowedToRead/MmrFH...
但是当我执行 get 调用时,exists 方法的计算结果为 false,我不明白为什么。
我的猜测是,您的查询(您没有包含在问题中)正在尝试读取用户的整个
recipes
子集合,这将不起作用,因为 Firebase 安全规则不会过滤数据。相反,规则引擎只是确保来自客户端 SDK 的任何数据访问都符合您为该数据设置的规则。
您当前的代码将在您请求单个文档时工作,但不适用于列表样式查询,因为Firestore实际上无法以可扩展的方式检查所有潜在文档的数据。对于列表样式的调用,您将使用查询,并且必须确保您的查询满足规则的条件,这对于您当前的规则来说是不可能的 - 因为无法编写检查的查询与规则中的
exists
调用相同。
因此,您需要更改数据结构,以确保查询所需的所有数据都位于查询实际返回的文档内。完成此操作后,您的规则还可以过滤该数据 - 一旦规则和查询匹配,代码就会起作用。