Express.js session undefined in method put - node.js

Building an API with node and express. In my "home" route i set a session with a users id.
When i want to add and update information on a user i want to access the session to know which user to update. In my get routes i can access the session, but in my route with put method its always undefined. Why is this?
app.get('/users/:id/spots', spot.findSpotsByUserId); //I set the session in this method
app.get('/spots/:id', spot.findById);
app.put('/userspot/spot/:spotId/add'', spot.addUserSpot);
exports.findSpotsByUserId = function(req, res) {
var id = req.params.id; //Should ofc be done with login function later
db.collection('users', function(err, collection) {
collection.findOne({'_id':new BSON.ObjectID(id)}, function(err, user) {
if (err) {
res.send({'error':'Couldnt find user'});
} else {
req.session.userId = id;//<----- sets session
console.log("SESSION",req.session.userId);
}
......}
exports.findById = function(req, res) {
var id = req.params.id;
console.log('Get spot: ' + id);
console.log("SESSION!",req.session.userId);// <----prints the id!
db.collection('spots', function(err, collection) {
collection.findOne({'_id':new BSON.ObjectID(id)}, function(err, item) {
res.send(item);
});
});
};
exports.addUserSpot = function(req, res) {
var user = req.session.userId;
var spot = req.params.spotId;
console.log("SESSION!",req.session.userId);// always UNDEFINED!
//........}

You are looking for req.params.userId, not req.session.
The session is persisted between multiple calls, and it has no connection to the params object. You can set req.session.userId in a previous call and access it here, but I don't think this is what you want.
Try this:
exports.findById = function(req, res) {
req.session.test = "from findById";
...
};
exports.addUserSpot = function(req, res) {
console.log(req.session.test, req.params.userId);
...
};

Related

How to save user id value from database on server?

I have login/signup routes where I save a user to database. Every user has its own page where he can customize eveything. For example user changes his status. Status component makes ajax call to my server, and then my server tries to find a user from the curent session (I do not know how to do that) and then changes his status property in db.
I'm using React, Express, Mongoose.
I thought I coul'd save a user to my req object on /login or /signup route but this doesn't work.
api.get('/login', (req) => {
...getting data from req obj
req.user = user
...doing other things
});
The req object contains data coming in from the http call.
For example if your react app made a GET request to this url
http://localhost/user/123
and you had defined a route in your express app like this
router.get('user/:id', getUser());
then you can access this request object to get the user id in the http url param.
function getUser(req, res) {
let user_id = req.params.id
}
with that user_id you can find a user in the mongodb using mongoose like this.
function getUser(req, res) {
let user_id = req.params.id;
User.findOne({'_id': user_id}, (err, user) => {
if(err) {
return res.json(err);
}
return res.json(user);
});
}
or you can update a user object
function update(req, res) {
let user_id = req.params.id;
let avatar_url = req.body.avtar;
User.findOne({ '_id': user_id }, (err, user) => {
if (err) {
return res.json(err);
}
user.avatar = avatar_url;
user.save((err, user) => {
if(err) {
return res.json(err);
}
return res.json(user);
})
});
}
Recommend you read this to learn the basics.
http://mongoosejs.com/docs/guide.html
https://scotch.io/tutorials/build-a-restful-api-using-node-and-express-4

Redirecting POST to GET after Database Addition

I am using Mongoose and Express.js .
My Post request looks like this :
$('#update').on('click', function() {
var uname = $('#username').val();
var name = $('#name').val();
var json = {
user_name: name,
user_username: uname,
};
$.post("/saveprofile", json, function(data, error, xhr) {
if(!err)
window.location.href = "/feed";
});
});
This is how I'm handling the request :
app.post('/saveprofile', isLoggedIn, function(req, res) {
var username = req.body.user_username;
var uname = req.body.user_name;
User.findOne({$or:[{"facebook.email":req.user.facebook.email},{"local.email":req.user.local.email}]}, function (err, user){
user.name = uname;
user.username=username;
user.save();
res.send({redirect: '/feed'});
})
});
My documents get added into the db successfully but what I want is, when that happens it should redirect to a new page /feed . The above snippets mention 2 methods I've tried. But I've got no result . It doesn't redirect !
Edit:
Testing with exception handling gives undefined
app.post('/saveprofile', isLoggedIn, function(req, res) {
var username = req.body.user_username;
var uname = req.body.user_name;
try{
User.findOne({$or:[{"facebook.email":req.user.facebook.email},{"local.email":req.user.local.email}]}, function (err, user){
user.name = uname;
user.username=username;
user.save();
res.redirect("http://stackoverflow.com")
});
}
catch(ex){
console.log(ex) ;
}
});
Edit 2 :
I tried a sample request ...even it doesn't seem to redirect !
app.post('/test', isLoggedIn, function(req,res){
res.redirect("http://www.stackoverflow.com")
})
You can't make a redirection after an AJAX. You need to do it with Javascript.
So here is how we can do it,
Post request :
$('#update').on('click', function() {
var uname = $('#username').val();
var name = $('#name').val();
var json = {
user_name: name,
user_username: uname,
};
$.post("/saveprofile", json, function(data, err, xhr) {
if(!err)
window.location.href = data.redirect;
});
});
Server
app.post('/saveprofile', isLoggedIn, function(req, res) {
var username = req.body.user_username;
var uname = req.body.user_name;
User.findOne({$or:[{"facebook.email":req.user.facebook.email},{"local.email":req.user.local.email}]}, function (err, user){
user.name = uname;
user.username=username;
user.save(function(err){
if(!err)
res.send({redirect: '/feed'});
});
})
});
Link to Original Answer
Try res.redirect() instead :
res.redirect("/feed");

NodeJs - calling one method from another in server controller

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)
})
}
) }) }

Trying to update res.locals after database update

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);
});
});
}

Logout BasicAuth in node.js

i have reference for http://blog.modulus.io/nodejs-and-express-basic-authentication
my code conect my database mongodb:
var admin = express.basicAuth(authentikasi);
function authentikasi(user, pass, callback) {
// declrare my database mongodb
db.collection('ak_admin', function (err, data) {
data.findOne({'adm_name': {'$regex': user}}, function (err, level) {
if (level == null) {
console.log('Nilai database Administrator masuk Null ulangi login');
callback(null);
} else {
var a = level.adm_name;
var b = level.adm_password;
var c = level.adm_mobile;
if (user === a && pass === b) {
callback(null, {name: a, id: c});
} else
callback(null, false);
}
});
});
};
app.get('/admin', admin, function(req, res){
res.sendfile(__dirname + '/admin/index.html');
});
my schema for login basicauth is succesfull but my question : how to create logout because my site admin have login after use this schema not input username and password again :
app.get('/logout', function(req, res){
//how code in here for erase memory in variable admin (user and pass)
res.sendfile(__dirname + '/public/index.html');
});
please help me thanks you...

Resources