Ответ 1
Правила безопасности могут выполнять несколько действий:
-
убедитесь, что пользователь может добавлять/удалять свои собственные
uid
вstars
node"stars": { "$uid": { ".write": "$uid == auth.uid" } }
-
убедитесь, что пользователь может изменить только
starCount
, когда он добавляет свой собственныйuid
вstars
node или удаляет его оттуда - убедитесь, что пользователь может только увеличивать/уменьшать
starCount
на 1
Даже с этим может оказаться сложным иметь правило безопасности, гарантирующее, что значение starCount
равно числу uids в stars
node. Я рекомендую вам попробовать и поделиться своим результатом.
То, как я видел большинство разработчиков, имеет дело с этим:
- сделайте начальный подсчет на клиенте (если размер
stars
node не слишком велик, это разумно). - есть надежный процесс, запущенный на сервере, который объединяет
stars
вstarCount
. Он может использовать события child_added/child_removed для увеличения/уменьшения.
Обновление: с рабочим примером
Я написал рабочий пример системы голосования. Структура данных:
votes: {
uid1: true,
uid2: true,
},
voteCount: 2
Когда пользователь голосует, приложение отправляет обновление с несколькими местоположениями:
{
"/votes/uid3": true,
"voteCount": 3
}
И затем, чтобы удалить свой голос:
{
"/votes/uid3": null,
"voteCount": 2
}
Это означает, что приложение должно явно прочитать текущее значение для voteCount
, с помощью:
function vote(auth) {
ref.child('voteCount').once('value', function(voteCount) {
var updates = {};
updates['votes/'+auth.uid] = true;
updates.voteCount = voteCount.val() + 1;
ref.update(updates);
});
}
Это, по сути, транзакция с несколькими местоположениями, но затем встроенная в код приложения и правила безопасности вместо Firebase SDK и самого сервера.
Правила безопасности делают несколько вещей:
- убедитесь, что значение countCount может увеличиваться или уменьшаться на 1
- убедитесь, что пользователь может добавлять или удалять только собственные голоса.
- убедитесь, что увеличение счета сопровождается голосованием.
- убедитесь, что уменьшение счета сопровождается "unvote"
- обеспечить, чтобы голосование сопровождалось увеличением количества.
Обратите внимание, что правил нет:
- убедитесь, что "unvote" сопровождается уменьшением количества (может быть сделано с помощью правила
.write
) - повторение неудачных голосов /unvotes (для обработки одновременного голосования/опроса)
Правила:
"votes": {
"$uid": {
".write": "auth.uid == $uid",
".validate": "(!data.exists() && newData.val() == true &&
newData.parent().parent().child('voteCount').val() == data.parent().parent().child('voteCount').val() + 1
)"
}
},
"voteCount": {
".validate": "(newData.val() == data.val() + 1 &&
newData.parent().child('votes').child(auth.uid).val() == true &&
!data.parent().child('votes').child(auth.uid).exists()
) ||
(newData.val() == data.val() - 1 &&
!newData.parent().child('votes').child(auth.uid).exists() &&
data.parent().child('votes').child(auth.uid).val() == true
)",
".write": "auth != null"
}
jsbin с некоторым кодом для проверки этого: http://jsbin.com/yaxexe/edit?js,console