0

I have a username field and an email field on signup and I want to check if they exist before adding the user to the database. Most examples for passport only look up one field like username and I cant figure out how to look up 2. If I do what I have below and the user enters an existing username but a non-existing email it would go through and if the user enters an existing email but a non-existing username it would go through because their is no username.

I know why that is happening. I just can't figure out how to put the 2 queries together so it saves it only after it sees that there is no username and or no email. To be clearer, there should be no duplicates of usernames and emails.

I was thinking maybe setting a variable in the else statement saying that it is ok to save the user and later in the code check to see if there are 2 of these variables and if there are those variables then save but I don't know how to do that. I think it would be hard since the queries are asynchronous. I wish I could do that method.

and how would I deal with the connect-flash messages?

passport.use("local-signup", new LocalStrategy({
    usernameField : "email",
    passwordField : "password",
    passReqToCallback : true
},
    function(req, email, password, done){
        User.findOne({"email" : email}, function(err, user){
            if(err) return done(err);
            if(user){
                return done(null, false, req.flash("signupMessage", "That email is already taken"))
            }else{
                var newUser = new User();
                newUser.username = req.body.username;
                newUser.password = password;
                newUser.email = req.body.email;

                newUser.save(function(err, doc){
                    if(err) throw err;
                    console.log("doc", " " , doc)
                    return done(null, newUser);
                })
            }
        })
        console.log("username " + req.body.username)
        User.findOne({"username" : req.body.username}, function(err, user){
            if(err) return done(err);
            if(user){
                return done(null, false, req.flash("signupMessage", "that username is taken"))
            }else{
                var newUser = new User();
                newUser.username = req.body.username;
                newUser.password = password;
                newUser.email = req.body.email;

                newUser.save(function(err, doc){
                    if(err) throw err;
                    console.log("doc", " " , doc)
                    return done(null, newUser);
                })
            }
        })
    }
))
jack blank
  • 5,073
  • 7
  • 41
  • 73

1 Answers1

0

There are many ways you can do this.

Example, you can do it the promise way; where you can simultaneously perform and async calls to check for both username and email and if both calls return an OK result and then you proceed to insert.

See:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

Since you already got some code up there, I'll do the conventional nested step by step async way.

What I got below is - first I perform a call to User.findOne() to check for the email and if the value is unique then proceed to check the username using User.findOne() again.

The code only proceeds to insert the user when the 2nd User.findOne() call reports fine.

Note: while this logic works but if you nest too many calls you will get into what the Javascript community usually describe as the callback hell.

passport.use("local-signup", new LocalStrategy({
      usernameField : "email",
      passwordField : "password",
      passReqToCallback : true
    },
    function(req, email, password, done){
      // register user only if the email and username is unique
      // Step 1: Check email
      User.findOne({"email" : email}, function(err, user){
        if(err) return done(err);
        if(user){
          return done(null, false, req.flash("signupMessage", "That email is already taken"))
        } else {
          // Email is fine.
          // Step 2: Check username
          User.findOne({"username" : req.body.username}, function(err, user){
            if(err) return done(err);
            if(user){
              return done(null, false, req.flash("signupMessage", "that username is taken"))
            }else{
              // User name is fine too
              // Step 3: Create user
              var newUser = new User();
              newUser.username = req.body.username;
              newUser.password = password;
              newUser.email = req.body.email;

              newUser.save(function(err, doc){
                if(err) throw err;
                // User created
                console.log("doc", " " , doc);
                return done(null, newUser);
              });
            }
          });
        }
      });
    };
Samuel Toh
  • 18,006
  • 3
  • 24
  • 39
  • @jack blank Unfortunately I can't test the code above as it is specific to your project only. Please let me know if it works for you. Happy to have another look. – Samuel Toh Jul 26 '16 at 06:07
  • Thank you for your help and eplanation. It seems to work but I have problem sending 2 flash messages now. look at the question in the link provided. I would appreciate your continued help.http://stackoverflow.com/questions/38597793/sending-2-flash-messages-when-to-queries-to-databse-show-that-fields-exist-in-pa – jack blank Jul 26 '16 at 18:56
  • @jackblank answer added for the other question. – Samuel Toh Jul 27 '16 at 09:10