Firebase iOS Swift:防止重复的用户名

时间:2016-05-10 00:14:25

标签: ios swift firebase

我正在构建一个使用Firebase的电子邮件和密码登录功能的应用。我正在向用户注册用户名,电子邮件和密码。如果用户名不是唯一的,我正在努力阻止如何创建用户。我一直在阅读其他问题(特别是Firebase-android-make-username-uniquehow-prevent-username-from-duplicate-signup-infirebase),但我仍然没有完全发挥作用。

我按照上面第一个链接中的说明设置我的数据结构:

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

我的安全规则为:

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

使用此设置,如果我尝试使用已存在的用户名创建新用户,则会阻止用户添加到我的数据结构中。当调用以下代码时,如果用户名是重复的,则会打印“无法保存用户数据”。

  func createNewAccount(uid: String, user: Dictionary<String, String>) {

    USER_REF.childByAppendingPath(uid).setValue(user, withCompletionBlock: {
      (error:NSError?, ref:Firebase!) in
      if (error != nil) {
        print("User Data could not be saved.")
      } else {
        print("User Data saved successfully!")
      }
    })
  }

  func addUsernameToUsernamePath (userData: Dictionary<String, String>) {

    USERNAME_REF.updateChildValues(userData)
  }

这是我被困的地方。下面的我的创建帐户方法在调用createUser和authUser之前不调用上述两种方法(我需要获取uid)。我的问题是用户仍然是作为注册用户创建的,我的安全规则只是保持用户信息不被添加到我的数据结构中。如果用户名重复,我需要弄清楚如何阻止用户创建。

@IBAction func createAccount() {
    let username = usernameField.text
    let email = emailField.text
    let password = passwordField.text

    if username != "" && email != "" && password != "" {

      // Set Email and Password for the New User.

      DataService.dataService.BASE_REF.createUser(email, password: password, withValueCompletionBlock: { error, result in

        if error != nil {
          print("Error: \(error)")
          if let errorCode = FAuthenticationError(rawValue: error.code) {
            switch (errorCode) {
            case .EmailTaken:
              self.signupErrorAlert("Email In Use", message: "An account has already been created for this email address.")
            default:
              self.signupErrorAlert("Oops!", message: "Having some trouble creating your account. Please try again or check your internet connection.")
            }
          }

        } else {

          DataService.dataService.BASE_REF.authUser(email, password: password, withCompletionBlock: {
            err, authData in


            let user = ["provider": authData.provider!, "email": email!, "username": username!]
            let userData = [username!: authData.uid!]

            DataService.dataService.createNewAccount(authData.uid, user: user)
            DataService.dataService.addUsernameToUsernamePath(userData)          

          })

修改

这是我更新的createAccount方法,解决了我的问题。

  @IBAction func createAccount() {
    let username = usernameField.text
    let email = emailField.text
    let password = passwordField.text


if username != "" && email != "" && password != "" {

  DataService.dataService.USERNAME_REF.observeEventType(.Value, withBlock: { snapshot in
    var usernamesMatched = false
    if snapshot.value is NSNull {
      usernamesMatched = false
    } else {
      let usernameDictionary = snapshot.value
      let usernameArray = Array(usernameDictionary.allKeys as! [String])
      for storedUserName in usernameArray {
        if storedUserName == self.usernameField.text! {
          usernamesMatched = true
          self.signupErrorAlert("Username Already Taken", message: "Please try a different username")
        }
      }
    }

    if !usernamesMatched {
      // Set Email and Password for the New User.

      DataService.dataService.BASE_REF.createUser(email, password: password, withValueCompletionBlock: { error, result in

        if error != nil {
          print("Error: \(error)")
          if let errorCode = FAuthenticationError(rawValue: error.code) {
            switch (errorCode) {
            case .EmailTaken:
              self.signupErrorAlert("Email In Use", message: "An account has already been created for this email address.")
            default:
              self.signupErrorAlert("Oops!", message: "Having some trouble creating your account. Please try again or check your internet connection.")
            }
          }

        } else {

          // Create and Login the New User with authUser
          DataService.dataService.BASE_REF.authUser(email, password: password, withCompletionBlock: {
            err, authData in


            let user = ["provider": authData.provider!, "email": email!, "username": username!]
            let userData = [username!: authData.uid!]

            // Seal the deal in DataService.swift.
            DataService.dataService.createNewAccount(authData.uid, user: user)
            DataService.dataService.addUsernameToUsernamePath(userData)


          })

2 个答案:

答案 0 :(得分:1)

您可以在没有有效用户名的情况下进行注册,并拥有单独的&#34;设置用户名&#34;您在部分注册时显示的屏幕。

定义安全规则以在允许写入数据库的其他部分之前检查非空用户名。

答案 1 :(得分:0)

我能够通过将createAccount()更新为下面的代码来实现它。

  @IBAction func createAccount() {
    let username = usernameField.text
    let email = emailField.text
    let password = passwordField.text


    if username != "" && email != "" && password != "" {

      // Checks for internet connection before saving the meetup. Returns if there is no internet connection.
      let reachability = try! Reachability.reachabilityForInternetConnection()

      if reachability.currentReachabilityStatus == .NotReachable {
        let internetAlert = UIAlertController(title: "No Internet Connection", message: "Please make sure your device is connected to the internet.", preferredStyle: .Alert)
        let internetAlertAction = UIAlertAction(title: "OK", style: .Default, handler: nil)
        internetAlert.addAction(internetAlertAction)
        presentViewController(internetAlert, animated: true, completion: nil)
        return
      }
      DataService.dataService.USERNAME_REF.observeEventType(.Value, withBlock: { snapshot in
        var usernamesMatched = false
        if snapshot.value is NSNull {
          usernamesMatched = false
        } else {
          let usernameDictionary = snapshot.value
          let usernameArray = Array(usernameDictionary.allKeys as! [String])
          for storedUserName in usernameArray {
            if storedUserName == self.usernameField.text! {
              usernamesMatched = true
              self.signupErrorAlert("Username Already Taken", message: "Please try a different username")
            }
          }
        }

        if !usernamesMatched {
          // Set Email and Password for the New User.

          DataService.dataService.BASE_REF.createUser(email, password: password, withValueCompletionBlock: { error, result in

            if error != nil {
              print("Error: \(error)")
              if let errorCode = FAuthenticationError(rawValue: error.code) {
                switch (errorCode) {
                case .EmailTaken:
                  self.signupErrorAlert("Email In Use", message: "An account has already been created for this email address.")
                default:
                  self.signupErrorAlert("Oops!", message: "Having some trouble creating your account. Please try again or check your internet connection.")
                }
              }

            } else {

              // Create and Login the New User with authUser
              DataService.dataService.BASE_REF.authUser(email, password: password, withCompletionBlock: {
                err, authData in


                let user = ["provider": authData.provider!, "email": email!, "username": username!]
                let userData = [username!: authData.uid!]

                // Seal the deal in DataService.swift.
                DataService.dataService.createNewAccount(authData.uid, user: user)
                DataService.dataService.addUsernameToUsernamePath(userData)


              })