Подтвердить что ты не робот

Firebase android: уникальное имя пользователя

В конце года Parse будет закрыт, поэтому я решил начать использовать Firebase. Мне нужно реализовать процесс регистрации с тремя полями: электронная почта, имя пользователя, пароль ( Электронная почта и имя пользователя должны быть уникальными для моего приложения).

Поскольку Firebase не предоставляет простой способ управлять именем пользователя, например Parse, я решил использовать только регистрацию по электронной почте/паролю и сохранить некоторые дополнительные данные, такие как имя пользователя. Вот моя структура данных пользователей:

app : {
    users: {
       "some-user-uid": {
            email: "[email protected]"
            username: "myname"
       }
    }
}

Но я хочу сделать уникальное имя пользователя и проверить его перед созданием учетной записи. Это мои правила:

{
    "rules": {
        ".read": true,
        ".write": true,
        "users": {
            "$uid": {
                ".write": "auth !== null && auth.uid === $uid",
                ".read": "auth !== null && auth.provider === 'password'",
                "username": {".validate": "!root.child('users').child(newData.child('username').val()).exists()"}
            }
        }
   }
}

Большое спасибо за вашу помощь.

4b9b3361

Ответ 1

Часть ответа заключается в том, чтобы хранить индекс имен пользователей, которые вы проверяете в своих правилах безопасности:

app : {
    users: {
       "some-user-uid": {
            email: "[email protected]"
            username: "myname"
       }
    },
    usernames: {
        "myname": "some-user-uid"
    }
}

Таким образом, usernames node отображает имя пользователя в uid. Он по существу читает, что "имя пользователя" myname "принадлежит" some-user-uid ".

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

"users": {
  "$uid": {
    ".write": "auth !== null && auth.uid === $uid",
    ".read": "auth !== null && auth.provider === 'password'",
    "username": {
      ".validate": "
        !root.child('usernames').child(newData.val()).exists() ||
        root.child('usernames').child(newData.val()).val() == $uid"
    }
  }
}

Это подтверждает, что имя пользователя еще не заявлено кем-либо еще, или оно заявлено текущим пользователем.

Ответ 2

Сохраните имена пользователей, предложенные Фрэнком, но при сохранении имен пользователей используйте функцию RunTransaction в Firebase, чтобы убедиться, что имя пользователя не занято. Эта функция гарантируется Firebase как атомная операция, поэтому вы можете быть уверены в отсутствии столкновения.

firebaseRef.child("usernames").child(username).runTransaction(new Transaction.Handler() {
    @Override
    public Transaction.Result doTransaction(MutableData mutableData) {
        if (mutableData.getValue() == null) {
            mutableData.setValue(authData.getUid());
            return Transaction.success(mutableData);
        }

        return Transaction.abort();
    }

    @Override
    public void onComplete(FirebaseError firebaseError, boolean commited, DataSnapshot dataSnapshot) {
        if (commited) {
            // username saved
        } else {
            // username exists
        }
    }
});

Ответ 3

Я не знаю многого о безопасности firebase, но я, возможно, решил проблему с использованием Java. Я разместил его ниже.

моя структура данных

myapp
{
  users: {
          <unique generated-id>
          { username: "example.username" }
}
}


public boolean isUsernameExists(final String enteredUsername) {
        final Boolean[] isExist = {false};
        FBref.child("users").addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                for (DataSnapshot userSnapshot : dataSnapshot.getChildren()) {
                    String existingUsername = (String) userSnapshot.child("userName").getValue();
                    if (existingUsername.equals(enteredUsername)) {
                        isExist[0] = true;
                    }
                }
            }
            @Override
            public void onCancelled(FirebaseError firebaseError) {
                //some error thrown here
            }
        });
        return isExist[0];
    }