2

I want to prevent duplicate username while signUp form what user entered. I have created email login like below, firtly createUser and then auth it setValue with user dictionary.

But I stack with Firebase security settings and how to check handle this situation.

REF_BASE.createUser(email, password: pwd, withValueCompletionBlock: { ..

REF_BASE.authUser(email, password: pwd, withCompletionBlock: { ..

REF_USERS.childByAppendingPath(uid).setValue(user)

This handling always response error.

REF_USERS.childByAppendingPath(uid).childByAppendingPath("username").setValue(user["username"]) { (error: NSError!, result: Firebase!) in
            if error != nil {
                print(error.localizedDescription)
            }
            else { 
                self.REF_USERS.childByAppendingPath(uid).setValue(user)
            }
        }

This is my security rules, How Can I fix everything to be prevented from duplicate user?

"users": {
      ".read": "auth !== null",
      "$user": {
           "username": {
               ".read": "auth !== null",
               ".write": "newData.val() === auth.uid && !data.exists()"
           }
      }
    },

Update:

From Frank's answer, but I don't know what I need to do while signUp new user for swift in this situation.

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

Need I add same user uid at the same time for two different nodes? If someone explain it in Swift. It would be great.

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

I couldn't add new user informations to usernames parent node. It's needed another security rules?

iamburak
  • 3,508
  • 4
  • 34
  • 65
  • What error are you getting exactly? – André Kool Apr 28 '16 at 13:31
  • I'm getting, [Firebase] setValue: or removeValue: at /users/8372c890-112d-4a75-924c-98814ea15963/username failed: permission_denied – iamburak Apr 28 '16 at 13:38
  • First point is your second .read rule is obsolete because [rules cascade](https://www.firebase.com/docs/security/guide/securing-data.html#section-cascade). And for the error i'm not completely sure but it looks like you try to write a user to firebase and in your rules you only allow the value to be the uid (newData.val() === auth.uid) – André Kool Apr 28 '16 at 13:49

1 Answers1

0

If you are trying to prevent duplicate Firebase usernames, that can be done right at the createUser stage.

Assume a dialog is presented to new user asking to create an account: this will get their desired userName and password.

Send that to createUser and if there's an error (because it already exists) notify them and ask for a different userName:

    myRootRef.createUser(email, password: pw, withValueCompletionBlock: { error, result in

        if error != nil {
            self.errMsgField.stringValue = "email/username in use, try again"

        } else {
            let uid = result["uid"] as! String //the uid of the new user
            print("user created as  \(uid)")
            self.authUserWithAuthData( email, password: pw ) //auth the user
        }
    })

After the user is created you would probably add their info the /users node as well.

Jay
  • 34,438
  • 18
  • 52
  • 81