Nesting queries for nodejs postgres - node.js

I am currently making a webapp with a database using express and postgres and am having trouble implementing registration.
This is a small snippet of what happens after the user keys in username, name and password into a form which is then posted to the '/registerUser' route. Here is the post request at the '/registerUser' route. The pool.query works for the check_username, however, is does not work for the add_user query.
Here are the 2 queries:
check_username = 'SELECT 1 FROM Users where username = $1'
add_user = 'INSERT INTO users VALUES (username, name, password) VALUES ($1, $2, $3)'
router.post('/', function(req, res, next) {
var name = req.body.name;
var username = req.body.username;
var password = req.body.password;
pool.query(sql_query.query.check_username, [username], (err, data) =>{
if(data.rows[0] != undefined) {
console.log(`re register again!`);
res.redirect('/registerUser');
} else {
console.log("adding to database")
// Generate salt
bcrypt.genSalt(10, (err, salt) =>{
if(err) {
console.log(err);
}
// hash it with salt
bcrypt.hash(password, salt, (err,hash)=>{
if(err) console.log(err)
//password = hash
console.log(`${username} + ${password}`);
// save to database
pool.query(sql_query.query.add_user, [name, username, password], (err, data) => {
console.log("pass")
res.redirect("/")
});
});
});
}
});
});
What exactly is the problem here? Could it be that i cannot nest pool.queries?

the answer is that there is a syntax error with the insert queries. There shouldnt be a VALUES in front of the table columns.

Related

Node.js bcrypt compare returning false

I am working on a login script with Node.js and using bcrpyt to compare password hashes. When using the bcrpyt library, the compare function fails. However when I use the bcrpytjs library, the compare function succeeds. Below is the login function. I've included the hash and password for use is testing.
Password: LHLiiSGd1xLg
Hash: $2y$10$J47x5GEFtmULWem2nh3YvuZaAiZyFZlyTUFV97dAx2.dyb8Yst43y
function login(email, password, callback) {
// Require depedencies
const bcrypt = require("bcrypt")
const mysql = require('mysql');
// Create our mysql connection
const connection = mysql.createConnection({
host: configuration.host,
user: configuration.user,
password: configuration.password,
database: configuration.database
});
// Connect to the database
connection.connect();
// Create the database query
const query = 'SELECT id, firstname, lastname, email, password FROM tblclients WHERE email = ?';
// Query the database
connection.query(query, [ email ], function(err, results) {
// If we have an error
if (err) return callback(err);
// If we have no results
if (results.length === 0) return callback(new WrongUsernameOrPasswordError(email));
// Define the user object
const user = results[0];
console.log('Query: ', results);
// Compare the two hashes
bcrypt.compare(password, user.password.toString(), function(err, isMatch) {
// If the passwords do not match
if (err) return callback(err);
if (!isMatch) return callback('Passwords do not match');
// Return the user
callback(null, {
user_id: user.id.toString(),
nickname: user.firstname + ' ' + user.lastname,
email: user.email
});
});
});
}
I replaced the 2y prefix with 2a and the function now correctly works.
user.password.toString().replace(/^\$2y/, "$2a")

Unable to compare password stored in MySQL database with password entered from front end using bcrypt

I'm entering a password from front end inside MySQL for registered user. Now when im signing in I wish to compare the entered password with original stored password in database using bcrypt-nodejs. But unable to do so. Im a beginner at Node.js, please help !!
this code is in my server.js file which is the main node server file.
app.post('/signin', (req,res)=>{
const {email} = req.body;
let post= {email: email};
let sql= 'SELECT password FROM users WHERE email= ?';
let query= db.query(sql, post,(error,result)=>{
if(error)
{
throw error;
}
else if(!error)
{
bcrypt.hash(result, null,null, function(err,res){
});
bcrypt.compare(req.body.password, hash, (err,res)=>{
if(err)
{
throw error;
}
else if(res)
{
res.send('signin successful');
}
}
else {
res.status(400).json('error logging in');
}
//res.json('signin');
});
})
})
as you can see, Im trying to hash the result which is the password from the database and compare it with req.body.password which user enters from front end, but Im getting error in my console
Let's rewrite a little with async/await to make it more readable
app.post('/signin', async (req, res) => {
const { email } = req.body;
let post = { email: email };
let sql = 'SELECT password FROM users WHERE email= ?';
const queryResult = await new Promise(resolve => db.query(sql, post, (error, result) => resolve(result)));
// I assume you should access here your hash with something like this queryResult.password`
const hashStoredInDb = queryResult.password;
const compareResult = await new Promise(resolve => bcrypt.compare(req.body.password, hashStoredInDb, (err, res) => resolve(res)));
// Your other verification logic based on compare result.
})
So, the main logic is to compare hashed password already stored in db with provided from user.
Also, you could add some verifications in provided code, I've missed some try/catch for simplicity and readability.

How to compare salted/hashed passwords from database correctly?

I've seen this asked before but in other languages (C# and PHP) but I am working through Javascript. I am storing a username and password onto my database but the password is being hashed via bcrypt.
I can store it correctly but I cannot pull it from my database and compare it correctly. It always console logs my 'password does not match' message.
This is my registration code that stores the username and password onto my database.
app.post('/register', function (req, res) {
var usernameCollection = mongoDBDatabase.collection('accounts');
username = req.body.username;
bcrypt.hash(req.body.password, saltRounds, function (err, hash) {
usernameCollection.insertOne({
personId: req.body.username,
username: req.body.username,
password: hash
}).then(function(data) {
if (data) {
//res.redirect('/' + username);
//window.location.href = "/" + username;
}
});
});
});
And here is my code where I am searching my database for the username and trying to compare the password to no avail.
//login page: storing and comparing email and password,and redirecting to home page after login
app.post('/login', function (req, res) {
var usernameCollection = mongoDBDatabase.collection('accounts');
var username = req.body.username;
var enteredPassword = req.body.password;
usernameCollection.findOne({
$or:[
{ username: username}
]
}).then(function(user){
if (user) {
console.log('That username was found in the database');
bcrypt.compare(enteredPassword, user.password, function(err, result){
if(result == true){
console.log('Password matches!');
res.redirect('/' + username);
}
else{
console.log('Password did not match');
res.redirect('/');
}
});
}
else{
console.log('The username ' + username + ' was NOT found in the database');
}
});
});
I just want to compare the stored password to the entered password and confirm they are the same to log the user in.

Unable to use variable outside the function

I am using Koa module - Node js and mysql & stuck on a problem.
In signup function (inside welcomeCtrl.js) I have:
var bcrypt = require('bcrypt');
module.exports = {
signup: function* (next) {
bcrypt.genSalt(10, function(err, salt) {
console.log(salt);
bcrypt.hash(password, salt, function(err, hash) {
// Store hash in your password DB.
console.log(hash); //no error
var hashedPassword = hash;
});
});
console.log(bcrypt.hash.hash); //gives error
//or
console.log(bcrypt.hash.hahedPassword); //gives error
queryString = "insert into user(email,name, phone, password, course_id, dpt_id) values('%s','%s','%s','%s','%s','%s')";
query = util.format(queryString, email, name, phone, hash, courseId, dptId);
results = yield databaseUtils.executeQuery(query);
this.redirect('/');
}
}
I am calling signup post function in different routes.js file as:
router.post('/signup', welcomeCtrl.signup);
Here is the executeQuery function in the databaseUtils.js file
var executeQuery = function(query, callback) {
pool.getConnection(function(err, connection) {
// Use the connection
connection.query(query, function(err, rows, fields) {
connection.release();
if(err) {
err.mysqlQuery = query;
logger.logError(err);
}
if(typeof callback == "function") {
callback(err, rows);
}
// Don't use the connection here, it has been returned to the pool.
});
});
};
module.exports = {
executeQuery: thunkify(executeQuery),
executePlainQuery: executeQuery
};
Is there any way to use hash variable outside the function so that it can be inserted in query?
You should move your query function into the callback for bcrypt.hash.
bcrypt.genSalt(10, function(err, salt) {
console.log(salt);
bcrypt.hash(password, salt, function(err, hash) {
// Store hash in your password DB.
console.log(hash); //no error
queryString = "insert into user(email,name, phone, password, course_id, dpt_id) values('%s','%s','%s','%s','%s','%s')";
query = util.format(queryString, email, name, phone, hash, courseId, dptId);
databaseUtils.executeQuery(query, function() {
this.redirect('/');
});
});
});
Problem is, where does your redirect function come from? You're going to loose context on this unless you bind the functions. Do fat arrow functions work in your setup? If so you could do it that way.

Prevent updating user's password if the input was left empty?

I'm struggling to prevent updating user's password in database if the password input was left empty.
Here is the route responsible for updating user data:
router.put('/update', passport.authenticate('jwt', {session: false}), (req, res) => {
let user = req.user;
user.firstname = req.body.firstname;
user.lastname = req.body.lastname;
user.username = req.body.username;
user.email = req.body.email;
user.password = req.body.password || null;
User.updateUser(user, (err) => {
if (err) {
res.json({
success: false,
message: 'User details couldn\'t be updated.'
});
} else {
res.json({
success: true,
message: 'User updated'
});
}
});
});
And here is the User model method which generates a hash of a password and saves the new data in the database:
module.exports.updateUser = function (user, callback) {
if (user.password) {
bcrypt.genSalt(10, (err, salt) => {
bcrypt.hash(user.password, salt, (err, hash) => {
if (err) throw err;
user.password = hash;
});
});
}
user.save(callback);
};
I check if the password value was given but I don't know how to keep the old encrypted password in the database if there is no new value given for the password. If user doesn't fill the password input, it is being saved as null, as expected though...
I hope there is an approach to achieve this, I just can't figure out at the moment as I'm a beginner.
Thank you in advance!
I guess that you are using Mongoose to communicate with the Database.
Change this Line of your code :
user.password = req.body.password || null;
with this :
if(req.body.password != null) {
user.password = req.body.password
}else{
/* find each user with a last name matching 'user.userame', selecting
/*the `password` field and returning the result in 'usr'
*/
User.find({'username' : user.username}, 'password', function (err, usr) {
if (err) return handleError(err);
user.password = usr.password;
})
}
Based on #Neil Lunn's suggestion about checking the documentation, I came up with a solution. I changed the updateUser method to this:
module.exports.updateUser = function (user, callback) {
if (user.password) {
bcrypt.genSalt(10, (err, salt) => {
bcrypt.hash(user.password, salt, (err, hash) => {
if (err) throw err;
user.password = hash;
user.save(callback);
});
});
} else {
User.findById(user.id).update({
username: user.username,
email: user.email,
firstname: user.firstname,
lastname: user.lastname
}, callback);
}
};
If the password is present, then update everything as is, if no password provided, then update only the needed fields except the password.
Maybe this is not the best solution, but it works for now.
Thank you!

Resources