Использование переменных в операции «Список» правил безопасности Firestore - PullRequest
0 голосов
/ 31 января 2019

Я пытаюсь настроить правила безопасности, которые разрешают доступ к коллекции, на основе значения поля документа во вложенной коллекции.

Это работает, как и ожидалось, при извлечении отдельного документа по идентификатору, который являетсяget операция.Тем не менее, при запросе main_collection (операция list) это завершается с ошибкой «Отказано в доступе».Поскольку в коллекции только один документ, это не тот случай, когда у меня нет разрешения на некоторые запрашиваемые документы, например, на этот вопрос .

МойСтруктура базы данных выглядит следующим образом.Он содержит перечисляемую коллекцию (main_collection), в которой есть один документ (some_doc), в которой есть одна подколлекция (sub_collection), в которой есть один документ (another_doc).

/main_collection/some_doc/sub_collection/another_doc

another_doc имеет одно строковое поле someFieldValue.

В этом примере мой запрос относится ко всей коллекции, то есть к одному документу.В моем реальном приложении оно запрашивает только те документы, к которым оно ожидает получить доступ, но конечный результат здесь тот же, потому что я не могу отфильтровать вложенную коллекцию документа из клиентской библиотеки.

firestore.collection('main_collection').get()

Это моя безопасностьrules.

service cloud.firestore {
  match /databases/{database}/documents {
    match /main_collection/{mainColDoc} {
      // This operation works
      allow get: if subCollectionDocumentHasField('someFieldValue');
      // This operation fails with permission denied
      allow list: if subCollectionDocumentHasField('someFieldValue');

      // This checks for the existence of a field on the subcollection's document
      function subCollectionDocumentHasField(fieldName) {
        return get(/databases/$(database)/documents/main_collection/$(mainColDoc)/sub_collection/another_doc).data.keys().hasAny([fieldName]);
        //return get(/databases/$(database)/documents/main_collection/some_doc/sub_collection/another_doc).data.keys().hasAny([fieldName]);
      }
    }
  }
}

Функция subCollectionDocumentHasField проверяет наличие поля someFieldValue в документе another_doc.В этой функции, если я заменим переменную $(mainColDoc) на жестко закодированный идентификатор документа some_doc, операция list будет успешной.Поскольку в этом контексте можно использовать переменную пути $(database), я ожидаю, что другие тоже могут быть такими.

Это ошибка или ожидаемое поведение?

Ответы [ 2 ]

0 голосов
/ 20 марта 2019

Я открыл заявку в Google и эффективно подтвердил, что @ José вывел из использования, а именно, что правило безопасности «проверяется только один раз на запрос».

Для уточнения, а правило безопасности для *Операция 1003 * обычно не запрашивает содержимое документа (во избежание потенциально низкой производительности), есть хотя бы одно условие, когда будет запрашивать содержимое документа.Это когда правило безопасности гарантировано для возврата только одного документа.Когда эта гарантия будет соблюдена, будет запрошено содержимое отдельного документа, поскольку можно поддерживать высокую производительность;так же, как в операции get.

Итак, в связанном примере в моем вопросе, где правило операции list ссылается на родительский документ, эта гарантия соблюдается, и содержимое родительского документа будет запрашиваться.

Кроме того, в моем примере, где правило операции list ссылается на жестко закодированный идентификатор документа, эта гарантия соблюдается и запрашивается содержимое жестко-закодированного документа.

Дляради явного указания этого для операции list в любом случае, когда Firestore не может гарантировать, что его правило будет запрашивать только один документ, в проекте будет автоматически отказано в доступе.

0 голосов
/ 18 февраля 2019

Это на самом деле ожидаемое поведение , вы не можете использовать правила Firebase для фильтрации результатов вашего запроса .


Aтипичный сценарий будет иметь коллекцию сообщений, где каждое сообщение ссылается на своего создателя.

Нельзя просто добавить правило, в котором чтение разрешено только для сообщений, для которых создатель является аутентифицированным пользователем,для автоматической фильтрации сообщений текущего аутентифицированного пользователя.

Единственный способ - запросить фильтр на стороне клиента (или с помощью функции Cloud).


Документацияочень ясно об этом:

При написании запросов для извлечения документов имейте в виду, что правила безопасности не являются фильтрами - запросы - это все или ничего.Чтобы сэкономить ваше время и ресурсы, Cloud Firestore сравнивает запрос с его потенциальным набором результатов вместо фактических значений полей для всех ваших документов.Если запрос может потенциально вернуть документы, которые клиент не имеет разрешения на чтение, весь запрос завершится неудачей.

Из документации Firebase

...