允许删除并使用Firebase规则进行写入

时间:2018-03-04 14:14:14

标签: firebase firebase-realtime-database firebase-security-rules

我正在使用Firebase实时数据库。我有一个结构,以防止许多孩子。我有2把钥匙。一个用于max(max_people),另一个包含有多少个孩子(registered_people)。

我的结构:

enter image description here

我有max_people键。这是可以在已批准密钥中的最大子项。 Registered_people正在计算批准密钥中有多少个孩子。

这是我的安全规则:

"registrations": {
     "approved": {
        ".write": "(root.child('/agenda/activitys').child($room_id).child('max_people').val() > root.child('/agenda/activitys').child($room_id).child('registered_people').val())"
}

我在firebase规则中做的是检查是否有很多行。如果有很多我阻止写作。这可以按预期工作。

但是现在问题是,max_people例如是20,registered_people也是20.不会发生写入。因为我已经宣布了。但是我怎么能允许删除。因为我想随时删除。

所以简而言之,我想删除无论如何。我想用现行规则写作。

更多信息:

我使用以下代码将数据添加到密钥:

let data = [
    "full_name": "test",
    "email_addres": "test",
]

Database.database().reference().child("agenda/activitys/" + event + "/registrations/approved").child(Auth.auth().currentUser!.uid).setValue(data) { (error, ref) in
            print("got from subscribing \(String(describing: error))")
            if((error) != nil){
                completionHandler(Result.failure(ApiError.noMorePlaces))
                return
            } else {
                completionHandler(Result.success("succes \(event)"))
                return
            }
        }

按预期添加作品。

我使用以下代码删除数据:

Database.database().reference().child("agenda/activitys/" + event + "/registrations/approved").child(Auth.auth().currentUser!.uid).removeValue { (error, ref) in
            if((error) != nil){
                completionHandler(Result.failure(ApiError.unknownError))
                return
            } else {
                completionHandler(Result.success("succes \(event)"))
                return
            }
        }

删除无法按预期工作。如果最多有20个密钥,我会收到permission_denied错误。并且最大限度地被充分利用(所以我有20个密钥与批准的孩子下的数据)。

错误:

[Firebase/Database][I-RDB038012] setValue: or removeValue: at /agenda/activitys/Jumping Fitness/registrations/approved/exCnADF43AdFUzGsi0GllEsZJZY2 failed: permission_denied

但是当小于最大键数时,删除工作。

编辑: 我已经在firebase规则模拟器上测试了建议的解决方案。我也有模拟写错误。

我认为我有解决方案。我删除了密钥,所以在规则上我也需要密钥。我的解决方案:

"registrations": {
  "approved": {
    ".write":  "(root.child('/agenda/activitys').child($room_id).child('max_people').val() > root.child('/agenda/activitys').child($room_id).child('registered_people').val())",
        "$key" : {
           ".write" : "!newData.exists()"
        }
  }

1 个答案:

答案 0 :(得分:2)

删除数据时,newData变量将为null。因此,您可以使用exists()方法检查它是否存在:

"registrations": {
     "approved": {
        ".write": "(root.child('/agenda/activitys').child($room_id).child('max_people').val() > root.child('/agenda/activitys').child($room_id).child('registered_people').val()) || !newData.exists()"
}

更新:查看您提供的代码后,我可以看到您对子密钥执行了写操作。但请记住,根据documentation

  

较浅的安全规则会覆盖更深层路径的规则。

这意味着"批准"下的写规则将覆盖" $ key"的写规则。所以你应该加入这两个规则并将它们保存在" $ key"规则。像这样:

"registrations": {
  "approved": {
        "$key" : {
           ".write" : "(root.child('/agenda/activitys').child($room_id).child('max_people').val() > root.child('/agenda/activitys').child($room_id).child('registered_people').val()) || !newData.exists()"
        }
  }