Я внедряю систему пользователей и событий. Одно ограничение состоит в том, что пользователь может принимать только одно событие за один раз.
Сначала я пытался реализовать ограничение путем запроса events
узла в events
.write
правило, ищут событие, которое уже имело USERID равный auth.uid
. Но я не мог понять, как это сделать, поэтому я решил создать новый узел, hosts
, как таблицу поиска. Он просто хранит любые пользовательские идентификаторы, которые в настоящее время размещают событие. Если пользователь пытается создать событие, и их userId уже существует в hosts
, то это ошибка.
Правила:
{
"rules":{
"users":{
"$uid":{
".read": "auth.uid == $uid",
".write": "auth.uid == $uid",
".validate": "newData.exists()"
}
},
"hosts":{
"$uid":{
".read": "true",
//to be a host, you must be a user
".write": "auth.uid == $uid && root.child('users').hasChild(auth.uid) && !root.child('hosts').hasChild(auth.uid)",
".validate": "newData.exists()"
}
},
"events":{
"$uid":{
".read": "true",
//to create an event, you must be a host
".write": "root.child('hosts').hasChild(auth.uid)",
".validate": "true"
}
}
}
}
Javascript:
createEvent(form){
var user = firebase.auth().currentUser
var db = firebase.database();
var newEventRef = db.ref('events').push();
var newEvent = {}
newEvent[uid] = form*/
var update = {
['hosts/'+user.uid]: true
update['events/'+newEventRef.key] = form
};
db.ref().update(update)
.then((...args)=>{
...
})
.catch(err=>{
...
})
},
Проблема с вызовом обновления заключается в том, что он всегда терпит неудачу. Я пытаюсь вставить в hosts
и events
одновременно. Но правило write
events
ожидает, что userId будет находиться на hosts
до того, как он начнет запись, поэтому я догадываюсь, почему он терпит неудачу.
Должен ли я сделать 2 отдельных обновления? 1, чтобы вставить userId в hosts
, а затем, если это удастся, другая вставка в events
?
В правилах безопасности есть три переменные, которые относятся к данным:
data
- данные, которые существуют в местоположении правила до его обновленияnewData
- данные, как они есть в местоположении правила после его обновленияroot
- данные, которые существуют в корне базы данных до их обновления Поэтому, когда вы ссылаетесь на root
в своих правилах, вы получаете данные до обновления. Чтобы получить обновленные данные, вы должны обратиться к newData
. Поскольку, к сожалению, нет newRoot
, вам нужно будет перейти от newData
до требуемого уровня, вызвав parent()
несколько раз.
Пример:
"events":{
"$uid":{
".read": "true",
//to create an event, you must be a host
".write": "newData.parent().parent().child('hosts').hasChild(auth.uid)",
".validate": "true"
}
}