Ich erstelle eine App, die Firebases E-Mail- und Passwort-Login verwendet. Ich lasse den Benutzer sich mit einem Benutzernamen, einer E-Mail-Adresse und einem Passwort registrieren. Ich habe Probleme damit, den Benutzer daran zu hindern, erstellt zu werden, wenn der Benutzername nicht eindeutig ist. Ich habe andere Fragen (speziell Firebase-android-make-username-unique und how-prevent-username-from-duplicate-signup-infirebase) gelesen, aber ich habe es immer noch nicht vollständig funktionieren.Firebase iOS Swift: Doppelte Benutzernamen verhindern
folgte ich die Anweisungen in dem ersten Link oben und meine Datenstruktur als ein:
app : {
users: {
"some-user-uid": {
email: "[email protected]"
username: "myname"
}
},
usernames: {
"myname": "some-user-uid"
}
}
und meine Sicherheitsregeln wie:
"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"
}
}
}
Mit diesem Setup, wenn ich versuche zu erstellen Ein neuer Benutzer mit einem bereits vorhandenen Benutzernamen verhindert, dass der Benutzer meiner Datenstruktur hinzugefügt wird. Wenn der folgende Code aufgerufen wird, wird "Benutzerdaten konnten nicht gespeichert" gedruckt, wenn der Benutzername ein Duplikat ist.
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)
}
Hier ist, wo ich feststecke. Meine create account -Methode ruft die oben genannten zwei Methoden nicht auf, bis createUser und authUser aufgerufen werden (was ich brauche, um die UID zu erhalten). Mein Problem ist, dass der Benutzer immer noch als registrierter Benutzer erstellt wird und meine Sicherheitsregeln nur verhindern, dass die Benutzerinformationen zu meiner Datenstruktur hinzugefügt werden. Ich muss herausfinden, wie man den Benutzer daran hindert, erstellt zu werden, wenn es einen doppelten Benutzernamen gibt.
@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
Hier ist meine aktualisierte create Methode, die mein Problem gelöst.
@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)
})
Überprüfen Sie, dass der Benutzername vor dem Aufruf von createUser() nicht existiert? – Kato
Danke für den Vorschlag. Ich habe gerade meinen Code aktualisiert und es scheint das Problem gelöst zu haben. – chickenparm
Warum suchen Sie nicht zuerst nach dem doppelten Benutzernamen, über createUser-> FAuthenticationErrorEmailTaken, und wenn dieser verfügbar ist, erstellen Sie den Benutzer im Knoten/users? Wenn Sie dies tun, können Sie diesen Code auf wenige Zeilen reduzieren, da dieser Benutzername garantiert nicht in Ihrem/users-Knoten vorhanden ist. – Jay