Firebase: установить правила безопасности в зависимости от пользовательских ролей
Я хотел бы реализовать правила безопасности "write" в Firebase в зависимости от ролей пользователей.
Моя структура данных выглядит так:
+ myapp
+ users
+ john
+ email: "[email protected]"
+ roles
+ administrator: true
+ mary
+ email: "[email protected]"
+ roles
+ moderator: true
+ ...
+ documents
+ -JVmo6wZM35ZQr0K9tJu
+ ...
+ -JVr56hVTZxlAI5AgUaS
+ ...
+ ...
Например, я хочу, чтобы только пользователи-пользователи могли писать документы.
Это правила, к которым я пришел:
{
"rules": {
".read": true,
"$documents": {
".write": "root.child('users').child(auth.uid).child('roles').child('administrator').val() === true"
}
}
}
Но это не работает: даже пользователи-администраторы не могут писать документы...
Является ли мое понимание правил безопасности Firebase совершенно ошибочным?
ОБНОВЛЕНИЕ: Как раз перед тем, как Дженни ответит (верьте или нет :-), я реализовал то же самое решение, которое он предоставляет (конечно, на основе комментария Като).
Хотя, делая некоторые тесты, я не мог позволить структуре правил
{
"rules": {
"documents" {
"$document" {
".read": "root.child('users').child(auth.uid).child('roles').child('documents').child('read').val() === true",
".write": "root.child('users').child(auth.uid).child('roles').child('documents').child('write').val() === true"
}
}
}
}
работа... У меня всегда было предупреждение:
"FIREBASE WARNING: on() or once() for /documents failed: Error: permission_denied: Client doesn't have permission to access the desired data. "
Поэтому я придумал эту структуру, вместо этого:
{
"rules": {
"documents" {
".read": "root.child('users').child(auth.uid).child('roles').child('documents').child('read').val() === true",
".write": "root.child('users').child(auth.uid).child('roles').child('documents').child('write').val() === true"
}
}
}
Что действительно работает для меня: если я задаю роли /customers/read node true для пользователя, он может прочитать все документы, иначе он не сможет (и то же самое для записи).
Теперь я сомневаюсь:
- почему я не мог допустить, чтобы первое правило (как было предложено Като) работает?
- видите ли вы какое-либо возможное отверстие безопасности в правиле, подобном тому, которое я сделал?
- являются правилами, использующими переменные "$", необходимыми/полезными, даже если вам не нужно разрешать/запрещать читаемость/возможность записи каждого отдельного документа на основе этого ключа, но вы просто хотите разрешить/запретить читабельность/удобочитаемость узла как целое?
Ответы
Ответ 1
Основываясь на именах ваших пользовательских записей, они не соответствуют auth.uid
, который, вероятно, является простейшим идентификатором входа, например twitter:2544215
.
Начните с настройки ваших пользователей, которые будут храниться через их простой вход uid:
+ myapp
+ users
+ twitter:2544215
+ email: "[email protected]"
+ roles
+ administrator: true
+ twitter:2544216
+ email: "[email protected]"
+ roles
+ moderator: true
+ ...
+ documents
+ -JVmo6wZM35ZQr0K9tJu
+ ...
+ -JVr56hVTZxlAI5AgUaS
+ ...
+ ...
Затем добавьте правило безопасности, чтобы администраторы могли обращаться к documents
. У вас есть пара вариантов здесь, в зависимости от вашего конкретного варианта использования.
-
Чтобы администраторы могли писать доступ к содержимому каждого документа:
{
"rules": {
"documents": {
"$documents": {
".write": "root.child('users').child(auth.uid).child('roles').child('administrator').val() === true"
}
}
}
}
-
Или, альтернативно, предоставить им доступ ко всей коллекции:
{
"rules": {
"documents": {
".write": "root.child('users').child(auth.uid).child('roles').child('administrator').val() === true"
}
}
}
Разница между этими двумя является переменной $documents
которая перемещает правило безопасности на один шаг дальше в иерархию.
(Это было всего лишь совокупность комментариев @Kato в форме ответа)