简体   繁体   English

如何使用Firebase(Swift)中的安全规则限制子节点

[英]How can i limit child nodes using security rules in Firebase (Swift)

I am developing Turn based game using firebase. 我正在使用Firebase开发回合制游戏。 My game has game rooms and each room includes max 3 child nodes. 我的游戏有游戏室,每个游戏室最多包含3个子节点。 These are Player1,Player2 and current user count. 它们是Player1,Player2和当前用户数。 My case, Player1 created a room with 2 child nodes(Player1 ID and current user counts). 在我的情况下,Player1创建了一个包含2个子节点的房间(Player1 ID和当前用户数)。 Player 1 is waiting just 1 enemy. 玩家1正在等待1个敌人。 However, if 2 other players click join at the same time, the room will have 3 Players. 但是,如果同时有2个其他玩家单击加入,则会议室中将有3个玩家。 How i can avoid this situation using security rules ? 我如何使用安全规则来避免这种情况?

My Related database part as text like below: 我的相关数据库部分为文本,如下所示:

"QuickPlay3hanePlaying" : {
"ByVmFbUC6HS01v4SASeA2ev33zz1" : {
  "3s6TdUxImrNhMReJbS8kBh4I9im1" : {
    "IQ" : 1350,
    "date" : 1.474527951467337E9,
    "gizliSayi" : [ 1, 2, 3, 4, 5 ],
    "isReady" : 0,
    "isSiraBende" : 0,
    "isWin" : 0,
    "name" : "Emre Esen",
    "photoUrl" : "https://scontent.xx.fbcdn.net/v/t1.0-1/p200x200/1796656_10203231676898828_1482882234_n.jpg?oh=b1600006284e4e8ca9411d804c5571a2&oe=5880E580",
    "sonTahminim" : [ 1, 2, 3, 4, 5 ],
    "uid" : "3s6TdUxImrNhMReJbS8kBh4I9im1"
  },
  "ByVmFbUC6HS01v4SASeA2ev33zz1" : {
    "IQ" : 1280,
    "date" : 1.474527943420204E9,
    "gizliSayi" : [ 1, 2, 3, 4, 5 ],
    "isReady" : 0,
    "isSiraBende" : 1,
    "isWin" : 0,
    "name" : "Emot Emot",
    "photoUrl" : "https://scontent.xx.fbcdn.net/v/t1.0-1/p200x200/14225541_330456493965915_6052582248934611374_n.jpg?oh=35c26a6ea69a3266451a33908c7a060a&oe=586E13B1",
    "sonTahminim" : [ 1, 2, 3, 4, 5 ],
    "uid" : "ByVmFbUC6HS01v4SASeA2ev33zz1"
  },
  "userSayisi" : 2
}

} }

Create Room Code Block: 创建房间代码块:

    func createRoom(){


    Model.sharedInstance.QuickPlayOdaAdi = Model.sharedInstance.userFirebaseID

    setPlayerInfo()

    let interval = NSDate().timeIntervalSince1970

    let info = ["photoUrl":Model.sharedInstance.userPictureUrl,
                "uid":Model.sharedInstance.userFirebaseID,
                "IQ":Model.sharedInstance.userIQ,
                "name":Model.sharedInstance.username,
                "isSiraBende":1,
                "gizliSayi":Model.sharedInstance.gizliSayi,
                "isReady":Model.sharedInstance.isReadyForPlaying,
                "isWin":Model.sharedInstance.isWin,
                "sonTahminim":Model.sharedInstance.rakipSonTahmini,
                "date":interval]


    Model.sharedInstance.quickPlayRoomPerGameRef.child(Model.sharedInstance.userFirebaseID).setValue(["userSayisi":1])

    Model.sharedInstance.quickPlayRoomPerGameRef.child(Model.sharedInstance.userFirebaseID).child(Model.sharedInstance.userFirebaseID).setValue(info)

    // uygulama kapatıldıgında remove olsun diye

    Model.sharedInstance.quickPlayRoomPerGameRef.child(Model.sharedInstance.QuickPlayOdaAdi).child(Model.sharedInstance.userFirebaseID).onDisconnectRemoveValue()
    Model.sharedInstance.quickPlayRoomPerGameRef.child(Model.sharedInstance.QuickPlayOdaAdi).child("userSayisi").onDisconnectRemoveValue()



    Model.sharedInstance.handleCreateRoom =  Model.sharedInstance.quickPlayRoomPerGameRef.child(Model.sharedInstance.QuickPlayOdaAdi).observeEventType(.Value, withBlock: { (snapshot) in

        print("SnapCount: \(snapshot.childrenCount)")

        // usersayısı ve 1 kullanıcı ile snap sayısı 2 oluyor 1 kullanıcı için

        if snapshot.childrenCount == 3 {

            print("Game Start")




            Model.sharedInstance.quickPlayRoomPerGameRef.child(Model.sharedInstance.QuickPlayOdaAdi).removeObserverWithHandle(Model.sharedInstance.handleCreateRoom)

            Model.sharedInstance.quickPlayRoomPerGameRef.child(Model.sharedInstance.QuickPlayOdaAdi).updateChildValues(["userSayisi":2])


            let ilkEleman = snapshot.children.allObjects[0] as! FIRDataSnapshot

            let ikinciEleman = snapshot.children.allObjects[1] as! FIRDataSnapshot

            let ucuncuEleman = snapshot.children.allObjects[2] as! FIRDataSnapshot




            print(ucuncuEleman.key)

            if ilkEleman.key != Model.sharedInstance.userFirebaseID && ilkEleman.key != "userSayisi" {

                 print(ilkEleman.key)

                dispatch_async(GlobalBackgroundQueue, {

                    Model.sharedInstance.enemyName = ilkEleman.value!["name"] as! String
                    Model.sharedInstance.enemyIQ = ilkEleman.value!["IQ"] as! Int
                    Model.sharedInstance.enemyFirebaseID = ilkEleman.value!["uid"] as! String
                    Model.sharedInstance.enemyPictureUrl = ilkEleman.value!["photoUrl"] as! String



            Model.sharedInstance.quickPlayChooseGameRef.child(Model.sharedInstance.userFirebaseID).updateChildValues(["isPlay":1])




                    dispatch_async(GlobalMainQueue, {

                        self.enemyNameLbl.text = Model.sharedInstance.enemyName
                        self.enemyRank.text = "\(Model.sharedInstance.enemyIQ)"
                        self.enemyImage.hnk_setImageFromURL(NSURL(string: Model.sharedInstance.enemyPictureUrl)!)


                    })

                })




                Model.sharedInstance.delay(2.5, closure: {
                    self.performSegueWithIdentifier(Model.sharedInstance.quickPlayHaneSayisi, sender: self)



                })




            }
            else if ikinciEleman.key != Model.sharedInstance.userFirebaseID && ikinciEleman.key != "userSayisi" {


                 print(ikinciEleman.key)
                dispatch_async(GlobalBackgroundQueue, {

                    Model.sharedInstance.enemyName = ikinciEleman.value!["name"] as! String
                    Model.sharedInstance.enemyIQ = ikinciEleman.value!["IQ"] as! Int
                    Model.sharedInstance.enemyFirebaseID = ikinciEleman.value!["uid"] as! String
                    Model.sharedInstance.enemyPictureUrl = ikinciEleman.value!["photoUrl"] as! String



                    Model.sharedInstance.quickPlayChooseGameRef.child(Model.sharedInstance.userFirebaseID).updateChildValues(["isPlay":1])



                    dispatch_async(GlobalMainQueue, {

                        self.enemyNameLbl.text = Model.sharedInstance.enemyName
                        self.enemyRank.text = "\(Model.sharedInstance.enemyIQ)"
                        self.enemyImage.hnk_setImageFromURL(NSURL(string: Model.sharedInstance.enemyPictureUrl)!)


                    })

                })



                Model.sharedInstance.delay(2.5, closure: {
                    self.performSegueWithIdentifier(Model.sharedInstance.quickPlayHaneSayisi, sender: self)


                })

            }else{


                print(ikinciEleman.key)
                dispatch_async(GlobalBackgroundQueue, {

                    Model.sharedInstance.enemyName = ucuncuEleman.value!["name"] as! String
                    Model.sharedInstance.enemyIQ = ucuncuEleman.value!["IQ"] as! Int
                    Model.sharedInstance.enemyFirebaseID = ucuncuEleman.value!["uid"] as! String
                    Model.sharedInstance.enemyPictureUrl = ucuncuEleman.value!["photoUrl"] as! String



                    Model.sharedInstance.quickPlayChooseGameRef.child(Model.sharedInstance.userFirebaseID).updateChildValues(["isPlay":1])



                    dispatch_async(GlobalMainQueue, {

                        self.enemyNameLbl.text = Model.sharedInstance.enemyName
                        self.enemyRank.text = "\(Model.sharedInstance.enemyIQ)"
                        self.enemyImage.hnk_setImageFromURL(NSURL(string: Model.sharedInstance.enemyPictureUrl)!)


                    })

                })



                Model.sharedInstance.delay(2.5, closure: {
                    self.performSegueWithIdentifier(Model.sharedInstance.quickPlayHaneSayisi, sender: self)


                })


            }




        }else if snapshot.childrenCount == 2 {

            print("1 user waiting")

            Model.sharedInstance.quickPlayRoomPerGameRef.child(Model.sharedInstance.userFirebaseID).updateChildValues(["userSayisi":1])

        }



    }) { (error) in
        print(error)
    }


}

Join Room Code Block: 加入房间代码块:

    func joinRoom(){

    setPlayerInfo()



    Model.sharedInstance.quickPlayRoomPerGameRef.queryOrderedByChild("userSayisi").queryEqualToValue(1).queryLimitedToLast(1).observeSingleEventOfType(.Value, withBlock: { (snapshot) in



       if snapshot.exists(){




       let odaAdi = snapshot.children.allObjects[0] as! FIRDataSnapshot


        Model.sharedInstance.QuickPlayOdaAdi = odaAdi.key

        let interval = NSDate().timeIntervalSince1970

        let info = ["photoUrl":Model.sharedInstance.userPictureUrl,
            "uid":Model.sharedInstance.userFirebaseID,
            "IQ":Model.sharedInstance.userIQ,
            "name":Model.sharedInstance.username,
            "isSiraBende":0,
            "gizliSayi":Model.sharedInstance.gizliSayi,
            "isReady":Model.sharedInstance.isReadyForPlaying,
            "isWin":Model.sharedInstance.isWin,
            "sonTahminim":Model.sharedInstance.rakipSonTahmini,
            "date":interval
        ]



      Model.sharedInstance.quickPlayRoomPerGameRef.child(Model.sharedInstance.QuickPlayOdaAdi).child(Model.sharedInstance.userFirebaseID).setValue(info)

        Model.sharedInstance.quickPlayRoomPerGameRef.child(Model.sharedInstance.QuickPlayOdaAdi).removeObserverWithHandle(Model.sharedInstance.handleJoinRoom)

        Model.sharedInstance.quickPlayRoomPerGameRef.child(Model.sharedInstance.QuickPlayOdaAdi).child(Model.sharedInstance.userFirebaseID).onDisconnectRemoveValue()
        Model.sharedInstance.quickPlayRoomPerGameRef.child(Model.sharedInstance.QuickPlayOdaAdi).child("userSayisi").onDisconnectRemoveValue()



        Model.sharedInstance.quickPlayRoomPerGameRef.child(odaAdi.key).observeSingleEventOfType(.Value, withBlock: { (snapshot) in

            print("SnapCount: \(snapshot.childrenCount)")



                let ilkEleman = snapshot.children.allObjects[0] as! FIRDataSnapshot

                let ikinciEleman = snapshot.children.allObjects[1] as! FIRDataSnapshot

                let ucuncuEleman = snapshot.children.allObjects[2] as! FIRDataSnapshot





                if ilkEleman.key != Model.sharedInstance.userFirebaseID && ilkEleman.key != "userSayisi" {

                    print(ilkEleman.key)

                    dispatch_async(GlobalBackgroundQueue, {

                        Model.sharedInstance.enemyName = ilkEleman.value!["name"] as! String
                        Model.sharedInstance.enemyIQ = ilkEleman.value!["IQ"] as! Int
                        Model.sharedInstance.enemyFirebaseID = ilkEleman.value!["uid"] as! String
                        Model.sharedInstance.enemyPictureUrl = ilkEleman.value!["photoUrl"] as! String



                        Model.sharedInstance.quickPlayChooseGameRef.child(Model.sharedInstance.userFirebaseID).updateChildValues(["isPlay":1])



                        dispatch_async(GlobalMainQueue, {

                            self.enemyNameLbl.text = Model.sharedInstance.enemyName
                            self.enemyRank.text = "\(Model.sharedInstance.enemyIQ)"
                            self.enemyImage.hnk_setImageFromURL(NSURL(string: Model.sharedInstance.enemyPictureUrl)!)


                        })

                    })

                    Model.sharedInstance.delay(2.5, closure: {



                        self.performSegueWithIdentifier(Model.sharedInstance.quickPlayHaneSayisi, sender: self)


                    })



                }
                else if ikinciEleman.key != Model.sharedInstance.userFirebaseID && ikinciEleman.key != "userSayisi"{


                    print(ikinciEleman.key)
                    dispatch_async(GlobalBackgroundQueue, {

                        Model.sharedInstance.enemyName = ikinciEleman.value!["name"] as! String
                        Model.sharedInstance.enemyIQ = ikinciEleman.value!["IQ"] as! Int
                        Model.sharedInstance.enemyFirebaseID = ikinciEleman.value!["uid"] as! String
                        Model.sharedInstance.enemyPictureUrl = ikinciEleman.value!["photoUrl"] as! String



                        Model.sharedInstance.quickPlayChooseGameRef.child(Model.sharedInstance.userFirebaseID).updateChildValues(["isPlay":1])


                        dispatch_async(GlobalMainQueue, {

                            self.enemyNameLbl.text = Model.sharedInstance.enemyName
                            self.enemyRank.text = "\(Model.sharedInstance.enemyIQ)"
                            self.enemyImage.hnk_setImageFromURL(NSURL(string: Model.sharedInstance.enemyPictureUrl)!)


                        })

                    })

                    Model.sharedInstance.delay(2.5, closure: {




                        self.performSegueWithIdentifier(Model.sharedInstance.quickPlayHaneSayisi, sender: self)


                    })

                }
                else{

                    print(ucuncuEleman.key)
                    dispatch_async(GlobalBackgroundQueue, {

                        Model.sharedInstance.enemyName = ucuncuEleman.value!["name"] as! String
                        Model.sharedInstance.enemyIQ = ucuncuEleman.value!["IQ"] as! Int
                        Model.sharedInstance.enemyFirebaseID = ucuncuEleman.value!["uid"] as! String
                        Model.sharedInstance.enemyPictureUrl = ucuncuEleman.value!["photoUrl"] as! String



                        Model.sharedInstance.quickPlayChooseGameRef.child(Model.sharedInstance.userFirebaseID).updateChildValues(["isPlay":1])


                        dispatch_async(GlobalMainQueue, {

                            self.enemyNameLbl.text = Model.sharedInstance.enemyName
                            self.enemyRank.text = "\(Model.sharedInstance.enemyIQ)"
                            self.enemyImage.hnk_setImageFromURL(NSURL(string: Model.sharedInstance.enemyPictureUrl)!)


                        })

                    })

                    Model.sharedInstance.delay(2.5, closure: {




                        self.performSegueWithIdentifier(Model.sharedInstance.quickPlayHaneSayisi, sender: self)


                    })


                }







        }) { (error) in
            print(error)
        }




       }else{

        self.createRoom()

        }


        }) { (error) in

            print(error)
    }

}

This is possible to handle within your security rules but you will have to change your database structure a little bit. 这可以在安全规则内处理,但是您将不得不稍微更改数据库结构。 Instead of what you have now you have to do somthing like this: 除了现在需要的东西,您还需要执行以下操作:

"QuickPlay3hanePlaying" : {
  "ByVmFbUC6HS01v4SASeA2ev33zz1" : {
    "Player1" : {
      "3s6TdUxImrNhMReJbS8kBh4I9im1" : {
        "IQ" : 1350,
        ...
        "uid" : "3s6TdUxImrNhMReJbS8kBh4I9im1"
      },
    },
    "Player2" : {
      "ByVmFbUC6HS01v4SASeA2ev33zz1" : {
        "IQ" : 1280,
        ...
        "uid" : "ByVmFbUC6HS01v4SASeA2ev33zz1"
      },
    },
    "userSayisi" : 2
  }

And your security rules would look like this: 您的安全规则如下所示:

{
"rules": {
  "QuickPlay3hanePlaying": {
    "$id": {
      "player1": {".validate": true},
      "player2":{".validate": true},
      "userSayisi": {".validate": true},
      "$other": {".validate": false}
      }
    }
  }
}

The reason for the change in database structure is because you can only have 1 wildcard key in your security rules at a certain position. 更改数据库结构的原因是,您的安全规则中的某个位置只能有1个通配符。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM