1st post. I'm a student studying js and came across this problem with a callback that I'm not sure how to structure properly.
var bcrypt = require('bcrypt-nodejs');
var users = db.collection("users");
this.addUser = function(username, password, email, callback) {
"use strict";
// Generate password hash
var salt = bcrypt.genSaltSync();
var password_hash = bcrypt.hashSync(password, salt);
// Create user document
var user = {'_id': username, 'password': password_hash};
// Add email if set
if (email != "") {
user['email'] = email;
}
// NOT SURE What to write here
callback(Error("addUser Not Yet Implemented!"), null);
}
First of all: do not use sync methods if possible, use callbacks instead.
var bcrypt = require('bcrypt-nodejs');
var users = db.collection("users");
this.addUser = function(username, password, email, callback) {
"use strict";
// Generate password hash
bcrypt.genSalt(function(err, salt) {
if (err) {
callback(err);
return;
}
bcrypt.hash(password, salt, function(err, password_hash) {
if (err) {
callback(err);
return;
}
// Create user document
var user = {
'_id': username,
'password': password_hash
};
// Add email if set
if (email != "") {
user['email'] = email;
}
// NOT SURE What to write here
callback(null);
});
});
}
and please ask precise questions.
If I understand propperly, you dont know how to handle a callback?
you simply pass the function that will be called after all work in your function is done as the parameter callback. when your done, you call the callback with the wanted parameters.
here it's the err object in case of an error or null if there is no error.
If you want to pass your created user to the callback, just replace
callback(null); with callback(null, user);
Related
I have to implement a functionality for the user who can after login change the password to new one.
For that I want to update the hash and salt value for new password set. How can I do that?
Since on registration I am saving the password first time in hash and salt form in mongoDB.
How can I update that now?
Here is the code I am trying to use for password change:
router.get('/api/changePassword', function(req,res,next){
req.checkBody('oldPass', 'Empty Password').notEmpty();
req.checkBody('newPass', 'Password do not match').equals(req.body.confirmPassword).notEmpty();
var user = new User();
user.setPassword(req.body.newPass);
user.save(function (err,data) {
if (err) {
res.render('register', {errorMessages: err});
} else {
console.log("password set successfully");
}
})
})
But here I doubt that it will get updated into the existing user's database since I am creating the object user again here and saving it. Will it create again a new user in Collections and update the hash and salt value for that? How to then update the existing user password hash and salt value?
Below is the hash and salt model User schema code:
userSchema.methods.setPassword = function(password) {
this.salt = crypto.randomBytes(16).toString('hex');
this.hash = crypto.pbkdf2Sync(password, this.salt, 1000, 64, 'sha1').toString('hex');
};
userSchema.methods.validPassword = function(password) {
var hash = crypto.pbkdf2Sync(password, this.salt, 1000, 64, 'sha1').toString('hex');
return this.hash === hash;
};
module.exports = mongoose.model('User', userSchema);
And this is the route code of registartion page, first time when user registers and put password:
router.route('/register')
.get(function(req, res, next) {
res.render('register', { title: 'Register a new account'});
})
.post(function(req, res, next) {
req.checkBody('name', 'Empty Name').notEmpty();
req.checkBody('email', 'Invalid Email').isEmail();
req.checkBody('location', 'Empty Location').notEmpty();
req.checkBody('password', 'Empty Password').notEmpty();
req.checkBody('password', 'Password do not match').equals(req.body.confirmPassword).notEmpty();
var errors = req.validationErrors();
if (errors) {
res.render('register', {
name: req.body.name,
email: req.body.email,
location:req.body.location,
errorMessages: errors
});
} else {
var user = new User();
user.name = req.body.name;
user.email = req.body.email;
user.location = req.body.location;
user.setPassword(req.body.password);
user.save(function (err,data) {
if (err) {
res.render('register', {errorMessages: err});
} else {
console.log("user saved successfully");
}
})
Sorry, my previous explanation was incorrect, so I am going to write this as an answer. You won't actually be able to access the User object in the method alone, so what you will have to do is something like the following:
create a function with User.find() that returns the user.
Then pass in this user as a parameter to the new method you created as I described in the comment above, and continue to .update() this user that was passed into the setPassword() method as a parameter.
So your methods for the schema should be:
createPassword()
validPassword()
setPassword()
and the part of your code where you actually have the function that uses these methods to set this data should look something like:
function findUser() {
return User;
}
function setPassword(password) {
User.setPassword(User, password, passwordValid /*This is a boolean*/)
}
I am new to node.js and i am trying to create the reset password module for my app. I got stuck on a problem where I wanted to access the result outside of a query.
router.post('/forgot',(req,res)=>{
const db = require('../db.js');
if (req.body.email !== undefined) {
var emailAddress = req.body.email;
// TODO: Using email, find user from your database.
db.query('SELECT * FROM users WHERE email = ?',[emailAddress],(err,results,fields)=>{
if(err){
console.log('Error in pulling the information of the user from the database');
}
var userid = results[0].id;
console.log(userid);
});
var payload = {
id: userid, // User ID from database
email: emailAddress
};
console.log(payload);
} else {
res.send('Email address is missing.');
}
});
I want to get the value of userid which i got from my database and pass it to my outside variable payload and store it in the
id: userid
I did my research on other similar question but was not clear on this topic so any help will be highly appreciated. Thankyou
You're using a callback function here to get the result of your query, what this means is after the query is run it will go ahead and go through the function in the parameter the (err, results, fields) => { ... }, so you could either build your payload inside that callback function, where you would already have the userid on results[0].id or call another function inside that callback with the userid as a parameter.
Something like this
router.post('/forgot', (req, res) => {
const db = require('../db.js');
if (req.body.email !== undefined) {
var emailAddress = req.body.email;
// TODO: Using email, find user from your database.
db.query('SELECT * FROM users WHERE email = ?', [emailAddress], (err, results, fields) => {
if (err) {
console.log('Error in pulling the information of the user from the database');
}
var userid = results[0].id;
console.log(userid);
buildPayload(userid, emailAddress)
});
} else {
res.send('Email address is missing.');
}
});
buildPayload(userId, emailAddress) {
var payload = {
id: userId, // User ID from database
email: emailAddress
};
console.log(payload);
// whatever else you need to do
}
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.
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 6 years ago.
I am new to Nodejs. I am trying to return data. after select query. Here i am writing two condition's. first is very simple in logic and it is working but let me know why second condition is not working.
First Condition:
var arr = {email:"john#gmail.com", password:"};
return arr;
databaseConnection.query("SELECT * FROM users where email = '"+email+"' and password = '"+password +"'", function (err, result) {
});
Second Condition
databaseConnection.query("SELECT * FROM users where email = '"+email+"' and password = '"+password +"'", function (err, result) {
var arr = {email:"john#gmail.com", password:"};
return arr;
});
from passport.js
var LocalStrategy = require('passport-local').Strategy;
var FacebookStrategy = require('passport-facebook').Strategy;
var TwitterStrategy = require('passport-twitter').Strategy;
var configAuth = require('./auth');
module.exports = function(passport,databaseConnection) {
var usermodule = require('../models/user')(databaseConnection);
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser(function(user, done) {
done(null, user);
});
passport.use('local-login', new LocalStrategy({
usernameField : 'username',
passwordField : 'password',
passReqToCallback : true // allows us to pass back the entire request to the callback
},
function(req, email, password, done) { // callback with email and password from our form
var user={};
var result = usermodule.login(email,password);
console.log('usercraeted');
user["email"]=email;
user["status"]=true;
user["name"]="John Snow";
user["avatar"]="";
user["loginStatus"]=true;
return done(null, user);
user["msg"]="invalide email";
console.log("out");
return done(null, false,user["msg"]);
};
);
};
In your first example, the code is executed up to this point:
var arr = {email:"john#gmail.com", password:"};
return arr;
// interpreter exits and `{email:"john#gmail.com", password:"}` is returned,
// `databaseConnection.query("` is never executed
In your second example, the code is executed up to this point:
databaseConnection.query("SELECT * FROM users where email = '"+email+"' and password = '"+password +"'", function (err, result) {
var arr = {email:"john#gmail.com", password:"};
return arr;
});
// interpreter exits, undefined is returned
The second condition doesn't work because node.js is asynchronous. And your return is on a callback that take some times to be executed.
You have to use callbacks.
function getUser() {
var email = "test#test.com";
var password = "test";
getDatas(email, password, function(err, result) {
// the result is good and not undefined if no errors :)
});
}
function getDatas(email, password, callback) {
databaseConnection.query("SELECT * FROM users where email = '"+email+"' and password = '"+password +"'", function (err, result) {
callback(err, result); // callback is executed with the result you
});
}
Hope I helped you
I'm using the following function to hash a user's password, following Express's example for authentication:
function hash(pwd, salt, fn) {
// Bytesize
var len = 128,
// Iterations. ~300ms
iterations = 12000;
if (3 == arguments.length) {
crypto.pbkdf2(pwd, salt, iterations, len, fn);
} else {
fn = salt;
crypto.randomBytes(len, function(err, salt){
if (err) return fn(err);
salt = salt.toString('base64');
crypto.pbkdf2(pwd, salt, iterations, len, function(err, hash){
if (err) return fn(err);
fn(null, salt, hash);
});
});
}
}
The salt, as you can see, is returned as a string encoded in base64. The hash, however, is returned as a SlowBuffer. This same function is also used to compare hashes when trying to log a user in.
My Mongoose schema for Users specifies that the hash should be of type String. This ends up storing the hash in a strange way, resulting in contents like this which wreaked havoc on my mongo host:
My question is, is there a better/smarter way to store this hash in my database? I've tried encoding it with .toString('hex'), and I've also tried changing the hash type in the User schema to buffer, but both these approaches made all comparisons false when trying to log users in. Comparisons are made in my authenticate function, seen below:
function authenticate(name, pass, fn) {
var findUser = function(username) {
var deferred = Q.defer(),
populateObj = [
// list of paths to populate objects normally goes here
];
User.findOne({ username: name }).populate(populateObj).exec(function (err, retrievedUser) {
if (err || !retrievedUser) {
console.log(err);
deferred.reject('Cannot find user.');
}
else {
deferred.resolve(retrievedUser);
}
});
return deferred.promise;
};
findUser(name).then(function(data) {
// apply the same algorithm to the POSTed password, applying
// the hash against the pass / salt, if there is a match we
// found the user
hash(pass, data.salt, function(err, hash){
if (err) return fn(err);
if (hash == data.hash) return fn(null, data);
return fn('Invalid password.');
});
}, function() {
return fn('Failed to retrieve user.');
});
}
Storing the hash as a hex string in the database works okay for me (storing them 'raw' in either a String or a Buffer property doesn't):
var crypto = require('crypto');
var mongoose = require('mongoose');
var client = mongoose.connect('mongodb://localhost/test');
var UserSchema = new mongoose.Schema({
salt : String,
hash : String
});
var User = mongoose.model('User', UserSchema);
hash('secret', function(err, salt, key) {
new User({ salt : salt, hash : key.toString('hex') }).save(function(err, doc) {
User.findById(doc._id, function(err, doc) {
hash('secret', doc.salt, function(err, key) {
console.log('eq', doc.hash === key.toString('hex'));
});
});
});
});
(by the way, both crypto.pbkdf2 and crypto.randomBytes have synchronous counterparts)