Firebase android: rendre le nom d'utilisateur unique

Parse va fermer à la fin de l'année, j'ai donc décidé de commencer à utiliser Firebase. J'ai besoin de mettre en place un processus d'enregistrement avec 3 champs: email, nom d'utilisateur, mot de passe ( courriel & nom d'utilisateur doit être unique pour mon application).

<!-Puisque Firebase ne fournit pas un moyen facile de gérer le nom d'utilisateur comme Parse, j'ai décidé d'utiliser seulement l'enregistrement de l'email/mot de passe et d'enregistrer quelques données supplémentaires comme le nom d'utilisateur. Voici la structure des données de mes utilisateurs:

app : {
    users: {
       "some-user-uid": {
            email: "test@test.com"
            username: "myname"
       }
    }
}

Mais, ce que je veux faire est de rendre le nom d'utilisateur unique et de la vérifier avant de créer un compte. Ce sont mes règles :

{
    "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()"}
            }
        }
   }
}

je vous Remercie beaucoup pour votre aide

25
demandé sur FloGz 2016-02-06 19:37:48

3 réponses

une partie de la réponse est de stocker un index des noms d'utilisateurs, que vous vérifiez dans vos règles de sécurité:

app : {
    users: {
       "some-user-uid": {
            email: "test@test.com"
            username: "myname"
       }
    },
    usernames: {
        "myname": "some-user-uid"
    }
}

usernames le noeud établit une correspondance entre un nom d'utilisateur et un uid. Il se lit essentiellement comme "username' myname 'est détenu par'some-user-uid'".

avec cette structure de données, vos règles de sécurité peuvent vérifier s'il y a déjà une entrée pour un nom d'utilisateur donné:

"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"
    }
  }
}

ceci confirme que le nom d'utilisateur N'est pas réclamé par quelqu'un encore ou il est réclamé par le l'utilisateur actuel.

41
répondu Frank van Puffelen 2016-02-06 18:22:34

enregistrer les noms d'utilisateurs comme suggéré par Frank mais quand vous enregistrez les noms d'utilisateurs, utilisez la fonction runTransaction dans Firebase pour s'assurer que le nom d'utilisateur n'est pas pris. Cette fonction est assurée par Firebase pour être une opération atomique de sorte que vous pouvez être assuré de pas de collision

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
répondu Viven 2016-03-28 01:49:00

Je ne sais pas encore grand chose sur la sécurité firebase, mais j'ai peut-être résolu le problème en utilisant Java. Je l'ai posté ci-dessous.

ma structure de données est

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];
    }
-3
répondu SJSU Software Engineer 2016-03-21 10:33:28