Firebase android : make username unique

前端 未结 3 1533
不思量自难忘°
不思量自难忘° 2020-11-21 22:43

Parse will shut down at the end of the year, so I decided to start using Firebase. I need to implement a register process with 3 fields : email, username, password (

相关标签:
3条回答
  • 2020-11-21 23:20

    I dont know much about firebase security yet, but I may have solved the problem using Java. I have posted it below.

    my data structure is

    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];
        }
    
    0 讨论(0)
  • 2020-11-21 23:21

    Save usernames as suggested by Frank but when you save usernames, use runTransaction function in Firebase to make sure that the username is not taken. This function is guaranteed by Firebase to be an atomic operation so you can be rest assured of no 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
            }
        }
    });
    
    0 讨论(0)
  • 2020-11-21 23:33

    Part of the answer is to store an index of usernames, that you check against in your security rules:

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

    So the usernames node maps a username to a uid. It essentially reads as "username 'myname' is owned by 'some-user-uid'".

    With this data structure, your security rules can check if there is already an entry for a given username:

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

    This validates that the username isn't claimed by anyone yet OR it is claimed by the current user.

    0 讨论(0)
提交回复
热议问题