Как проверить, существует ли пользователь с адресом электронной почты, введенным пользователем в форме входа, или нет в firebase - PullRequest
0 голосов
/ 19 июня 2019

Я впервые работаю с firestore db.Итак, у меня есть класс User в моем приложении:

data class User(
    val name: String,
    val email: String,
    val standard: String,
    val formNum: String,
    val isVerified: Boolean = false
)

Каждый раз, когда регистрируется новый пользователь, он сохраняет данные в базе данных firestore.Я хочу запросить, когда пользователь нажимает кнопку входа в систему, но , прежде чем они действительно войдут в систему , существует ли пользователь с таким адресом электронной почты или нет.Я использую следующий код:

db.collection(User.USERS_DB_NAME)
            .whereEqualTo("email", email.text.toString())
            .get()
            .addOnSuccessListener {
                if (it.size() == 0)
                {
                    Log.d(TAG, "Email not found")
                    email.error = getString(R.string.error_invalid_email)
                }
            }

Однако в журнале выдается предупреждение:

W / Firestore: (19.0.2) [Firestore]: прослушивание запроса(пользователи, для которых электронная почта == email@example.com) не удалось: Статус {code = PERMISSION_DENIED, description = Отсутствует или недостаточно разрешений., причина = null}

Вот мое правило:

service cloud.firestore {
  match /databases/{database}/documents {
    match /users/{user} {
      allow read, write: if request.auth != null && user == request.auth.uid;
    }
  }
}

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

Ответы [ 3 ]

2 голосов
/ 19 июня 2019

Как я вижу, вы получаете PERMISSION_DENIED при использовании следующей строки:

allow read, write: if request.auth != null && user == request.auth.uid;

Чтобы решить эту проблему, я рекомендую использовать следующие строки кода:

allow read, update, delete: if request.auth.uid == user;
allow create: if request.auth.uid != null;

Что в основном означает, что вы разрешаете операции чтения, обновления и удаления только в том случае, если идентификатор пользователя совпадает с идентификатором из аутентификации Firebase, и вы разрешаете создание нового пользователя, только если идентификатор пользователя null.

Редактировать:

service cloud.firestore {
  match /databases/{database}/documents {
    match /users/{userId} {
      allow read, update, delete: if request.auth.uid == userId;
      allow create: if request.auth.uid != null;
    }
  }
}

Или еще проще:

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if request.auth != null;
    }
  }
}
1 голос
/ 19 июня 2019

Поскольку вы прокомментировали ответ Мухаммеда о том, что пользователь еще не вошел в систему, ожидается, что ваши правила отклонят запрос. Очевидное решение - разрешить чтение всем:

service cloud.firestore {
  match /databases/{database}/documents {
    match /users/{user} {
      allow read;
      allow write: if request.auth != null && user == request.auth.uid;
    }
  }
}

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

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

service cloud.firestore {
  match /databases/{database}/documents {
    match /users/{user} {
      allow list: /* TODO: something to require a query on email address */;
      allow read, write: if request.auth != null && user == request.auth.uid;
    }
  }
}

Примечание: я все еще ищу, как проверить запрос в правилах, поскольку из документации кажется, что условие where() не выставлено в request.query.

Но это по-прежнему сопряжено с риском раскрытия данных другого пользователя: если вы знаете чей-либо адрес электронной почты, вы можете перечислить его документ и таким образом получить его данные.

Чтобы предотвратить это, у вас есть два варианта:

  1. Создание облачной функции (или другой конечной точки на стороне сервера), которая выполняет запрос в доверенной среде и возвращает пользователю только результат true / false.
  2. Создайте отдельную коллекцию, используя только адреса электронной почты пользователей. В этой коллекции я использую адреса электронной почты в качестве идентификатора документа, а затем сохраняю UID пользователя в качестве (вероятно, единственного) значения в документе.

То, что вы пытаетесь реализовать, звучит довольно близко к API Firebase Authentication fetchSignInMethodsForEmail , в котором перечислены поставщики для данного адреса электронной почты. Идея этого API заключается в том, что вы комбинируете его с параметром «разрешить только одну учетную запись на адрес электронной почты», чтобы реализовать поток, в котором на первом экране пользователь вводит свой адрес электронной почты, а затем на втором экране вы либо разрешаете ему зарегистрироваться (адрес электронной почты еще не известен) или запросить их учетные данные.

1 голос
/ 19 июня 2019

Измените Правила на:

service cloud.firestore {
  match /databases/{database}/documents {
    match /users/{user} {
      allow read, write: if request.auth != null;
    }
  }
}
...