1
votes

I am trying to check if a username already exist in the database.

Here is the code I have written for that..


 func textFieldDidEndEditing(_ textField: UITextField) {

        //check if username is already taken in the database
        let username = self.usernameTextField.text!
        let reference = Database.database().reference().child("activeUsernames")
        let query = reference.queryOrdered(byChild: "username").queryEqual(toValue: username)

        let banner = StatusBarNotificationBanner(title: " The username \(username) is not available.", style: .danger)

        let successBanner =  StatusBarNotificationBanner(title: "The username \(username) is available.", style: .success)

        query.observe(.value, with: { (DataSnapshot) in

            if DataSnapshot.exists() {

                print("Darn username already exists")
                banner.show()

            } else {
               print("Yes I can use this username")
                successBanner.show()



            }

        }, withCancel: nil)
    }

So far it works however inconsistently. Sometimes if I enter a username that already exist the print statement "Yes I can use this username" appears when it clearly is already taken, and sometimes it lets me know it is already taken. I notice I get this statement in the console

Using an unspecified index. Your data will be downloaded and filtered on the client. Consider adding ".indexOn": "username" at /activeUsernames to your security rules for better performance

I'm not sure if this is causing the inconsistency of the checking or not. However I'm not quite sure on how to change or edit the security rules efficiently.

Here is my data struct for active usernames if this helps, just displays users uids and the username associated with that uid..

- activeUsernames
 6GpUz3iLwmWdDrlMtf7tT0yAULw2
 username: 
 8sRfoqa4dKYzUKGdIZAtwE6NQZH2
 username: 
 SRY4xUmRMgXbLL7GfsxosF6sS1y2
 username: 

Also here are the security rules

 "rules": {
    ".read": true,
    ".write": true
  }
}
2

2 Answers

2
votes

To get rid of the message, change your rules to: don't forget to separate them by ,

{
  "rules": {
    ".read": true,
    ".write": true,
    "activeUsernames": {
      ".indexOn": "username"
    }
  } 
}

This tells the Firebase servers to add an index on username under /activeUsernames, which allows it to perform ordering/filtering on the server instead of on the client.

1
votes

The best approach to this would be to create a cloud function that will check if the username is taken and simply return true or false.

  • Having your rules set to true means that anyone can read or write in this database and that is very insecure
  • Using cloud functions that allow to abstract this from your code and be used in any other platform such as android and web
  • Check the cloud function documentation here on how to setup and call your cloud functions, then you can use the Admin SDK in your function to get full access to the database and query the database etc.