2016-08-22 3 views
4

Возможно, я слишком много занимаюсь этой проблемой с точки зрения SQL, но у меня возникают проблемы с пониманием того, как правильно ограничить, какие дети должны быть заполнены узлом.«Ловить все остальные». Правило базы данных Firebase

Скажите, что я хочу вести учет продуктов с произвольными именами. Каждый продукт должен содержать price, но больше ничего не допускается.

Мой наивный подход был добавить .validate правило в продуктах, требующих NewData содержать price ребенка, явным образом предоставить доступ на запись к price узлу, а затем удаляя все доступ к $other узел (нечто вроде пункта по умолчанию в распределительном заявлении):

{ 
    "rules": { 
     "$product": { 
      ".read": true, 
      ".write": true, 
      ".validate": "newData.hasChildren(['price'])", 
      "price": { 
       ".write": true, 
       ".validate": "newData.isNumber()" 
      }, 
      "$other": { 
       ".read.": false, 
       ".write": false, 
      } 
     } 
    } 
} 

Это не работает. Добавление нового продукта с {"price": 1234, "foo": "bar"} будет по-прежнему приниматься. Если я однако добавлю правило ".validate": false к $other, вместо этого ничего не принимается (например, {"price": 1234} не допускается).(я сделал это неправильно, как-то.)

Есть ли способ реализовать что-то похожее на то, что я пытаюсь сделать здесь? Если нет, то каков правильный способ ограничения структуры данных в Firebase? Должен ли я вообще это делать? Что мешает пользователю заполнить мою базу данных мусором, если я этого не сделаю?

+0

Я не уверен, что я следую почему '«$ другой»: {«.validate»ложь}' не то, что вы хотите. Однако, невзирая на это, знаете ли вы, что вы не можете отменить разрешение после предоставления? Таким образом, '.write": true' под '$ product' означает ваш' '.write": false' под '$ other' игнорируется? – cartant

+0

@cartant Я обновил вопрос, чтобы уточнить, почему проверка не работает. –

ответ

7

Вы попадаете в некоторые обычные ямы безопасности Firebase. Наиболее распространенным является то, что разрешение каскадируется: если вы предоставили разрешение на чтение или запись на определенном уровне в дереве, вы не сможете отнять это разрешение на более низком уровне.

Это означает, что эти правила являются неэффективными (так как вы предоставил чтения/записи на один уровень выше уже):

"$other": { 
    ".read.": false, 
    ".write": false, 
} 

Чтобы решить эту проблему, вы должны понять, что .validate правила различны: данные считается только действительным, когда все правила выполнены. Таким образом, вы можете отказаться от данных $other с правилами проверок:

{ 
    "rules": { 
     "$product": { 
      ".read": true, 
      ".write": true, 
      ".validate": "newData.hasChildren(['price'])", 
      "price": { 
       ".validate": "newData.isNumber()" 
      }, 
      "$other": { 
       ".validate": false 
      } 
     } 
    } 
} 
+0

Это решает. Самое смешное, что я подумал, что я пробовал это решение (например, я кратко упомянул в вопросе), но, видимо, мне удалось как-то подделать это. В любом случае, ваш ответ также сделал различия между валидацией и записью гораздо яснее для меня, поэтому спасибо за это. :) –

+0

Как бы это выглядело в болте? – Waltari