2

I've incorporated a sign-up flow of five view controllers as opposed to one central VC for Firebase sign up.

Normally there would be the problem of data being lost before sign up, but I'm pushing all the entered values via segue programmatically to the final confirmation page and sending the data to Firebase for auth eventually.

My problem lies therein - I want to check if the username exists before signing up. This is imperative for the UX of my app and I can't just do this all one VC.

Here's the code I have for the UsernameViewController:

   let rootRef = FIRDatabase.database().reference()

   rootRef.queryOrdered(byChild: "users").queryEqual(toValue: self.chooseUsernameTextField.text!)
    .observe(FIRDataEventType.value, with: { (snapshot: FIRDataSnapshot!)  in

            if snapshot.hasChildren() == false {
                print("not found")

            } else {
                print("usr found")
            }
        });

Here's the code I have for the Firebase Database Security Rules

   {
     "rules": {
        ".read": false,
        ".write": false,
      "users": {
        ".validate": "data.child('username').val() === true",
      ".read": true
      }
     }
    }

and finally, a screenshot of my Data tree (My Data tree won't let me nest any new users or create a user node without a value for some reason):

Picture of Firebase Data Tree: App Name/Users

I have a nagging suspicion that my data rules and tree are configured properly to match the code, but I'm stuck in a XY problem of not knowing what to do for Firebase security to get my code of username checking complete.

Please help me! :(

J.G. Homework
  • 33
  • 1
  • 5
  • Possible duplicate of [Firebase android : make username unique](http://stackoverflow.com/questions/35243492/firebase-android-make-username-unique) – Jay Dec 10 '16 at 14:16

3 Answers3

3

If there's a user created within the Auth section of Firebase as well, then you can actually use the fetchProviders method, and if no providers are returned, you have no user in you Auth section.

FIRAuth.auth()?.fetchProviders(forEmail: email, completion: { (providers, error) in
            if providers == nil {
                   // user doesn't exist
              } else {
                   // user does exist
              }
        })
MQLN
  • 2,292
  • 2
  • 18
  • 33
2

I have not tested the code but the theory would be to order by username that equals to the username you are looking for. If this snapshot exists you already have a user in the database with that name if it doesn't you do not.

Will run and test code when i have a chance to and update my post.

 let rootRef = FIRDatabase.database().reference()

      rootRef.child("users").queryOrdered(byChild:"username").queryEqual(toValue:   self.chooseUsernameTextField.text!)
    .observe(.value, with: { (snapshot)  in

            if snapshot.exists() == false {
                print("not found")

            } else {
                print("usr found")
            }
        });
Abishek Gokal
  • 186
  • 2
  • 13
  • Update If you do not want to make your users node readable by unauthenticated users you can store already taken usernames in a separate node and allow unauthenticated users to read from that list. Then check if the username occurs in that list. – Abishek Gokal Aug 09 '17 at 22:46
0

When using Firestore to save users, I did this

 Auth.auth().addStateDidChangeListener({ (auth, user) in 
     if let id = user?.uid{ 
        let userDoc =  db.collection("users").document(id)
        userDoc.getDocument { (document, error) in
            if document == nil{// if user doesn't exist, create one
                self.db.collection("users").document(id).setData(userProfile.toDictionary()){ error in

                }
            }
        }
    }
    })
fullmoon
  • 8,030
  • 5
  • 43
  • 58