Firebase 安全规则,确保只有一个“数组删除”,并且只针对 userId

Fra*_*nck 6 firebase-security google-cloud-firestore

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

{text: "Beware of the dog", users: [ uid1, uid2, uid3, ... ]}
Run Code Online (Sandbox Code Playgroud)

当用户阅读/确认通知时,我想将他从可以看到通知的用户列表中删除(然后他将不再收到任何通知)。

为此,当用户按下“隐藏通知按钮”时,他会发送一个请求来更新通知记录:

users: FieldValue.arrayRemove(uid)
Run Code Online (Sandbox Code Playgroud)

我想使用用户的安全规则:

  • 不更改通知记录的其他部分。
  • 在 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;
Run Code Online (Sandbox Code Playgroud)
  • request.resource.size == 1 不起作用。不知道为什么,因为我的请求中只有一个字段。
  • 我无法确保 arrayRemove 严格限于其 uid。

任何提示、帮助、想法都值得赞赏。

小智 10

我遇到了类似的情况,这是一个脑筋急转弯。这就是我的诀窍:

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
Run Code Online (Sandbox Code Playgroud)

具体来说:

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