基于映射值的 Firestore 安全规则

Firestore security rules based on map values

我想根据用户的电子邮件地址存储是否允许用户阅读文档本身中的文档。多个用户应该可以访问同一个文档。

根据 the documentation Firestore 不允许查询数组成员。这就是为什么我将用户的电子邮件地址存储在 String-Bool 映射中,并将电子邮件地址作为键。

对于以下示例,我没有使用电子邮件作为映射键,因为它已经不适用于基本字符串。

数据库结构如下所示:

lists
  list_1
    id: String
    name: String
    owner: E-Mail
    type: String
    shared:
      test: true

此处列出了所有安全规则:

service cloud.firestore {
  match /databases/{database}/documents {
    match /lists/{listId=**} {
        allow read: if resource.data.shared.test == true
    }
  }
}

编辑:如果我使用 match /lists/{listId} 而不是 match /lists/{listId=**}

,它也不起作用

我的理解是,如果映射 shared[test] 中的值为真,则此安全规则应该允许所有人进行读取访问。

为了完整起见:这是我正在使用的查询(Android 上的 Kotlin):

collection.whereEqualTo("shared.test", true).get()
        .addOnCompleteListener(activity, { task ->
            if (task.isSuccessful) {
                Log.i("FIRESTORE", "Query was successful")
            } else {
                Log.e("FIRESTORE", "Failed to query existing from Firestore. Error ${task.exception}")
            }
        })

我猜我无法从安全规则访问映射值。那么我的问题的替代解决方案是什么?

Firestore rules reference 中写道可以像那样访问地图 resource.data.property == 'property' 所以,我做错了什么?

编辑: 这个问题现在应该已经解决了。如果您仍然看到它(并且确定它是规则评估器的错误),请在评论中告诉我。

我已经和这里的一些人聊过您遇到的问题,这似乎是安全规则本身的问题。从本质上讲,问题似乎特定于评估查询中的嵌套字段,就像您正在做的那样。

所以,基本上,您正在做的事情应该可以正常工作,您需要等待 Firestore 团队的更新才能使此查询正常工作。发生这种情况时,我会尽量记住更新此答案。对不起!

只要你有 (可选)嵌套属性,你应该确保 属性 存在,然后再继续检查它的值,例如

allow read: if role in request.auth.token && request.auth.token[role] == true

你的情况:

allow read: if test in resource.data.shared && resource.data.shared.test == true

,我在角色方面苦苦挣扎了很长时间,直到我意识到在非管理员用户上,管理字段是未定义的,并且 firestore 规则只是崩溃并且不会继续检查其他可能的匹配项。

对于没有 token.admin 的用户,这将始终 崩溃 无论您是否有其他匹配项为真,例如:

function userHasRole(role) {
  return isSignedIn() && request.auth.token[role] == true
}