Mongodb findone query in node.js & express times out - node.js

I'm trying to find one user in a db where password and username matches. If I write the correct username and password everything works smoothly. But if I write the wrong password for instance I get a timeout after about one minute.
Any suggestions of how I could fix this?
exports.bsLogin = function(req, res) {
console.log('************ bslogin ************');
var body = req.body;
var username2 = body.username;
var password2 = body.password;
db.collection('users', function(err, collection) {
collection.findOne({username:username2, password:password2}, function(err, item) {
if (err) {
res.render('bslogin',
{ title : 'Hello', error : 'Username or Password is incorrect' }
);
return;
}
if (item) {
res.writeHead(302, {
'Location': '/backstageArea'
});
res.end();
}
});
});
};

It's timing out because no response is being given when there is neither an err nor an item.
Based on the current responses, the 1st if could probably be modified to handle both MongoDB errors and lack of items:
if (err || !item) {
res.render('bslogin',
{ title : 'Hello', error : 'Username or Password is incorrect' }
);
return;
}
Or, add an else block to respond to each scenario separately:
if (err) {
/* ... */
} else if (item) {
/* ... */
} else {
/* ... */
}

Related

Cannot set headers after they are sent to the client using express-session

const emailaddress = req.body.emailaddress;
const password = req.body.password;
if (emailaddress && password) {
const query = `SELECT * FROM users where email=? AND password=?`;
connection.query(
query,
[emailaddress, password],
function (err, results, fields) {
if (err) {
res.send({
code: 500,
failed: "Error ocurred",
});
}
if (results.length > 0) {
req.session.regenerate(function (err) {
// if (err) next(err);
req.session.loggedin = true;
req.session.emailaddress = req.body.emailaddress;
req.session.save(function (err) {
// if (err) return next(err);
res.redirect("/home");
});
});
} else {
res.send("Incorrect email address and/or password!");
}
res.end();
}
);
} else {
res.send("Please enter username and/or password");
res.end();
}
I tried using the above code using express-session to store session values. but it gives the following error.
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
How can I avoid this. I already tried many solutions. I am following their documentation. Please help. Thank you.
https://www.npmjs.com/package/express-session
Possible problems:
Else block calls send and last line outside if and else calls end().
So if it falls into the Else block, both send and end will be called causing that error.
You also have multiple call to next(err), without knowing that is the next handler, I can tell you for sure, but they might be calling send as well. Which would fall into the same scenario as above.
I see you made some changes in your code after my answer.
Let me try again, you cannot use res.send and res.end together, you need to pick one. Also you need to make sure you are only calling res.send once.
your code should be something like this:
const emailaddress = req.body.emailaddress;
const password = req.body.password;
if (emailaddress && password) {
const query = `SELECT * FROM users where email=? AND password=?`;
connection.query(
query,
[emailaddress, password],
function (err, results, fields) {
if (err) {
res.send({
code: 500,
failed: "Error occurred",
});
return; // make sure your function execution stops here, as you already called send();
}
if (results.length > 0) {
req.session.regenerate(function (err) {
// if (err) next(err);
req.session.loggedin = true;
req.session.emailaddress = req.body.emailaddress;
req.session.save(function (err) {
// if (err) return next(err);
res.redirect("/home");
});
});
} else {
res.send("Incorrect email address and/or password!");
return; // same thing, called send() make sure to end the function
}
// res.end(); you probably don't need this
}
);
} else {
res.send("Please enter username and/or password");
// res.end(); you probably don't need this
return;
}

Async handling issue in nodejs

I am new in nodejs. I am creating a basic API to get record by id. Everything is working fine. It is returning user data from database. But when i use password variable from response in same function it give me empty value whereas i am getting value in response. I think this is async issue but i dont know how to fix it.
This is API code
var express = require('express');
var db = require('../db/database');
var bcrypt = require('bcrypt');
const router = express.Router();
router.get("/:userId", (req, res, next) => {
let uid = req.params.userId;
db.query(`SELECT * FROM users WHERE u_id = ${uid}`, (err, data)=> {
if(!err) {
if(data && data.length > 0) {
var message = '';
if(data.u_password){
//var pass = data.u_password;
if(bcrypt.compare('123456', data.u_password)) {
// Passwords match
message = 'Passwords match';
} else {
// Passwords don't match
message = 'Passwords dont match';
}
}
res.status(200).json({
message:message,
});
} else {
res.status(200).json({
message:"User Not found."
});
}
}
});
});
database.js
var mysql = require('mysql');
const pool = mysql.createPool({
connectionLimit : 10,
host: 'localhost',
user: 'root',
password: '',
database: 'lost_and_found',
debug : false
});
function executeQuery(sql, callback) {
pool.getConnection((err,connection) => {
if(err) {
return callback(err, null);
} else {
if(connection) {
connection.query(sql, function (error, results, fields) {
connection.release();
if (error) {
return callback(error, null);
}
return callback(null, results);
});
}
}
});
}
function query(sql, callback) {
executeQuery(sql,function(err, data) {
if(err) {
return callback(err);
}
callback(null, data);
});
}
module.exports = {
query: query
}
Response
{"message":""}
Please change the bcrypt.compare code to following code. It is a callback function:
bcrypt.compare('123456', data.u_password, function(err, result) {
if (err) {
// Passwords don't match
message = 'Passwords dont match';
} else {
// Passwords match
message = 'Passwords match';
}
res.status(200).json({
message:message,
});
})
EDIT 1: Please update the method to following logic:
db.query(`SELECT * FROM users WHERE u_id = ${uid}`, (err, data) => {
if (err) {
throw err;
}
if (data && data.length > 0) {
var message = '';
if (data.u_password) {
bcrypt.compare('123456', data.u_password, function (err, result) {
if (err) {
// Passwords don't match
message = 'Passwords dont match';
} else {
// Passwords match
message = 'Passwords match';
}
res.status(200).json({
message: message,
});
})
}
res.status(200).json({
message: "User Not found."
});
}
res.status(200).json({
message: "User Not found."
});
});

Why I'm getting two responses from find query?

I'm trying to check if user exists in MongoDb.
For unknown reason after I found that the user exsists and send response , it's logging me that the user does not exsists
app.post("/login", function(req, res) {
var userName = req.body.userName;
var pass = req.body.pass;
console.log('')
console.log('Try to login:')
console.log('userName: ' + userName);
console.log('pass: ' + pass);
if(req.body.userName && req.body.pass)
{
db.collection("customers").find({first_name:userName}, function(err, docs) {
docs.each(function(err, doc)
{
if(doc) {
//console.log(doc);
console.log('User Exsists')
res.send('YES');
}
else {
console.log('User Does Not Exsists')
res.end();
}
})});
}
else
{
console.log('NO')
res.send('NO')
}
});
Output: (first users not exists and the second does exists)
Try to login:
userName: sdlkj
pass: lkj
User Does Not Exsists
Try to login:
userName: sivan
pass: lkj
User Exsists
User Does Not Exsists
Why after I found that the user exists I'm getting another log line which it does not found ?
This is happening because you're iterating over the result cursor using each, which calls its callback one final time with a parameter value of null to signal that the cursor is exhausted.
Instead, you probably want to be using findOne here:
db.collection("customers").findOne({first_name: userName}, function(err, doc) {
if(doc) {
console.log('User Exsists')
res.send('YES');
}
else {
console.log('User Does Not Exsists')
res.end();
}
});

How to return a value from a mysql SELECT query in node.js

I'm still very new to Node.js, and i'm trying to understand how callbacks work.
So, here is my problem :
I should've put more code :
POST :
app.post('/register', function(req, res) {
//get data from the request
var data = {
username: req.body.username,
email: req.body.email,
password: req.body.password
};
function fetchID(callback) {
connection.query('SELECT id_user FROM USERS WHERE username = ?', data.username, function(err, rows) {
if (err) {
callback(err, null);
} else
callback(null, rows[0].id_user);
});
}
var user_id;
fetchID(function(err, content) {
if (err) {
console.log(err);
return next("Mysql error, check your query");
} else {
user_id = content;
console.log(user_id); //undefined
}
});
console.log(user_id); //undefined
var payload = {
iss: req.hostname,
sub: user_id
}
console.log(payload.sub); //correct id
})
GET :
app.get('/todos', function(req, res) {
if (!req.headers.authorization) {
return res.status(401).send({
message: 'You are not authorized !'
});
}
var token = req.headers.authorization.split(' ')[1];
var payload = jwt.decode(token, "shhh..");
//additional level of security
console.log('sub id is : ' + payload.sub); //undefined
if (!payload.sub) {
return res.status(401).send({
message: 'Authentication failed !'
});
}
})
I commented each console.log to be more clear. I need to get the correct id when i check for if (!payload.sub) in app.get()
Your two functions should be something like -
function fetchID(data, callback) {
connection.query('SELECT id_user FROM USERS WHERE username = ?', data.username, function(err, rows) {
if (err) {
callback(err, null);
} else
callback(null, rows[0].id_user);
});
}
and then
var user_id;
fetchID(data, function(err, content) {
if (err) {
console.log(err);
// Do something with your error...
} else {
user_id = content;
}
});
Here in the callback function, the returned variable content will hold the value for user_id.
EDIT
I have not solved the exact problem as you had described above.
But in following example, I have shown that, the callback mechanism is working -
First (Table creation and insert some dummy data)-
use test;
create table users (id int(11) primary key,username varchar(100));
insert into users values(1, "John");
insert into users values(2, "Sham");
Now I have made your post method as get and tested in browser.
Following is the full class tested in my localhost -
var application_root = __dirname,
express = require("express"),
mysql = require('mysql');
var app = express();
var connection = mysql.createConnection({
host : 'localhost',
user : 'root',
password : 'admin',
database: "test"
});
app.get('/getuser', function(req, res) {
//get data from the request
var data = {
username: req.query.username
};
function fetchID(data, callback) {
connection.query('SELECT id FROM users WHERE username = ?',
data.username, function(err, rows) {
if (err) {
callback(err, null);
} else
callback(null, rows[0].id);
});
}
var user_id;
fetchID(data, function(err, content) {
if (err) {
console.log(err);
res.send(err);
// Do something with your error...
} else {
user_id = content;
console.log(user_id);
res.send("user id is -" + user_id);
}
});
})
app.listen(1212);
Now these requests will produce this output -
http://127.0.0.1:1212/getuser?username=john => user id is -1 and
http://127.0.0.1:1212/getuser?username=sham => user id is -2
Hope this code example will help you to understand the callback in node.js.
Thanks

mongo not showing users even though I "know" they exist

I am trying to implement a authentication system for my website using MEAN however I have run into a relatively strange problem. I am able to register users and duplicate usernames can be identified. However, I cannot get logging into the website working. When I search the mongo database using the command line, I do not get anything. This is what my mongo output looks like.
>> show users
>>
The database has the username somewhere... so how do I get the users to be properly displayed? Why is that user is undefined when I try to log in even though I know the username is in the database?
var crypto = require('crypto');
var mongoose = require('mongoose');
var User = mongoose.model('User');
function hashPW(pwd) {
return crypto.createHash('sha256').update(pwd).digest('base64').toString();
};
module.exports.signup = function (req,res) {
var user = new User({username:req.body.usernmae});
console.log('made it here');
user.set('hashed_password', hashPW(req.body.password));
user.set('email', req.body.email);
user.save(function (err) {
if (err) {
try {
if (err.code==11000) res.render('signup', {message: 'Sorry, someone has that username already.'})
} catch(e) {
}
console.log(err);
//res.redirect('/signup');
} else {
req.session.user = user.id;
req.session.username = user.username;
req.session.msg = 'Authenticated as ' + user.username;
res.redirect('/');
}
});
};
module.exports.login = function (req,res) {
User.findOne({ username: req.body.username })
.exec(function(err,user) {
console.log(user);
console.log(err);
console.log(hashPW(req.body.password.toString()));
if (!user) {
err = 'User Not Found.';
} else if ( user.password === hashPW( req.body.password.toString() ) ) {
req.session.regenerate(function() {
req.session.user = user.id;
req.session.username = user.username;
req.session.msg = 'Authenticated as ' + user.username;
res.redirect('/');
});
} else {
err = 'Authentication failed.';
}
if (err) {
console.log(err);
req.session.regenerate(function() {
req.session.msg = err;
res.redirect('/login');
});
}
});
};
I notice that there's a typo in the provided code.
var user = new User({username:req.body.usernmae});
Should likely read
var user = new User({username:req.body.username});
This probably meant the name failed to set thus putting a junk user into your DB.
Also, regarding your command in the Mongo Shell, Neil's answer covered that the show command is not actually useful here. The reference for db.collection.find() is here.
silly mistake. the field is not password but hashed_password.
{ email: 'somerandomemail#gmail.com',
hashed_password: 'A8ctR3JAA84DWTmYXEAhxEEP1bTtAidaoyWArKHtk2g=',
username: 'Szpok',
_id: 54c09c458c4eccc90b9c4bb5,
__v: 0 }

Resources