添加了子项的Firebase甚至安全规则拒绝创建对象

时间:2018-01-29 20:05:37

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

我不知道它是如何可能的,但即使安全规则拒绝新数据,它也会在我的视图中添加新对象。我听db如下:

dbRef = db.ref('/PostsCompany/' + companyKey + '/Posts').orderByChild('Date');
dbRef.on('child_added', function (snap) {
   console.log(snap.val());
})

db结构:

  {
    "PostsCompany" : {
      "-L3Y7zOHpKu0tbr-cyXQ" : {
        "LastPost" : {
          "CommentsEnabled" : true,
          "CompanyKey" : "-L3Y7zOHpKu0tbr-cyXQ",
          "Date" : 1517316150394,
          "Message" : "test msg",
          "PostKey" : "-L464lDsQc8wmpuynK_n",
          "Type" : "Post"
        },
        "Posts" : {
          "-L464lDsQc8wmpuynK_n" : {
            "CommentsEnabled" : true,
            "CompanyKey" : "-L3Y7zOHpKu0tbr-cyXQ",
            "Date" : 1517316150394,
            "Message" : "test msg",
            "Type" : "Post"
          }
        }
      }
    }
  }

相关规则:

"PostsCompany": {
  "$companyKey": {
    ".read": "auth !== null",
    "Posts": {
        ".indexOn": ["Date"],
        "$postKey": {
            ".write": "auth.uid == root.child('CompanyPages')
                                       .child($companyKey)
                                       .child('OwnerUID')
                                       .val()",
            ".validate": "root.child('CompanyPages')
                              .child($companyKey)
                              .exists() &&
                          newData.hasChildren(['CompanyKey','Message','Date','Type','CommentsEnabled'])",
            "CompanyKey": {
                ".validate": "!data.exists() && 
                                        newData.val() == $companyKey"
            },
            "Date": {
                ".validate": "!data.exists() && 
                                        newData.val() <= now"
            },
            "Message": {
                ".validate": "!data.exists() && 
                                        newData.isString() && 
                                        newData.val().length<=1000"
            },
            "Type": {
                ".validate": "!data.exists() && 
                                        newData.val() == 'Post'"
            },
            "Media": {
                ".validate": "!data.exists() && 
                                        newData.hasChildren(['Type','Preview'])",
                "Type" : {
                    ".validate": "newData.val() == 'Image'"
                },
                "Preview" : {
                    ".validate": "newData.isString()"
                },
                "$other": {
                  ".validate": false
                }
            },
            "CommentsEnabled": {
                ".validate": "newData.isBoolean()"
            },
            "Comments": {
                ".read": " auth !== null",
                "$commentKey": {
                    ".write": " auth !== null &&
                                root.child('PostsCompany')
                                  .child($companyKey)
                                                .child('Posts')
                                  .child($postKey)
                                  .child('CommentsEnabled')
                                  .val() == true",
                    ".validate": "newData.hasChildren(['UID','Message','Date'])",
                    "UID": {
                        ".validate": "!data.exists() && 
                                      auth.uid == newData.val()"
                    },
                    "Date": {
                        ".validate": "!data.exists() && 
                                      newData.val() <= now"
                    },
                    "Message": {
                        ".validate": "!data.exists() && 
                                      newData.isString() && 
                                      newData.val().length<=1000"
                    },
                    "Likes": {
                        "$uidCommentLike": {
                            ".write": "auth.uid == $uidCommentLike",
                            ".validate": "newData.isBoolean()"
                        }
                    },
                    "Replies": {
                        "$replyKey": {
                            ".validate": "newData.hasChildren(['UID','Message','Date'])",
                            "UID": {
                                ".validate": "!data.exists() && 
                                                            auth.uid == newData.val()"
                            },
                            "Date": {
                                ".validate": "!data.exists() && 
                                              newData.val() <= now"
                            },
                            "Message": {
                                ".validate": "!data.exists() && 
                                              newData.isString() && 
                                              newData.val().length<=1000"
                            },
                            "Likes": {
                                "$uidReplyLike": {
                                    ".write": "auth.uid == $uidReplyLike",
                                    ".validate": "newData.isBoolean()"
                                }
                            },
                            "$other": {
                              ".validate": false
                            }
                            }
                    },
                    "$other": {
                        ".validate": false
                    }
                }
            },
            "Likes": {
                "$uid": {
                    ".write": "auth.uid == $uid",
                    ".validate": "newData.isBoolean()"
                }
            },
            "$other": {
              ".validate": false
            }
        }
    }
  }      
},

当我尝试添加新帖子时,它会显示我预期的错误 (错误:PERMISSION_DENIED:权限被拒绝)。

但不知何故dbRef仍然有效并获取新数据。我在Firebase控制台上仔细检查它,它从不在db上添加新数据,或者至少在视觉上没有任何变化。

我想验证控件会在我的案例中使用newData.hasChildren()。如果没有发送其中一个对象(例如我尝试过没有Type),则会再次发生。

newData.hasChildren(['CompanyKey','Message','Date','Type','CommentsEnabled']) 

1 个答案:

答案 0 :(得分:0)

这样做的原因是Firebase进行了乐观更新。它会在与Google的数据库服务器版本同步之前,在数据库的本地版本中添加新帖子。


连接到Firebase数据库的每个客户端都维护自己的内部版本的任何活动数据。写入数据后,首先将其写入此本地版本。然后,Firebase客户端会在“尽力而为”的基础上与远程数据库服务器和其他客户端同步该数据。

请参阅: https://firebase.google.com/docs/database/web/read-and-write#write_data_offline

https://firebase.googleblog.com/2016/11/what-happens-to-database-listeners-when-security-rules-reject-an-update.html


child_added发生在执行规则之前,这就是在您的情况下运行规则的原因,并且您无法同时在Firebase Console中看到结果。

如果您定义child_removed,则会在创建新帖子后直接将其称为。<​​/ p>