Node JS validation - javascript

I'm new to NodeJS, and have written a method to create a new user, but I need to validate the parameters passed. I'm attempting make sure that an email is not registered twice. This doesn't work, because it checks if the error array is empty before the self.emailExists() callback is completed, how do I fix this?
userSchema.statics.buildUser = function(email, name, cb) {
var self = this;
var user = new this();
var errors = [];
if (!validator.isEmail(email)) {
errors.push({
'err': -1,
'msg': 'Invalid email'
});
} else {
self.emailExists(email, function(exists) {
if (exists) {
errors.push({
'err': -1,
'msg': 'Email address is already in use'
});
} else {
user.email = email;
}
});
}
if (!validator.trim(name).length > 0) {
errors.push({
'err': -1,
'msg': 'Invalid name'
});
} else {
user.name = name;
}
if (errors.length != 0) {
cb(errors, null);
} else {
cb(false, user);
}
}
My emailExists method is:
userSchema.statics.emailExists = function(email, cb) {
var self = this;
self.count({email: email}, function (err, count) {
cb(count > 0);
});
}

You need to restructure your code to put the errors.length check in emailExists() callback. Try Async.js and Promises to manage asynchronous calls better

Related

TypeError: errors.forEach is not a function

I am working on a nodejs app. And I am getting this
TypeError: errors.forEach is not a function
error on my route file.
The code works fine without the promise function(). But as soon as I add the promise function. It throws the error
router.post('/signup', function(req, res, next) {
req.checkBody('email', 'Oops! A valid email is required.').isEmail() //validate email
var errors = req.validationErrors()
//look for already registered on database
//create a global variable called globalvar
var globalvar = {}; // Globally scoped object
//start function
var promise = new Promise(function findemail(resolve, reject) { //using promise
const find = db.collection('users').doc(email);
const doc = find.get();
if (!doc.exists) {
resolve();
} else {
reject();
}
});
promise.
then(function findemail() {
globalvar.bool = true;
console.log('email does not exists');
var errors = req.validationErrors();
}).
catch(function findemail() {
globalvar.bool = false;
console.log('email exists');
var errors = req.validationErrors();
});
//If no errors are found continue registration
if (!errors && globalvar.bool == true) {
//add user data
}
//DISPLAY ERRORS TO USER
else {
var error_msg = ''
errors.forEach(function(error) {
error_msg += error.msg + '<br>'
})
req.flash('error', error_msg)
res.render('signup', {
title: 'Registration Page',
name: req.body.name,
email: req.body.email,
password: ''
})
}
})
check the variable type of errors variable, it should be an array, map, or set.

accessing global function with javascript using mysql

I am trying to validate the user before accessing the content. I have declared function globally and passing it inside the body. When I run it , I am getting error has: user doesn't exist . Please let me know where I am going wrong.
function validate(user_id){
var user_id = db.query('select user_id from user WHERE user_id = ?', [user_id],
function(error,rows) {
if (user_id != user_id) {
return false;
} else {
return true;
}
});
}
router.post('/addcustomerskills', function(req,res) {
if (validate(user_id == true)) {
return true;
// my code should execute
}else {
response.success= false;
response.mssg = "User Doesn't Exist";
res.json(response);
}
function validate(user_id, req, res){
db.query('select user_id from user WHERE user_id = ?', [user_id], function(error,rows) {
if (error || rows.length === 0) {
var response = {}
response.success= false;
response.mssg = "User Doesn't Exist";
res.json(response);
} else {
// my code should execute
return true;
}
});
}
router.post('/addcustomerskills', function(req,res) {
validate(req.body.user_id, req, res);
})

NodeJs check username and password return null

I'm trying to check the entered username and password stored in a database.
My solution is not correct and I think there might be something better than my code.
Here it is thus far:
function login (username, password, callback) {
var query = "SELECT * FROM users WHERE username = ?";
connection.query(query, [username], function (err, results) {
if (err) return callback(err);
if (results.length === 0) return callback();
var user = results[0];
if (!bcrypt.compareSync(password, user.password)) {
return callback();
}
callback(null, {
id: user.id.toString(),
});
});
}
app.get('/salam', function (req, res) {
var username = 'mahdi';
var originalPassword = 'a';
login(username , originalPassword,function (callback) {
console.log(callback);
});
});
In my code, console.log(callback); returns null, but usernames and passwords are correct. How can I fix this?
In your success callback function, you are having 2 arguments but in error callback, only one argument.
In error and success case, value of first parameter will always be null and in if (!bcrypt.compareSync(password, user.password)) { case, value of first argument will be undefined as there is no value being passed as argument.
Suggestion: Use first argument as Boolean(false or true) and based on the value, handle the callback.
function login(username, password, callback) {
var query = "SELECT * FROM users WHERE username = ?";
connection.query(query, [username], function(err, results) {
if (err) return callback(false);
if (results.length === 0) return callback();
var user = results[0];
if (!bcrypt.compareSync(password, user.password)) {
return callback(false);
}
callback(true, {
id: user.id.toString(),
});
});
}
app.get('/salam', function(req, res) {
var username = 'mahdi';
var originalPassword = 'a';
login(username, originalPassword, function(success, value) {
if (success) {
console.log(value);
}
});
});
It should be, because you didn't pass anything in callback. Change like this :
function login (username, password, callback) {
var query = "SELECT * FROM users WHERE username = ?";
connection.query(query, [username], function (err, results) {
if (err) return callback(err);
if (results.length === 0) return callback(null, false);
var user = results[0];
if (!bcrypt.compareSync(password, user.password)) {
return callback(null, false);
}
callback(null, true, {
id: user.id.toString(),
});
});
}
app.get('/check', function (req, res) {
var username = 'mahdi';
var originalPassword = 'a';
login(username , originalPassword,function (err, result, id) {
console.log(err);
console.log(result);
console.log(id);
});
});
result is for finding out true|false of action. And id means when result is true
Also err for callback is needed to error handling

How to wait for results inside an if statement in js?

I'm bulding a node.js backend for a webapp and when i submit a form, i do various validations. One of them is to check if an invitation already exists with the same email address.(isUserAlreadyInvited function)
I created a function for this, however when i call this, i guess the response is not that fast and it just moves to the next statement even if the check returns true. How
//Loop through emails one by one
var emails_to_invite = ["test#test.com","invalid.com"];
var response_items = [];
async.each(emails_to_invite,
function(email, callback){
//Response item
var response_item = {}
response_item.email = email;
//Validate
if(Joi.validate({ email: email }, apiSchema).error) {
response_item.error = "not valid email";
response_items.push(response_item);
callback();
} else if(email == user.email) {
response_item.error = "Sending an invitation to your own email is kinda dumb";
response_items.push(response_item);
callback();
} else if(isUserAlreadyInvited(email,user_id)) {
response_item.error = "already invited";
response_items.push(response_item);
callback();
} else {
sendInvitationEmail(email,user_id,null,null,function(invitation_code){
if(invitation_code) {
response_item.invitationCode = invitation_code;
} else {
response_item.error = "server error";
}
response_items.push(response_item);
callback();
});
};
},
function(err){
//Return response
res.status(200).send(response_items);
}
);
function isUserAlreadyInvited(email,invited_by) {
User.findOne({
email: email,
invited_by: invited_by
}, function(err, user) {
if(err) {
return false;
} else {
return true;
}
});
}
Two returns here:
function isUserAlreadyInvited(email,invited_by) {
User.findOne({
email: email,
invited_by: invited_by
}, function(err, user) {
if(err) {
return false;
} else {
return true;
}
});
}
are defined inside this function
function(err, user) {
if(err) {
return false;
} else {
return true;
}
}
and have nothing with return value of isUserAlreadyInvited().
Apparently your isUserAlreadyInvited() is an asynchronous function that needs to be treated asynchronously - it shall get callback function as a parameter. That callback shall be invoked in place of that function(err, user) {}

Node.js mongodb trouble with callbacks

So I'm trying to create a sign up route that checks to see if the user exists first and i have the database call in a separate function that needs to return true or false when it's done. The problem is i'm not very familiar with callbacks and the whole asynchronous thing everything that i have searched for does not seem to work keeps giving me.
TypeError: callback is not a function
This is my code any help or direction would be appreciated.
function pullUserFromDatabase(username, callback) {
console.log(username); //for debug
mongodb.connect(url, function(err, db) {
if(err) {
console.log("didn't get far" + err) //for debug
}
var collection = db.collection(username);
collection.findOne({username}, function(err, item) {
if(err) {
console.log("nope it broke" + err) //for debug
} else {
console.log("it worked" + JSON.stringify(item)) //for debug
callback(true);
}
});
});
}
app.post("/signup", function(req, res) {
var username = req.headers["username"],
password = req.headers["password"],
randomSalt = crypto.randomBytes(32).toString("hex"),
passwordHashOutput = crypto.createHash('sha256').update(password + randomSalt).digest("hex");
if(!username || !password) {
res.send("Username or password not provided.")
} else if(pullUserFromDatabase(username)) {
res.send("User exist.")
}
});
You need to use the callback as follows:
function pullUserFromDatabase(data, callback) {
console.log(data.username); //for debug
mongodb.connect(url, function(err, db) {
if(err) {
console.log("didn't get far" + err) //for debug
}
var collection = db.collection(data.collection);
collection.find({"username": data.username}).count(function (err, count) {
callback(err, !! count);
});
});
};
app.post("/signup", function(req, res) {
var username = req.headers["username"],
password = req.headers["password"],
randomSalt = crypto.randomBytes(32).toString("hex"),
passwordHashOutput = crypto.createHash('sha256').update(password + randomSalt).digest("hex");
if(!username || !password) {
res.send("Username or password not provided.")
}
var data = {
username: username,
collection: "collectionName"
}
if(!username || !password) {
res.send("Username or password not provided.")
}
pullUserFromDatabase(data, function(err, exists) {
if (err) {
res.send(400, "Error - " + err);
}
else if(exists) {
res.send(200, "User exists.");
}
res.send(200, "User does not exist.");
});
});
The reason that callback is undefined is because you didn't pass a 2nd argument to pullUserFromDatabase(username) Provide a 2nd argument, eg. pullUserFromDatabase(username, function(result) {/* do something here with the result variable */})
If you're not very familiar with aync & callbacks, you might find it more intuitive to use promises, but that comes with its own learning curve.
In the context of the original code, this looks like:
...
if(!username || !password) {
res.send("Username or password not provided.");
return;
}
pullUserFromDatabase(username, function(result) {
if(result) {
res.send("User exist.");
} else {
// TODO: Handle this case. If res.send() is never called, the HTTP request won't complete
}
});
...
Also, you need to ensure your callback is always invoked. Add callback(false):
console.log("nope it broke" + err); //for debug
callback(false);
Do a similar step after "didn't get far" and then return so the callback doesn't get invoked multiple times.

Categories

Resources