Updating a object in mongoose results in loop - node.js

In my nodejs API app I have this route:
router.post('/startuserseries', function(req, res, next){
if(!req.body.username){
return res.status(400).json({message: 'Geen username'});
}
User.findOne({ 'username': req.body.username}, function(err, foundUser){
if(err)
return next(err);
if (foundUser) // check the value returned for undefined
{
foundUser.isdoingchallenges = true;
foundUser.save(function (err) {
if(err) {
console.error('ERROR!');
}
});
}
});
});
When I call this route in postman, the request never ends.
I have tried to use PUT but also didn't work, I tried various structures of code but neither worked.

This request will not finish because it doesn't write a response command on server.
You should solve easily this problem like below:
router.post('/startuserseries', function(req, res, next){
if(!req.body.username){
return res.status(400).json({message: 'Geen username'});
}
User.findOne({ 'username': req.body.username}, function(err, foundUser){
if(err)
return next(err);
if (foundUser) // check the value returned for undefined
{
foundUser.isdoingchallenges = true;
foundUser.save(function (err) {
if(err) {
res.json(err);
}
});
}
res.send(200);
// or your specific result json object
// res.json({"error":false,"message":"completed"})
});
});

Related

What is the proper way to handle an error in Node.JS?

This post request creates a new user account and saves a test score data point for a user.
~1/20 users or so run into an error and are redirected back to the previous page thus losing their results.
I have been unable to replicate the error or see any errors in the logs.
Looking for advice on how to change my error handling and or any insight to why this may be occurring.
Thank you!
router.post("/test", function(req, res){
User.findOne({username: req.body.username}, function(err, existingUser) {
console.log('user exists:' + existingUser)
if (err) {
return done(err);
}
if (!existingUser) {
var newUser = new User({username: req.body.username});
User.register(newUser, req.body.password, function(err, user){
user.testscore = req.body.testscore;
user.save()
if(err){
req.flash("error", err.message);
console.log(err)
res.redirect('back')
return res.render("register");
}
passport.authenticate("local")(req, res, function(){
res.redirect("/thank-you");
});
});
You can use try-catch along with async-await for error handling. I would write the code like this.
router.post('/test', async (req, res) => {
try {
const user = await User.findOne({username: req.body.username})
if (!user) {
let newUser = new User({username: req.body.username});
// If User.register returns promise then here also you can use await like above.
// If any error occurs catch block will catch it and show the error.
User.register(newUser, req.body.password, function(err, user) {
user.testscore = req.body.testscore;
user.save()
if(err) {
req.flash("error", err.message);
console.log(err)
res.redirect('back')
return res.render("register");
}
passport.authenticate("local")(req, res, function() {
res.redirect("/thank-you");
});
});
}
} catch (err) {
console.error(err.message)
}
})
Hope it helps to solve your problem.

Use request and passport npm login account

I am using nodejs for a project,now I want login my account with passport npm,but not from webpage,from request post method,can it be done?
main code like this:
router.post('/login',function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) { return next(err); }
if (!user) { return res.json(null); }
req.logIn(user, function(err) {
if (err) { return next(err); }
//return res.redirect('/'); redirect not work
});
})(req, res, next);
});
router.get('/check',function(req, res, next) {
request.post({
url:'http://localhost/login',
headers:{
'Content-Type': 'application/x-www-form-urlencoded'
},
form:{
username:'myname',
password:'mypassword'
}},function(err,httpRes,body){
//do here...?
return res.redirect('/');
});
});
When I call "check" with get method and use the correct username/password,I can print out the user data from database in "login" method,but lost the user session when it redirect home page.Any suggestion?
It's not redirecting the user when they GET /check because the POST request to /login in /check is getting redirected itself, not the actual user. Also making internal requests to internal webpages isn't the best solution for logging in. I suggest creating login() middleware like so:
// Don't forget to set req.body.username and req.body.password when calling login().
var login = function login(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) { return next(err); }
if (!user) { return next(); }
req.logIn(user, function(err) {
if (err) { return next(err); }
return next(null);
});
})(req, res, next);
};
And then calling it appropriately:
router.post('/login', login, function(req, res, next) {
if (req.user) {
console.log('We logged in successfully!');
res.redirect('/');
} else {
res.json(null);
}
});
router.get('/check', function(req, res, next) {
if (!req.user) {
login(req, res, function(err) {
if (err) {
return next(err);
}
if (!req.user) {
// No user, do some error handling.
} else {
// We have the user, do some custom stuff...
}
res.redirect('/');
});
} else {
// User is logged in already, do some other custom stuff...
}
});
You can check if a user is logged in by checking if req.user exists.

Getting out of sync server response

On a successful signup of a user I am currently seeing a mostly empty page with the text undefined. Redirecting to /app at the top.
UPDATE: I should also mention that after form submittal I am redirected to /users. So on /users I see the text mentioned above.
I think it is because of the req.redirect call being within the user.save callback but I am not sure what the fix is.
I am using mongoose for the ORM.
var User = require('../models/user');
module.exports = function(app) {
app.post('/users', function(req, res, next) {
var user = new User({
email: req.body.email,
password: req.body.password
});
user.save(function(err) {
if (err)
res.send(412, {message: err});
else
req.login(user, function(err) {
if (err !== undefined) return next(err);
res.redirect('/app', {
email: user.email,
id: user._id
});
});
});
});
};
It turns out that the req.login call has to be contained in a password.authenticate callback. The example on the site left that part out.
user.save(function(err) {
if (err)
res.send(412, {message: err});
else
passport.authenticate('local', function(err, user) {
if (err) { return next(err) }
if (!user) { return res.redirect('/login') }
req.login(user, function(err) {
if (err) { return next(err); }
return res.redirect('/app', { email:user.email, id:user._id });
});
})(req, res, next);
});

Can't assign req.session.user when is called fs.mkdir

This is the code of the app.post that calls fs.mkdir by the function that I made, newdir:
app.post('/register', express.bodyParser(), function (req, res, next){
var newu = new UserModel({});
newu.user = req.body.nuser;
newu.pass = req.body.npass;
newu.mail = req.body.nmail;
UserModel.find({ user: req.body.user }, function (err, user){
if (user.lenght == 1) {
res.redirect('/');
}
else {
newdir(req.body.nuser);
next()
if (err) throw err;
newu.save(function (err, newu){
req.session.user = newu.user;
res.redirect('/home')
});
}
});
});
This is the code of newdir:
function newdir (username){
var pathu = __dirname + '/users/' + username;
fs.mkdir(pathu, function (err){
if (err) throw err;
});
}
An this is the code of /home:
app.get('/home', function (req, res){
console.log(req.session.user);
res.send('Welcome ' + req.session.user + '!');
});
I can assign a req.session.user in all app.post/get that I want, for example when I verify the user with this, I can assign the req.session.user correctly:
app.post('/verify', express.bodyParser(), function (req, res){
UserModel.find({ user: req.body.user }, function (err, user){
if (user[0] == undefined) {
res.redirect('/');
}
else{
if (user[0].pass == req.body.pass) {
req.session.user = user[0].user;
res.redirect('/home');
}
else{
res.redirect('/');
}
}
if (err) throw err;
});
});
But when I try to assign req.session.user in the same app.post where's it's called fs.mkdir, always req.session.user is undefined. Maybe I should create a module that makes the fs.mkdir call? I don't know what to do!
The problem is resolved when fs.mkdir is called in other module, very simple :D

calling functions and passing callback with express.js

What's the proper way to use custom callbacks with express.js functions?
Here's an example:
//routes/reset.js
user.save(function(err){
if ( err ) return next(err);
reset.send_reset_email(req, res, user, function(req, res){
req.flash('info', 'Check your email for a link to reset your password.');
res.redirect('/');
});
});
What signature should I use for reset.send_reset_email for this to work correctly?
This is what I have:
exports.send_reset_email = function(req, res, user, next){
//send email
transport.sendMail(options, function(err, responseStatus) {
if (err) {
console.log(err);
} else {
next(req, res);
//do I need to explicitly pass req, res here?
//is next() reserved word here?
}
});
});
Do I need to explicitly pass req, res here?
is next() reserved word here?
next() accepts an error or another route and is usualy called to continue with the next middleware.
in your send_reset_email function your next() isn't express's next() because you pass in function(req,res) and not next, pass in your own callback instead to handle the outcome of your sendmail function.
user.save(function(err){
if (err) return next(err) // if thats express's next()
reset.send_reset_email(req, res, user, function(err, data){
if(err) {
// send err msg
} else {
req.flash('info', 'Check your email for a link to reset your password.');
res.redirect('/');
}
});
});
xports.send_reset_email = function(req, res, user, cb){
//send email
transport.sendMail(options, function(err, responseStatus) {
if (err) return cb(err)
cb(null,responseStatus)
})
})

Resources