Как разрешить доступ к указанному c полю внутри поля, для которого требуется авторизация, правила базы данных firebase - PullRequest
0 голосов
/ 01 мая 2020

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

У меня есть функция поиска в моем приложении, которая позволяет пользователям искать других пользователей по имени пользователя

Правила Firebase

{
  "rules": {
    "users": {
      "$uid": {
        // Allow only authenticated content owners access to their data
        ".read": "auth.uid != null",
        ".write": "auth.uid != null"
      },

    },
    "chat": {
      "messages": {
        ".write": true,
        ".read": true
      }
    },
    "app-settings": {
      ".write": true,
      ".read": true
    }
  }
}

Здесь JSON пользователей

{
  "app-settings" : {
    "app-Available" : true,
    "version" : "4"
  },

  "users" : {
    "uid" : {
      "blocked" : false,
      "email" : "gamatiaihab@gmail.com",
      "profilePhotoUrl" : "https://lh3.googleusercontent.com/a-/AOh14Gi6eXrdLfZTQH0B7GvoTxhqBHoVFUUTibK3QKfrfA=s96-c",
      "uid" : "uid",
      "userName" : "gamatiaihab"
    }

  }
} 

В моем приложении есть функция, позволяющая пользователю изменять свое имя пользователя с помощью этого кода. я пытаюсь проверить, проверяет ли имя пользователя, было ли это занято другим пользователем, я обычно обращаюсь к информации об одном пользователе с помощью child(uid), это работает, если правила firebase настроены только для аутентифицированных пользователей, но для проверки имени пользователя I Мне не нужно заказывать by child(uid), потому что это вернет только одного пользователя, который является текущим пользователем, мне нужно упорядочить по child ("users"). orderBy ("userName"), и это вернет PERMISSION DENIED, потому что я этого не сделал пропуск child(uid)

  private void validateUserName(final String chatUserName){
        mEditChatUserNamePr.setVisibility(View.VISIBLE);
        mDb = FirebaseDatabase.getInstance().getReference().child("users");
        mDb.orderByChild("userName")
                .equalTo(chatUserName)
                 .addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                if (dataSnapshot.getValue() != null){
                    mEditChatUserNamePr.setVisibility(View.GONE);
                    mChatUserNameInput.setError("User name not available");
                }else {
                    updateUserName(chatUserName);

                }


            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

            }
        });
    } 

1 Ответ

1 голос
/ 01 мая 2020

Пользователь либо имеет доступ к полному узлу, либо вообще не имеет доступа к узлу. Невозможно предоставить им доступ только к части каждого дочернего узла.

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

Идиоматизм c (и гарантируется только ) Способ реализации уникальности заключается в использовании вещи, которая должна быть уникальной, в качестве ключей в списке в базе данных. Так что в вашем случае это означало бы:

  1. Создание списка имен пользователей, где каждый ключ является именем пользователя, а каждое значение - UID пользователя с этим именем пользователя.
  2. Использование транзакции, чтобы гарантировать, что два пользователя не обновляют один и тот же узел одновременно.
  3. Использование правил безопасности, чтобы никто не мог перезаписать имя пользователя, которое уже было заявлено другим пользователем.

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

...