Как я могу проверить, существует ли идентификатор в документе?

#google-cloud-firestore #firebase-security

# #google-cloud-firestore #firebase-безопасность

Вопрос:

У меня есть базовое приложение для чата, и пользователи могут блокировать друг друга. Когда пользователь A блокирует пользователя B, пользователь B больше не доступен для отправки сообщений.

Структура блоков

коллекция пользовательских блоков

Правило безопасности (беседы)

 function isBlocked() {
  return !get(/databases/$(database)/documents/user-blocks/$(request.resource.data.receiverId)).data.hasAny([request.auth.uid]);
}
 

Итак, когда пользователь B (аутентифицированный пользователь)
отправляет сообщение пользователю A (получателю), это не должно быть разрешено. Поскольку пользователь A заблокировал пользователя B.

Проблема

Приведенный выше код не работает. Как я могу проверить, существует ли идентификатор пользователя B в документе?

Ответ №1:

hasAny документируется в списке. Похоже, вы захотите перейти от поля для каждого блока к одному блоку со списком идентификаторов. Например. Документ в /user-blocks/ будет иметь blocks = [sender-id1, sender-id2], тогда ваше правило будет выглядеть следующим образом return !get(/databases/$(database)/documents/user-blocks/$(request.resource.data.receiverId)).data.blocks.hasAny([request.auth.uid]);

Вы также можете попробовать использовать оператор in на карте, например return !(request.auth.uid in get(/databases/$(database)/documents/user-blocks/$(request.resource.data.receiverId)).data)

Чтобы объединить это с вызовом exists, вам понадобится что-то вроде: `

 if (!exists(/databases/$(database)/documents/user-blocks/$(request.resource.data.receiverId)
     or !(request.auth.uid in get(/databases/$(database)/documents/user-blocks/$(request.resource.data.receiverId)).data))
 

`

Комментарии:

1. Спасибо за ваш ответ. Что происходит, когда пользователь B никого не заблокировал? В этом случае в пользовательских блоках не будет данных. Будет ли работать приведенный выше код?

2. Если пользователь B никого не заблокировал, я не ожидаю, что у вас будет объект user blocks . Это означает, что вам потребуется вызов exists() перед вызовом get. Если вы можете гарантировать, что документ с пользовательскими блоками существует, вы можете гарантировать, что список блоков в этом документе существует.

3. Учитывая, что в вашем списке есть только 1 элемент, который вы передаете hasAny, вы можете использовать in оператор, поскольку это, вероятно, сделает ваши правила более понятными.

4. Я собираюсь использовать in operator . Но мне нужно найти решение для документа, который может не существовать, если пользователь никого не заблокировал. Можете ли вы придумать решение, которое охватывает обе ситуации?

5. Сегодня вам нужно будет выполнить вызов exists(), за которым следует вызов get() . Если документ не существует, функция exists() вернет false .