Search code examples
gomgo

Logging in with username or email address


I'm trying to improve a block of code in my Go app which handles logins. It receives a login value and a password value and then checks either the username field or the email field in the database to see if a user can be found. If the login contains a @ symbol then email will be used.

So I've currently got:

if strings.Contains(login, "@") {
    err := collection("users").Find(bson.M{"email" : login}).One(&user)
    if err != nil { //no user found
        api.WriteError(w, 400, "USER_NOT_FOUND", "No user found with email address: " + login)
        return
    }
} else {
    err := collection("users").Find(bson.M{"username" : login}).One(&user)
    if err != nil { //no user found
        api.WriteError(w, 400, "USER_NOT_FOUND", "No user found with username: " + login)
        return
    }
}
//go on and check password

but you can see this is not very efficient as I'm having to handle the same error twice. I've also tried:

if strings.Contains(login.Identifier, "@") {
    err := collection("users").Find(bson.M{}).One(&user)
} else {
    err := collection("users").Find(bson.M{"username" : login}).One(&user)
}

if err != nil { //no user found
    api.WriteError(w, 400, "USER_NOT_FOUND", "No user found with email address: " + login)
    return
}
//go on and check password

but err doesn't always exist.

I thought about somehow making the {"username" : login} parts a string variable but I can't seem to get this working.


Solution

  • Something like this?

    field := "username"
    if strings.Contains(login.Identifier, "@") {
        field = "email"
    }
    err := collection("users").Find(bson.M{field: login}).One(&user)
    if err != nil {
        api.WriteError(w, 400, "USER_NOT_FOUND", "No user found with " + field + ": " + login)
    }