Mongoose Put method CastError - node.js

With the following put mongoose method, I get an error in postman if I do not fill all key/value pair!
app.put('/api/users/:user_id', function(req, res) {
users.update({
id_userLogin : req.body.id_userLogin,
userName : req.body.userName,
email : req.body.email,
password : req.body.password,
userNotes: req.body.userNotes
}, function(err, user) {
if (err)
res.send(err);
users.find(function(err, users) {
if (err)
res.send(err)
res.json(users);
});
});
});
It works fine if I put all key/value pair but if it miss one pair, I get
"message": "Cast to string failed for value \"undefined\"",
"name": "CastError",
"type": "string"
if I add || "" for each params we can update the user with all empty params. In fact if a params is not updated we should keep the initial value
Any help would be appreciated

You should check all request parameters for plausibility and discard the request if it is malformed. For non-mandatory params (e.g., userNotes), you can set the param to an empty string if it is undefined:
app.put('/api/users/:user_id', function(req, res) {
if (!req.id_userLogin || userName || password) {
return res.send('Malformed request', 400);
}
users.update({
id_userLogin : req.body.id_userLogin,
userName : req.body.userName,
email : req.body.email,
password : req.body.password,
userNotes: req.body.userNotes || ""
}, function(err, user) {
if (err)
res.send(err);
users.find(function(err, users) {
if (err)
res.send(err)
res.json(users);
});
});
});

I move the code to for controller
exports.update = function(req, res, next) {
var id = req.params.id
User.findByIdAndUpdate(id, req.body, function(err, user) {
if (err) {
return next(err);
} else {
res.json(user);
}
});
}
and for the route
app.route('/api/users/:id').put(users.update);
which fix the issue. With this method you can update one of the params

Related

passport js, auth fail with http 500. no response

I'm developing full-stack,
with
Node,
Express,
Session-mysql,
passport...
like a title, my router.post has no res.
router.post('/', function(req, res) {
hasher({password: req.body.password, function(err, pass, salt, hash){
var account = {
authId: 'local:'+req.body.username,
username: req.body.username,
password: hash,
salt: salt,
displayName: req.body.displayName
};
var sql = 'INSERT INTO accounts SET ?';
conn.query(sql, account, function(err, results) {
if(err) {
console.log("signup_post_in_error");
res.status(500);
} else {
req.login(account, function(err) {
console.log(err);
req.session.save(function() {
res.redirect('/board');
})
})
}
});
}})
})
form(action='/signup' method='post')
when I click submit, there is no response.

mongoose findOne work using id instead of _id

I was stuck for a while when I do _id in findOne function I got empty result.
exports.getUser = function(req, res) {
User.findOne({id: req.params.id}, function(err, user) {
if (err) {
return res.status(400).send({
msg: err
})
} else {
return res.json({status:1, data: user})
}
})
}
Above code worked but I'm curious why this won't work
...
User.findOne({_id: req.params.id}, function(err, user) {
...
I think I have to parse req.params.id with ObjectId function, but is there any global method that ignore this rule? for me it make sense just use _id: myId

PassportJS: Edit user info

I'm using PassportJS. I'm trying to let users edit their email address if needed. This is the code I have which is currently not working.
Any advice? Thank you!
app.post("/editprofile", middleware.isLoggedIn, function(req, res, next){
User.update({ id: req.session.passport.user }, {
email: req.body.email,
}, function(err, user) {
if (err) return next(err);
User.findById(req.user._id, function(err, user) {
if (err) return next(err);
console.log(err)
return res.render('landing.ejs', {
user:user
});
});
});
});
Consider using this and every thing will be fine
app.post("/editprofile", middleware.isLoggedIn, function(req, res, next){
User
.findOneAndUpdate({ _id: request.session.passport.user }, req.body.email)
.exec(function(err, user) {
if (err) return res.render(/* Your error template here */, {
err: err.message
};
return res.render('landing.ejs', {
user: user
});
});
}
}
Hope this helps!

Send variables to layout

I'm learning how to build web applications using Node.js and express, so I'm really noob yet.
So, I have some questions here. I'm building a landing page, and all the informations that I'm getting from my Database (in mysql) will appear in a single page.
I'm sending values from my database, to my layout, built in Jade.
And I created multiple functions to get specific data, here an example:
function getUser(username, userId, callback) {
connection.query('SELECT * FROM users WHERE user_id = ?', userId, function(err, result) {
if (err)
callback(err, null);
else
var callBackString = {};
callBackString.value1 = result[0].user_email;
callBackString.value2 = result[0].user_name;
callback(null, callBackString);
});
}
When the user tries to login I check if the user exists to change the layout and send to the layout some important values:
router.post('/login', function(req, res) {
connection.query('SELECT user_id FROM users WHERE user_email = ? AND user_password = ?', [req.body.login, req.body.password], function(err, results) {
if (err) throw err;
if (results[0]) {
userId = results[0].user_id;
getUser("username", userId, function(err, data) {
if (err) {
console.log("ERROR : ", err);
} else {
res.render('logged_in', {
email: data.value1,
username: data.value2,
});
res.end();
}
});
} else {
res.render('index', {
validation: "failed"
});
}
});
});
I'm only calling one function here (getUser()), and when I call this function, the layout changes, and I send some values.
But now I would like to create a new function called getPosts(), to get informations from a different table, and send it to the layout too, like I did when i called the function getUser()
I tried to do something like this but I had no success, when I call the variables outside the scope I keep getting "undefined".
router.post('/login', function(req, res) {
connection.query('SELECT user_id FROM users WHERE user_email = ? AND user_password = ?', [req.body.login, req.body.password], function(err, results) {
if (err) throw err;
if (results[0]) {
userId = results[0].user_id;
getUser("username", userId, function(err, data) {
if (err) {
console.log("ERROR : ", err);
} else {
email = data.value1;
username = data.value2;
}
});
getPosts("posts", 1, function(err, data) {
if (err) {
console.log("ERROR : ", err);
} else {
postName = data.value1;
postText = data.value2;
}
});
res.render('logged_in', {
email: email,
username: username,
pstname: postName,
psttxt: postText
});
res.end();
} else {
res.render('index', {
validation: "failed"
});
}
});
});
What do I need to change on my code? Thank you.
You should read about asynchronization in node.js so if you change your code as bellow it may work:
router.post('/login', function(req, res) {
connection.query('SELECT user_id FROM users WHERE user_email = ? AND user_password = ?', [req.body.login, req.body.password], function(err, results) {
if (err) throw err;
if (results[0]) {
userId = results[0].user_id;
getUser("username", userId, function(err, data) {
if (err) {
console.log("ERROR : ", err);
} else {
email = data.value1;
username = data.value2;
getPosts("posts", 1, function(err, data) {
if (err) {
console.log("ERROR : ", err);
} else {
postName = data.value1;
postText = data.value2;
res.render('logged_in', {
email: email,
username: username,
pstname: postName,
psttxt: postText
}
});
}
});
} else {
res.render('index', {
validation: "failed"
});
}
});
});

Sailsjs: How to populate association after *update* to model?

I have the following controller code that works for index, show, create methods but the update fails when I include populate - what am I doing wrong?
// User List
index: function(req, res) {
User.find()
.populate('profile')
.exec(function(err, users) {
if (err) return res.json(err, 400);
if (!users) return res.json(users, 404);
res.json(users, 200);
});
},
// Single User
show: function(req, res) {
User.findOne({ username: req.param('username') })
.populate('profile')
.exec(function(err, user) {
if (err) return res.json(err, 400);
if (!user) return res.json(user, 404);
res.json(user, 200);
});
},
// Create User
create: function(req, res) {
User.create(req.body, function(err, user) {
if (err) return res.json(err, 400);
Person.create({user: user.id, slug: user.username}, function(err, profile) {
if (err) return res.json(err, 400);
User.update(user.id, {profile: profile.id})
.populate('profile')
.exec(function(err, user) {
if (err) return res.json(err, 400);
});
user.profile = profile;
res.json(user, 200);
});
});
},
// Update User
update: function(req, res) {
var username = req.param('username');
User.update({ username: username }, req.body)
.populate('profile')
.exec(function(err, user) {
if (err) return res.json(err, 400);
res.json(user, 201);
});
},
As per the documentation the update function takes a callback to which it passes the updated records.
Example from the doc :
// For example, to update a user's name,
// .update(query, params to change, callback)
User.update({
name: 'sally'
},{
phone: '555-555-5555'
}, function(err, users) {
// Error handling
if (err) {
return console.log(err);
// Updated users successfully!
} else {
console.log("Users updated:", users);
}
});
Applied to your code, it would look like this :
// Update User
update: function(req, res) {
var username = req.param('username');
User.update({ username: username }, req.body)
.exec(function(err, users) {
if (err) {
return res.json(err, 400);
}
var user = users.slice(0,1); // Take the first user in the array
User.findOne(user.id) // You may try something like User._model(user) instead to avoid another roundtrip to the DB.
.populate('profile')
.exec(function(err, user) {
if (err) {
return res.json(err, 400);
}
res.json(user, 201);
});
});
}
Jeremie your answer is correct in essence but has a few issues:
the user object returned by the update call and then sliced does not
have a populate function
slice the users list returns a list instead of the object desired
Personal preference but I also prefer the following which uses the exec call instead of the callback.
update: function(req, res) {
var id = req.param('id');
User
.update(id, req.params.all())
.exec(function(err, users) {
if(err) return res.json(err, 400);
var user = users[0];
console.log('ID', user.id);
User
.findOne(user.id)
.populate('profile')
.exec(function (err, user){
if (err) return res.json(err, 400);
res.json(user, 201);
});
});
},

Resources