-1

I am trying to check username uniqueness while registering user. I know there are tons of questions about it and I went through all of them however my problem is that it doesn't do anything, it doesn't print that the username exists and it even doesn't register with the username.

What I am doing wrong? I can't seem to find answer, the only thing that could be wrong is the if nesting.

This is the struct:

AppName:
    users
     1v2mRJTvrBQ7dMQohUU3rnn7ypI3: //UID
     username: John

And that is the code:

func registerUser(){
        guard let username = usernameField.text, let email = emailField.text, let password = passwordField.text else{
            print("Successfully registered")
            return
        }
        if connectedToNetwork() == true{
            if passwordField.text == confirmPasswordField.text{
                let usersRef = FIRDatabase.database().reference().child("users")
                usersRef.queryOrdered(byChild: "username").queryEqual(toValue: "\(username)")
                .observeSingleEvent(of: FIRDataEventType.value, with: { (snapshot) in
                    if snapshot.value is NSNull{

                AuthProvider.Instance.register(withEmail: email, password: password, username: username, loginHandler: { (errMessage) in
                    if errMessage != nil{

                    }else{
                        let user = FIRAuth.auth()?.currentUser
                        guard let uid = user?.uid else{
                            return
                        }
                        user?.sendEmailVerification() { error in
                            if let error = error {
                                print(error.localizedDescription)
                            } else {
                                print("Email has been sent to you!")
                            }
                        }
                        //User logged in and redirect

                    }
                })
                    }else{
                    print("Username already exists")// It doesn't execute this
                    }
                })
            }else{
                Util.errorAlert(message: "Passwords do not match!")
            }
        }else{
            Util.errorAlert(message: "The internet connection appears to be offline.")
        }
    }

I even tried different security rules but those shouldn't make any difference but those that I used:

{ 
"rules": { 
".read": "auth != null", 
".write": "auth != null", 
"Snuses": { 
".indexOn": "Brand",
    "$username": {
        ".validate": "!root.child(users').hasChild($username)"
    }
} 
} 
}

What is the thing I am doing wrong?

Tarvo Mäesepp
  • 4,477
  • 3
  • 44
  • 92

3 Answers3

1

Your problem is in your security rules. You're doing a query before the user has been authenticated. This query will fail because your rules state that the user has to be authenticated in order to query the database (auth != null).

What you need to do is create another child called "usernames". Make this readable by anyone without authentication. Check if the username is taken and if not, claim it for the new user. Then, do your auth call and create your user in the "users" child.

Jordi Bruin
  • 1,588
  • 1
  • 11
  • 20
0

Knowing nothing about Firebase, your way of "knowing that it's doing something" appears to be alerting or printing. So if it's not doing that, i see at least two execution paths which don't end in alerting or printing.

if errMessage != nil{

guard let uid = user?.uid else{

Also this could be missing else but i can't find it with the level of effort adequate to answering a S.O. question:

if snapshot.value is NSNull{

Purely theoretically, your Util.errorAlert may be broken too.

Pavel Zdenek
  • 7,146
  • 1
  • 23
  • 38
0

Firebase won't allow duplicate user (names) so just look for an error when you try to create the user.

FIRAuth.auth()?.createUser(withEmail: email, password: password) { (user, error) in
  // ...
}

There are 4 errors that could be returned:

FIRAuthErrorCodeInvalidEmail
     Indicates the email address is malformed.

FIRAuthErrorCodeEmailAlreadyInUse  (this is the one to address you question)
     Indicates the email used to attempt sign up already exists. Call 
     fetchProvidersForEmail to check which sign-in mechanisms such
     user used, and prompt the user to sign in with one of those.

FIRAuthErrorCodeOperationNotAllowed
     Indicates that email and password accounts are not enabled. Enable them in the
     Authentication section of the Firebase console.

FIRAuthErrorCodeWeakPassword
     Indicates an attempt to set a password that is considered too weak. The 
     NSLocalizedFailureReasonErrorKey field in the NSError.userInfo
     dictionary object will contain more detailed explanation that can
     be shown to the user.
Jay
  • 34,438
  • 18
  • 52
  • 81
  • But it doesn't check the username.. Email thing is working but I need to check username also, which is stored inside Firebase database. – Tarvo Mäesepp Nov 16 '16 at 19:37
  • @TarvoMäesepp Is the username that you are storing in firebase the same as the firebase username? It typically would be the same but you may have a different use case. i.e. When you create a user, it's done with their email address and then that is stored in your /users via your code. – Jay Nov 16 '16 at 20:29
  • I am storing "username": "usernameField.text" into firebase database under users node after registration with some other details also. What are better rules then? What do you mean with firebase username? – Tarvo Mäesepp Nov 16 '16 at 20:50
  • @TarvoMäesepp When you create/register a Firebase user, that's done with a username (email) and password. Typically your Firebase structure contains a /users node with the children inside that node being the uid of that user and the children contains other details about the user; address etc. Your goal is to prevent duplicate usernames and that can be accomplished without rules. When you create the Firebase user (with their email) Firebase will throw an error if that username (email) already exists as a Firebase user. Watch for that error and take action if you get an error or proceed if not. – Jay Nov 16 '16 at 22:44