2016-05-10 4 views
0

Я создаю приложение, в котором используется функция входа и пароля Firebase. У меня зарегистрирован пользователь с именем пользователя, электронной почтой и паролем. Я борюсь с тем, как остановить пользователя от создания, если имя пользователя не уникально. Я читал другие вопросы (в частности, Firebase-android-make-username-unique и how-prevent-username-from-duplicate-signup-infirebase), но я до сих пор не получил его для полной работы.Firebase iOS Swift: предотвратить дублирование имен пользователей

Я следовал инструкциям в первой ссылке выше и настроить свою структуру данных, как:

app : { 
    users: { 
     "some-user-uid": { 
      email: "[email protected]" 
      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)   

      }) 

EDIT

Вот мой обновленный метод 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) 


      }) 
+0

Подтвердить, что имя пользователя не существует до вызова createUser()? – Kato

+0

Спасибо за предложение. Я только что обновил свой код и, похоже, решил проблему. – chickenparm

+0

Почему вы не проверяете имя пользователя с двойным именем, через createUser-> FAuthenticationErrorEmailTaken, а если оно доступно, то создайте пользователя в узле/users? Если вы сделаете это, вы можете уменьшить этот код до нескольких строк, так как это имя пользователя не будет уже существовать в вашем/пользовательском узле. – Jay

ответ

1

Вы можете позволить подписаться без действительного имени пользователя и иметь отдельный «установить имя пользователя» экран, который вы показываете в случае частичной регистрации.

Определите свои правила безопасности, чтобы проверить ненулевое имя пользователя, прежде чем разрешить запись в другие части вашей базы данных.

+0

Спасибо за предложение. Я просто нашел способ решить эту проблему, проверив, нет ли имени пользователя до вызова createUser(). Тем не менее, я ценю это предложение и могу его реализовать, если я не доволен своим решением. – chickenparm

+0

Вы, скорее всего, захотите сделать то и другое, иначе у вас будет условие гонки, если два человека регистрируются одновременно для одного и того же имени пользователя. –

+0

Хорошая точка.Я просто попытался создать две учетные записи с одинаковым именем пользователя на двух iPhone. Когда я коснулся создания учетной записи в то же самое время, я столкнулся с проблемами. – chickenparm

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) 


       }) 
Смежные вопросы