[英]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.