Firebase安全规则,仅确保对用户ID进行一次“阵列删除”

时间:2019-02-19 10:49:28

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

我有通知记录,其中有文本和用户列表(最多10个)。

{text: "Beware of the dog", users: [ uid1, uid2, uid3, ... ]}

当用户阅读/确认该通知时,我想将他从可以查看该通知的用户列表中删除(这样他将一无所获)。

为此,当用户按下“隐藏通知按钮”时,他发送了一个使用以下内容更新通知记录的请求:

users: FieldValue.arrayRemove(uid)

我想确保用户使用安全规则:

  • 不更改通知记录的其他部分。
  • 在arrayRemove部分中发送其uid,仅发送其uid。

尝试过

allow update: if 
    request.auth.uid != null 
    && request.auth.uid in resource.data.users 
    && request.resource.size() == 1 
    && request.resource.data.users != null;
  • request.resource.size == 1不起作用。无法弄清楚为什么,因为我的请求中只有一个字段。
  • 我无法确保arrayRemove严格限于其uid。

任何提示,帮助,想法都很好。

2 个答案:

答案 0 :(得分:3)

我也有类似的情况,这真是一个令人毛骨悚然的事情。 这就是我的诀窍:

allow update: if 
    request.auth.uid != null 
    && request.resource.data.diff(resource.data).affectedKeys().hasOnly([data])
    && request.resource.data.users.size() == resource.data.users.size() - 1
    && resource.data.users.removeAll(request.resource.data.users)[0] == request.auth.uid

特别是:

  1. 第一个规则是您拥有的规则-检查用户身份验证
  2. 第二条规则检查新文档和旧文档之间的差异,并确保受影响的唯一密钥是名为data的密钥
  3. 第三个规则确保新数组比旧数组短1个项目(以便一次只能删除1个项目)
  4. 第四个规则uid从旧数组中减去新数组(现在减少了1 removeAll()),并返回它们之间的差值。在这种情况下,它返回一个仅包含您选择uid的单个arrayRemove()的数组。然后,我们只需检查uid(只能存在于位置[0]处),并确保它等于已验证用户的uid

答案 1 :(得分:0)

我认为没有循环是不可能的,这在安全规则中是不存在的。好吧:如果您了解所有用户,则可以枚举所有选项,从本质上展开不可能的循环。但是,即使在安全规则中可行,规则也会变得非常冗长。

我建议创建一个子集合,其中每个UID都存储在单独的文档中。然后,在该子集合中,您可以通过仅允许用户删除自己的文档来实现您的要求。