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."
});
});
Related
I'm using koa to reset a password, wanting to use .save in order to fire the schema.pre('save' ).
data was returning with findOneAndUpdate, but not when I use .save.
what's the magic combination to make this return the .save doc properly with the await/asyncs?
r.post("/public/auth/resetpass", async (ctx, next) => {
const values = ctx.request.body;
const query = {
email: values.email,
resetPasswordToken: values.resetPasswordToken,
resetPasswordExpires: {
$gt: new Date(new Date())
}
};
const update = {
password: values.password,
resetPasswordToken: null,
resetPasswordExpires: null
};
// let userFound = null;
await User.findOne(query,async function(err, user) {
if (err) {
console.log("*** err");
next(err);
} else {
if (_.isEmpty(user)) {
ctx.status = 200;
ctx.body = {
error: true,
message: "token is incorrect or time has expired for password reset"
};
} else {
user.password = values.password;
await user.save(function(err, doc) {
if (err) {
console.log('***err saving');
next(err);
} else {
//console.log fires, but ctx body doesn't return
console.log ('***saved, writing poco');
ctx.body = userToPoco(doc);
}
});
}
}
});
});
ultimately switched to a promise.
await user.save().then (doc =>{
ctx.body = doc;
});
I have declare the variable first. but if I do console.log(userinsertData) outside looping variable still not fill.
what i should do for solving this problem?
here my code:
var User = require('../models/user');
module.exports = {
myaction: function(req, res, next) {
var data = req.body,
userinsertData = [];
try {
data.forEach(function(item, index) {
var userdata = new User();
userdata.name = item.name;
userdata.age = item.age;
userdata.sex = item.sex;
userdata.save(function(err, data) {
if (err) {
res.send(err)
} else {
userinsertData.push(data);
}
});
})
} catch (e) {
res.json({
message: 'data not valid'
})
}
console.log(userinsertData);
res.json({
message: 'musician created!',
data: userinsertData
});
}
};
you should solve the problem as
async.eachSeries(data, function (info, callback) {
//here process your data and call callback() for next iteration
}, function (err) {
if (err) {
//this will be called after all iterations and in case of error
}else{
console.log('Well done :-!');
//this will be called after all interations successfully
}
});
this problem you are facing is because of asynchronous nature of nodejs and async helps you to introduce blocking.
Don't forget to include async
Use promise
var User = require('../models/user');
module.exports = {
myaction: function(req, res, next) {
var data = req.body,
userinsertData = [];
new Promise(function(resolve, reject) {
data.forEach(function(item, index) {
var userData = new User(item);
userData.save(function(err, data) {
// if error, reject
if(err) return reject(err);
// we have proceed all items in data, resolve it
else if(data.length - 1 === index) return resolve(userinsertData);
// not finished yet, keep proceeding
else userinsertData.push(data);
});
}).then(function(successResult) {
res.json({
message: 'musician created!',
data: successResult
});
}, function(errorResult) {
res.json({
message: 'data not valid'
});
});
}
};
Use callbacks
var User = require('../models/user');
module.exports = {
myaction: function(req, res, next) {
var data = req.body,
userinsertData = [];
function saveUser(callback) {
data.forEach(function(item, index) {
var userData = new User(item);
userData.save(function(err, data) {
// if error, return callback with error
if(err) return callback(err);
// we have proceed all items in data, return data
else if(data.length - 1 === index) callback(null, userinsertData);
// not finished yet, keep proceeding
else userinsertData.push(data);
});
}
saveUser(function(err, users) {
if(err) return res.json({message: 'data not valid'});
res.json({
message: 'musician created!',
data: users
});
});
}
};
This is what async package does internally
I am trying to login from my signin.ejs file,after click on the login button in
my signin page it shows "Cannot read property collection undefined" what is the
problem.
I defined my route like this in app.js:
app.post('/login', routes.dologin);
I defined my dologin route in index.js:
exports.dologin = function (req, res) {
res.locals.session = req.session;
var user = req.body.user;
db.authenticateUser(user.email, user.password, function ( err, response) {
if (err) {
.......
.......
} else {
.......
........
}
});
};
In my db.js:
var mongo = require('mongoskin'),
crypto = require('crypto');
module.exports = function (config) {
var USERS_COLLECTION = 'users',
ORDERS_COLLECTION = 'orders',
salt = 'supersecretkey',
db;
authenticateUser: function (emailId, password, callback) {
db.collection(USERS_COLLECTION).count({email : emailId, password: encryptPassword(password)}, function (err, count) {
if (err) {
console.log("error authenticating user: " + err);
callback(new Error(err));
} else if (count === 0) {
callback(new Error("emailid/password did not match"));
} else {
callback(null);
}
});
},
}
What is the problem here for getting "Collection undefined"? i think here
everything is right... Is there any problem here?tell me..please Thanks.
You should add this code db = mongo.db('localhost:27017/yourdb');
var mongo = require('mongoskin'),
crypto = require('crypto');
module.exports = function (config) {
var USERS_COLLECTION = 'users',
ORDERS_COLLECTION = 'orders',
salt = 'supersecretkey',
db = mongo.db('localhost:27017/yourdb');
authenticateUser: function (emailId, password, callback) {
db.collection(USERS_COLLECTION).count({
email: emailId,
password: encryptPassword(password)
}, function (err, count) {
if (err) {
console.log("error authenticating user: " + err);
callback(new Error(err));
} else if (count === 0) {
callback(new Error("emailid/password did not match"));
} else {
callback(null);
}
});
},
}
I am trying to update the value of my model and it does not work.
The weird thing is that I am printing out the result and it looks different than what I see in my database by using Robomongo.
Any thoughts why this happens?
Here is my code:
exports.create = function(req, res) {
var productId = req.query.product;
if (productId) {
Request.createWizard(req.user, { productId: productId }, function(err, request) {
Product.findById(productId, function(err, product) {
if (err) {
return console.log('oh no! error', err);
} else {
if (product.price =! 0 )
request.status = 'ready';
console.log(request);
(Here I see in the terminal: status = ready)
}
});
req.flash('success', { msg: 'Your request has been successfully created.' });
res.redirect('/discover');
});
} else {
var pages = require('../../schemas/wizard/request')();
res.render('requests/form', {
title: 'Make a Request',
pages: pages,
saveState: false
});
}
};
When I am checking the database status is still on pending.
You're changing the status property, but you're not saving the document back to the database after doing so:
Request.createWizard(req.user, { productId: productId }, function(err, request) {
Product.findById(productId, function(err, product) {
if (err) {
return console.log('oh no! error', err);
} else {
if (product.price !== 0) {
request.status = 'ready';
request.save(function(err) { // <-- save it back to the database
if (err) {
console.log('oh no! error', err);
} else {
console.log(request);
}
});
}
}
});
req.flash('success', { msg: 'Your request has been successfully created.' });
res.redirect('/discover');
});
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