Why am I getting [object object ] instead of JSON? - javascript

I'm making an API. When I send correct data for login, I get JSON but when I send incorrect data, I get this [object object] message, why?
When the correct information is provided.
Here is my code.
router.route('/login').post(function (req, res, next) {
console.log('i should be here when path match to login', req.body);
UserModel.findOne({
username: req.body.username,
})
.exec(function (err, user) {
if (err) {
return next(err);
}
if (user) {
var passwordMatch = passwordHash.verify(req.body.password, user.password);
if (passwordMatch) {
var token = generateToken(user);
res.status(200).json({
user: user,
token: token
});
} else {
next({
message: "password didnot match",
status: 400
})
}
} else {
next({
message: 'Invalid Username',
status: 400
})
}
});
});

The value [Object object] has nothing to do with the data you sent. This has to do with the way you print the value.
[Object object] means you have received an object. The value of type usually returned when you either concatinate the object with string.
Example:
var obj = {a: 1};
console.log('Printing ' + obj); // Prints [object object]
So, instead of concatinating the object, you can stringify the object and print it.
Example
var obj = {a: 1};
console.log('Printing ' + JSON.stringify(obj)); // Prints {"a":1}
Or
var obj = {a: 1};
console.log('Printing ', obj); // Prints formatted {"a":1}

res.status(200).json({
user: user,
token: token
});
This is how you are sending on success. You are formatting response as JSON.
But on failure, you are returning plain JS Object. Formatting failure responses as JSON object will solve your problem.

You can do this without using next. Try this code, It will work straight away!
router.route('/login').post(function (req, res, next) {
console.log('i should be here when path match to login', req.body);
UserModel.findOne({
username: req.body.username,
})
.exec(function (err, user) {
if (err) {
console.log(err);
res.status(500).json({message:'Backend error'})
}
if (user) {
var passwordMatch = passwordHash.verify(req.body.password, user.password);
if (passwordMatch) {
var token = generateToken(user);
res.status(200).json({
user: user,
token: token,
message:'Login successful'
});
} else {
res.status(400).json({message:'Wrong password'})
}
} else {
res.status(400).json({message:'User does not exist'})
}
});
});

Related

Value comes back undefined despite being present in the object

I am having trouble getting access to a value in an object in my Express app after being successfully retrieved from a Mongo DB collection.
Here is the code.
app.post("/api/validate", async (req,res) => {
console.log('validating with id -> ', req.body.uid._id)
try {
User.findById(mongoose.Types.ObjectId(req.body.uid._id)).then(response => {
console.log('The response object -> ', response) // logs the object
console.log('Type ->', typeof(response)) // logs 'object'
console.log('Value -> ', response.isAdmin) // logs undefined
if(response.isAdmin === true) { // never triggered
res.json({ authorized: true, result: response, message: 'User Authorized' })
} else {
res.json({ authorized: false, message:'User not authorized' })
}
})
} catch (error) {
res.json({ message: 'User not found.', err: error })
}
})
Here is a simplified log of the response.
{
userName: 'Tom Smith',
userId: '0',
comment: 'New Admin test',
isAdmin: true,
}
The problem is the isAdmin value is always undefined so the if condition never gets triggered. If anyone can help me figure out what is going wrong here I'd much appreciate it.
Try with a callback instead of resolving the Promise with then:
app.post('/api/validate', async (req, res) => {
console.log('validating with id -> ', req.body.uid._id);
User.findById(
req.body.uid._id,
(err, user) => {
if (err) return res.json(err);
if (!user) return res.json({ message: 'User not found.' });
console.log('The response object -> ', user); // logs the object
console.log('Type ->', typeof user); // logs 'object'
console.log('Value -> ', user.isAdmin); // logs undefined
if (user.isAdmin === true) {
// never triggered
res.json({
authorized: true,
result: user,
message: 'User Authorized',
});
} else {
res.json({ authorized: false, message: 'User not authorized' });
}
}
);
});

bcrypt compareSync returns false even they have same string

I am trying to make login functionality
While I was creating the login function like this
login: (req,res) => {
const body = req.body;
getUserByEmail(body.email,(err,results)=>{
if(err){
console.log(err);
}
if(!results){
return res.json({
sucess: 0,
data: "Invalid email or password 1"
});
}
console.log(body.pw);
console.log(results.pw);
const result = compareSync(body.pw,results.pw);
console.log(result)
if(result){
results.pw = undefined;
const jsontoken = sign({result: results},"1234413",{
expiresIn: "1h"
});
return res.json({
sucess: 1,
message: "login sucessfully",
token: jsontoken
});
}else{
return res.json({
sucess: 0,
data: "Invalid email or password2"
});
}
});
}
Terminal Answer
I console log the body.pw and results.pw but seems like it give me same strings but
I was not sure why it gives me false result even if I have same string for body.pw and results.pw
compareSync compares a password with a hash. You first need to hash the password before comparing it with the plain-text password.
First run
bcrypt.hash(myPlaintextPassword, saltRounds).then(function(hash) {
// Store hash in your password DB.
});
Then you can compare
bcrypt.compare(myPlaintextPassword, hash).then(function(result) {
// result == true
});

NodeJS user authentication with JWT

I am just started with nodejs with react frontend. But I have some issue while authenticating user. I am trying to fetch user with specific email and password. My api for this is as follows:
I have created three files controller, services and router files for any api request.
//userServices.js
const db = require('./../../db-connection/connection')
userAuth: (params, callback) => {
db.query(`SELECT * FROM Users WHERE email = ?`,[params.email],
(error, result, fields) => {
if(!error) {
console.log('result = ' + result[0]);
return callback(error, result[0])
}
else
return callback(error)
});
}
And this is my userController js file.
//userController.js
const {create, userindex, userAuth} = require('./UserServices');
const {genSaltSync, hashSync, compareSync} = require('bcrypt');
const {sign} = require('jsonwebtoken');
userLoginAuth: (req, res) => {
const body = req.body;
userAuth(body, (error, results) => {
if (error)
console.log(error);
if (!results) {
return res.json({
success: 0,
data: 'Invalid email or password'
})
}
const result = compareSync(body.password, results.password);
if(!result) {
results.password = undefined;
const jsontoken = sign({result: results}, 'choegyel123', {
expiresIn: '1h'
});
return res.json({
success: 1,
message: 'Login successful',
token: jsontoken
})
} else
console.log('password' + result.password)
return res.json({
success: 0,
error: 'Invalid email or password'
});
});
}
But the problem is in userServices.js file. My sql query is correctly executed but in callback for the ' results ' i am getting weird object. I think I should get some array of corresponding data from the database table and in my console log I am getting [object object]. I am not sure what does this actually mean and I am also all sure this is a blocker, since I cannot retrive password with this object in my userController. Any help would be greatly appreciated. Thanks!
Issues
compareSync returns a boolean with true indicating correct password. You're using if(!result) which is the reverse.
Make sure your {} are correct on the else
You're logging result.password which is undefined because result is your compareSync return value. You meant to log results.password. Avoid using result and results for two different things because it makes it easy to make these mistakes. Something like bcryptResult and resultObj might be better.
When you console.log(), pass data as the second argument or make a second log because concatenating objects always shows [object Object].
Updated snippet
const result = compareSync(body.password, results.password);
if(result) {
results.password = undefined;
const jsontoken = sign({result: results}, 'choegyel123', {
expiresIn: '1h'
});
return res.json({
success: 1,
message: 'Login successful',
token: jsontoken
})
} else {
console.log('password', results.password)
return res.json({
success: 0,
error: 'Invalid email or password'
});
}

Promise returns undefined json in Express post request

I have a promise within a selectRecipientData function that returns some user data from an api.
export async function selectRecipientData({ email }) {
engage.selectRecipientData({
listId: listId,
email: email,
returnContactLists: false,
}, function(err, result) {
if(err) {
console.log(err);
} else {
let recipient = JSON.stringify(result);
// this logs successfully
console.log('Recipient details: ' + recipient );
return recipient;
}
});
}
When I call this function within a post request. The data is logged within the promise but is undefined when returned as per below:
server.post('/api/v1/public/selectrecipientdata', async (req, res) => {
formData = req.body;
let { email } = formData;
if (!email) {
res.json({ error: 'Email is required' });
return;
}
try {
let recipientData = await selectRecipientData({ email });
// why is this undefined?
console.log('This is Undefined: '+ JSON.stringify(recipientData) );
res.json({recipientData});
} catch (err) {
res.json({ error: err.message || err.toString() });
}
});
Anyone tell me why? Thanks
You've written selectRecipientData as a callback style function, but you're calling it as an async/await style. If engage.selectRecipientData returns a promise, you could do something like:
export async function selectRecipientData({email}) {
const result=await engage.selectRecipientData({
listId: listId,
email: email,
returnContactLists: false,
});
const recipient=JSON.stringify(result);
console.log('Recipient details: ' + recipient );
return recipient;
}
Otherwise, to convert it to a promise you could do something like:
export function selectRecipientData({email}) {
return new Promise((resolve,reject)=>{
engage.selectRecipientData({
listId: listId,
email: email,
returnContactLists: false,
}, function(err, result) {
if (err) {
reject(err);
}
else {
let recipient = JSON.stringify(result);
console.log('Recipient details: ' + recipient);
resolve(recipient);
}
});
});
}

Calling async function in node.js

I have an async function
async function getPostAsync() {
const post = await Post.findById('id');
// if promise was successful,
// but post with specific id doesn't exist
if (!post) {
throw new Error('Post was not found');
}
return post;
}
I am calling the function with
app.get('/', (req, res) => {
getPostAsync().then(post => {
res.json({
status: 'success',
});
}).catch(err => {
res.status(400).json({
status: 'error',
err
});
})
});
but I just receive
{
"status": "error",
"err": {}
}
I would expect to either get the error Post was not found or some error with the connection or something like that, but the variable err is simply an empty object in my catch statement.
Consider the following:
let e = Error('foobar');
console.log( JSON.stringify(e) )
This outputs {}, much like in your case. That's because errors don't serialize to JSON very well.
Instead, try this:
res.status(400).json({
status : 'error',
err : err.message // `String(err)` would also work
});

Categories

Resources