Google cloud firestore Firebase安全规则,确保一个“;数组删除";仅限,且仅限用户ID

Google cloud firestore Firebase安全规则,确保一个“;数组删除";仅限,且仅限用户ID,google-cloud-firestore,firebase-security,Google Cloud Firestore,Firebase Security,我有通知记录,其中有文本和用户列表(最多10个) 当用户阅读/确认通知时,我想将其从可以看到通知的用户列表中删除(这样他就不会再收到任何通知) 为此,当用户按下“隐藏通知按钮”时,他发送一个更新通知记录的请求,其中包括: users: FieldValue.arrayRemove(uid) 我希望使用安全规则强制用户: 不会更改通知记录的其他部分 在arrayRemove部分发送其uid,并且仅发送其uid 试用 allow update: if request.auth.uid

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

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

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

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

非常感谢任何提示、帮助和想法。

如果没有循环,我认为这是不可能的,因为安全规则中不存在循环。好吧:如果你知道所有的用户,你也许能够列举所有的选项,基本上展开不可能的循环。但即使这在安全规则中是可能的,规则也会非常冗长


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

我认为如果没有循环,这是不可能的,因为安全规则中不存在循环。好吧:如果你知道所有的用户,你也许能够列举所有的选项,基本上展开不可能的循环。但即使这在安全规则中是可能的,规则也会非常冗长


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

我也遇到过类似的情况,这是一个相当棘手的问题。 这就是我的诀窍:

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
具体而言:

  • 第一条规则是您拥有的-检查用户身份验证
  • 第二条规则检查新文档和旧文档之间的差异,并确保唯一受影响的键是名为
    data
  • 第三条规则确保新数组比旧数组短1项(因此一次只能删除1项)
  • 第四条规则使用
    removeAll()
    从旧数组中减去新数组(现在减少了1
    uid
    ),并返回一个带差值的数组。在本例中,它返回一个数组,该数组只包含您选择的
    arrayRemove()
    的单个
    uid
    。然后我们只需检查
    uid
    ——它只能存在于位置
    [0]
    ——并确保它等于经过身份验证的用户的
    uid

  • 我有一个类似的情况,这是一个相当脑筋急转弯。 这就是我的诀窍:

    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
    
    具体而言:

  • 第一条规则是您拥有的-检查用户身份验证
  • 第二条规则检查新文档和旧文档之间的差异,并确保唯一受影响的键是名为
    data
  • 第三条规则确保新数组比旧数组短1项(因此一次只能删除1项)
  • 第四条规则使用
    removeAll()
    从旧数组中减去新数组(现在减少了1
    uid
    ),并返回一个带差值的数组。在本例中,它返回一个数组,该数组只包含您选择的
    arrayRemove()
    的单个
    uid
    。然后我们只需检查
    uid
    ——它只能存在于位置
    [0]
    ——并确保它等于经过身份验证的用户的
    uid

  • 好的,谢谢你的回答。我想Firestore将在某个时候发展并提供解决方案。好的,谢谢你的回答。我想Firestore会在某个时候发展并提供解决方案。你的第三条规则不应该是
    请求.资源.数据.用户.大小()==1
    ,因为请求中应该只有一项吗?啊!看起来像是
    FieldValue.arrayUnion/FieldValue.arrayRemove
    在验证发生之前对
    请求.resource.data
    执行了一些魔术。看起来它具有所有以前的值。你的#3现在完全有道理了。谢谢第二行应该是request.resource.data.diff(resource.data.affectedKeys().hasOnly(['users'))你的第三条规则不应该是
    request.resource.data.users.size()==1
    ,因为请求中应该只有一项吗?啊!看起来像是
    FieldValue.arrayUnion/FieldValue.arrayRemove
    在验证发生之前对
    请求.resource.data
    执行了一些魔术。看起来它具有所有以前的值。你的#3现在完全有道理了。谢谢第二行应该是request.resource.data.diff(resource.data.affectedKeys().hasOnly(['users'))