Запрос Firebase возвращает "PERMISSION_DENIED", но правила работают в тестовой консоли. - PullRequest
0 голосов
/ 02 августа 2020

У меня есть следующее правило Firebase:

match /PendingInvites/{inviteID} {
    allow read: if request.auth != null && 
        isInviteForUser(database, inviteID);
}

и следующие функции:

  function isInviteForUser(database, inviteID) {
  
    let dataItem = get(/databases/$(database)/documents/PendingInvites/$(inviteID)).data;
  
    return (dataItem.userPhone == request.auth.token.phone_number) ||
                    (dataItem.userEmail == request.auth.token.email);
  }

Тестирование коллекции с использованием онлайн-теста роли работает, я проверяю, используя настоящие документы и со значениями userPhone и userEmail (совпадающими и не совпадающими). Все работает, как ожидалось, отрицая значения несоответствия и разрешая совпадающие значения.

Вот где это становится странным. Когда я запускаю этот (Android) запрос:

val companyMemberDocuments = Firebase.firestore.collection("PendingInvites").whereEqualTo("userPhone", firebaseAuth.currentUser!!.phoneNumber).whereEqualTo("userEmail", firebaseAuth.currentUser!!.email).get().await()

, я получаю «PERMISSION_DENIED: Отсутствуют или недостаточны разрешения». Насколько я понимаю правила, думаю, это должно сработать. Он работает в онлайн-консоли, я специально запрашиваю userPhone (или userEmail), но это не работает.

Я пробовал удалить userEmail и тестировал только userPhone, но это тоже не работает. работа.

Есть идеи, как я могу исправить правила (или запрос)?

Спасибо

Документ:

Токен аутентификации, использованный при тестировании:

{
  "uid": "",
  "token": {
    "sub": "",
    "aud": "certifly-global",
    "phone_number": "+16505551234",
    "firebase": {
      "sign_in_provider": "phone"
    }
  }
}

Документ

Обратите внимание на то, как документ включает ОБА, userPhone и userEmail

1 Ответ

1 голос
/ 03 августа 2020

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

Ваш запрос запрашивает все документы в PendingInvites, где userPhone == +16505551234. Однако ваши правила не позволяют этого по двум причинам:

  1. Ваш запрос не соответствует ограничениям правила (что и userPhone, и userEmail имеют значения c). Запрос просто указывает userPhone.
  2. Система не будет выполнять get() для каждого документа, который может совпадать. Хотя это будет работать для отдельных документов, полученных от клиента, это не будет работать для запросов, которые могут вернуть любое количество документов.

Таким образом, вам придется решить обе проблемы.

  1. Ваш запрос должен будет отфильтровываться с использованием как userPhone, так и userEmail в соответствии с вашими правилами. Это означает, что вам нужно будет добавить еще один whereEqualTo в userEmail, который соответствует требованиям правил. Другими словами, клиентское приложение должно передать адрес электронной почты пользователя в этом фильтре.

  2. Вам вообще не нужно использовать get() в правилах. Вы можете ссылаться на поля в документах в текущей коллекции через resource.data.

Для правил также потребуется что-то вроде этого:

match /PendingInvites/{inviteID} {
    allow read: if
        request.auth != null && 
        resource.data.userPhone == request.auth.token.phone_number &&
        resource.data.userEmail == request.auth.token.email;
}
...