On my project with node and mongodb db.collection.find just not working. In routes.js file there is a function getUser() that tried to find a user by user_id, but finds nothing. I tried to do the same with same parameters on console and everything works fine.
How to invoke the error: go to your profile page, create an item and redirect back to the profile page, then refresh it. Because of that a profile.ejs file can't be executed.
function getUser(user_id) {
var items;
User.find({'user.id': user_id}, function(err, users) {
if(err) throw err;
items = users;
return items;
});
}
app.get('/profile', isLoggedIn, function (req, res) {
wasMessageShown(app.locals.answerObj);
console.log(req.user);
var user;
if(req.user.user.id){
user = req.user;
} else {
user = getUser(req.user.item.user_id);
}
res.render('profile.ejs', {
user: user,
messageSuccess: app.locals.answerObj.messageSuccess,
messageFailure: app.locals.answerObj.messageFailure
});
});
Related
I am using app.param to enter a parameter into the url which is the user username and it works except that any get requests right after that do not load the html page for the client. I am not getting any type of error except after the page fails to load i get a 404 error on the page. What could be the issue, i even tried router.param instead and got the same result. obviously the functionallity requires this to work on multiple pages.
//Profile views for other users
app.param('username', function(req, res, next, username) {
User.findOne({ 'local.username' : username }, function(err, user) {
if(err)
throw err;
if(user==null)
return false;
req.person = user;
next();
});
});
app.get('/:username', function(req, res) {
Profile.findOne({ 'pic.username' : req.person.local.username }, function(err, profilepic) {
if(err) {
throw err;
}
console.log(profilepic);
res.render('pages/visitprofile', {
user : req.person,
profilepic : profilepic
});
});
});
app.get('/photos/:username', function(req, res) {
Profile.findOne({ 'pic.username' : req.person.local.username }, function(err, profilepic) {
if(err)
throw err;
res.render('pages/photos', {
profilepic : profilepic
});
});
});
app.listen(3000);
console.log('express is listening on port 3000');
When you are using app.get('/:username', callback) syntax, you need to look for req.params.username.
app.get('/photos/:username', function(req, res) {
res.send(req.params.username);
}
Here is the code:
exports.delete = function (req, res, next) {
console.log(req.user);
req.user.remove(function (err) {
if(err) {
return next(err);
} else {
res.json(req.user);
}
})
};
Of course this function is callback of delete method, what I don't understand is that, why removing req.user also deletes the specific user from MongoDB, as it is just a request.
Edit:
I have another callback(GET) which is executed on the same route:
exports.userByID = function (req, res, next, id) {
User.findOne({
_id: id
}, function (err, user) {
if (err) {
return next(err);
} else {
req.user = user;
next();
}
});
};
User is MongoDB model.
Where you do your req.user = user you're setting the value of req.user to the instance of your mongodb model.
So, calling req.user.remove is in fact calling your mongodb model remove function.
Change your delete function to:
exports.delete = function (req, res, next) {
console.log(req.user);
delete req.user
//etc...
};
delete req.user will remove the user object from your request object
With the following controller, how can I call one method from another in the same controller?
Specifically, calling login() within a successful signup(), while retaining the same functionality for login() when it is used by a form?
The line this.login(newUser) does not work, nor does plain old login(newUser)
In both scenarios, I get the error:
TypeError: Cannot call method 'login' of undefined
var mongoskin = require('mongoskin');
module.exports = {
login: (function (req, res) {
req.db.collection('auth').findOne({_id: mongoskin.helper.toObjectID(req.body.id)},
function (err, results) {
// log person in and send results to client
}
)
}),
signup: (function (req, res) {
var user = req.body;
req.db.collection('auth').insert(user, function (err, newUser) {
// after adding user, automatically log them in
// does not work:
//login(newUser, function (err) {
// do something
//})
// does not work:
this.login(newUser, function (err) {
// do something
})
}
)
})
}
Controllers should be doing as little as possible, and should orchestrate the work required by executing functions stored elsewhere.
View this gist - click here
What I have done is created "services" that are not tied to the client request, therefore re-usable everywhere.
Hope this helps.
Thanks to Dave Newton
var mongoskin = require('mongoskin');
var myCollection = 'auth';
Solution
function localLogin(db, myCollection, user, res){
db.collection(myCollection).findOne({_id: mongoskin.helper.toObjectID(user._id)},
function(err, user){
res.send({ token: createToken(user) });
});
module.exports = {
login: (function (req, res) {
var user = req.body;
localLogin(req.db, myCollection, user, res)
},
signup: (function (req, res) {
var user = req.body;
req.db.collection(myCollection).insert(user, function (err, newUser) {
// after adding user, automatically log them in
localLogin(req.db, myCollection, newUser, res)
})
}
) }) }
When updating a user (via database update) in my Node.JS Express app, I update a user session which then updates a res.locals.session
However, when I try to access the res.locals.session within the Jade template, the values are displayed as they were prior to the database update.
Please can you help me to find out why the res.locals.session is not updating in the template?
Here is my code (cut down for brevity):
index.js
// Store session to locals so I can use it in Jade
app.use(function (req, res, next) {
res.locals.session = req.session;
next();
});
routes/user.js
var User = require('../models/Users');
function displaySettings(req, res) {
res.render('settings');
}
function saveSettings(User, req, res) {
// Updating user
User.update(
{ Member_id: req.session.user.Member_id }
, { settings: req.body }
, { upsert: false, multi: false }
, function (err) {
//if(err) return next(err);
//res.json({ message : 'Success!'});
console.log("saved");
});
// Retrieving user again, so that I can resave the updated user's details
// in the res.locals.session
var user = User.findById(req.session.user._id, function (err, user) {
console.log("found");
console.log(user);
req.session.user = user;
console.log(req.session.user);
res.locals.session = req.session;
console.log(res.locals.session);
});
// Finally display the view
displaySettings(req, res);
}
views/settings.jade
extends layout
block content
include includes/navigation
div.container.main
h1.text-center User Settings
div.row
div.col-md-6.col-md-offset-3
form#form-login.form-horizontal(action='/settings',method='post')
div#container(data-role='fieldcontain')
fieldset(data-role='controlgroup')
div.form-group
label.col-sm-4.control-label(for='username') Paypal Email
div.col-sm-8
// The session.user.settings.paypalEmail is showing
// the old value even after the user has re-saved
// their settings. I'm expecting the new, updated
// value to be displayed instead
input.form-control(id='username',type='text',value='#{session.user.settings.paypalEmail}',name='paypalEmail')
Try using res.redirect('settings') instead of calling displaySettings(req, res). I think this will allow res.locals to update.
what about rewriting the saveSettings as follows.
function saveSettings(User, req, res) {
// Updating user
User.update(
{ Member_id: req.session.user.Member_id }
, { settings: req.body }
, { upsert: false, multi: false }
, function (err) {
//if(err) return next(err);
//res.json({ message : 'Success!'});
console.log("saved");
// Retrieving user again, so that I can resave the updated user's details
// in the res.locals.session
var user = User.findById(req.session.user._id, function (err, user) {
console.log("found");
console.log(user);
req.session.user = user;
console.log(req.session.user);
res.locals.session = req.session;
console.log(res.locals.session);
// Finally display the view
displaySettings(req, res);
});
});
}
I am building an API using Restify and Mongoose for NodeJS. In the method below after finding the user and verifying their password, I am trying to save some login information before sending the response back to the user. The problem is the response will never return. If I place the response outside and after the save call, the data never gets persisted to MongoDB. Am I doing something wrong? And help would be great as I have been working on this for the past 2 days.
login: function(req, res, next) {
// Get the needed parameters
var email = req.params.email;
var password = req.params.password;
// If the params contain an email and password
if (email && password) {
// Find the user
findUserByEmail(email, function(err, user) {
if (err) {
res.send(new restify.InternalError());
return next();
}
// If we found a user
if (user) {
// Verify the password
user.verifyPassword(password, function(err, isMatch) {
if (err) {
res.send(new restify.InternalError());
return next();
}
// If it is a match
if (isMatch) {
// Update the login info for the user
user.loginCount++;
user.lastLoginAt = user.currentLoginAt;
user.currentLoginAt = moment.utc();
user.lastLoginIP = user.currentLoginIP;
user.currentLoginIP = req.connection.remoteAddress;
user.save(function (err) {
if (err) {
res.send(new restify.InternalError());
return next();
}
// NEVER RETURNS!!!!
// Send back the user
res.send(200, user);
return next();
});
}
else {
res.send(new restify.InvalidCredentialsError("Email and/or password are incorrect."));
return next();
}
});
}
else {
res.send(new restify.InvalidCredentialsError("Email and/or password are incorrect."));
return next();
}
});
}
else {
res.send(new restify.MissingParameterError());
return next();
}
},
One cause of this issue can be if you have a pre save hook which errors silently.
If you find your model as a .pre('save' () => {...}) function then double check this method is reached after you call save, and that it returns without errors.
Documentation on mongoose middleware can be found here