Error: can't set header after they are sent - node.js

I have two schemas, one for user and one for friendship system (follow system)
module.exports = mongoose.model('User', {
email: {
type: String,
unique: true,
lowercase: true
},
password:String,
profile: {
fullname: String,
gender: String,
role: {type: String, default: 'Autorizado'},
country: String },
});
and this for friend system
module.exports = mongoose.model('Friendship', {
follower: String,
followed: String
});
I'm using passport to auth my users... the problem is that I want lo load the user information and the friend information related to the user globally using res.locals I make this happen using 2 functions in login post route....
router.post('/login', userController.postLogin,friendController.getFollow);
this is my postlogin function
exports.postLogin = function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) return next(err);
if (!user) {
req.flash('errors', { msg: info.message });
return res.redirect('/login');
}
req.logIn(user, function(err) {
if (err) return next(err);
req.flash('success', { msg: 'Success! You are logged in.' });
res.redirect('/');
});
})
(req, res, next);
};
When I try to execute this code everything goes fine but when I log in I get the header error please how can I solved this or other way to get the user and follow information and use it in every view?.
EDIT 3: only works in the next two views
Single User page
<%= info.profile.fullname %>
<br>
<%= info.email %>
<br>
<%= info.profile.country %>
<br>
<%= user.follow %>
<br>
<% if(user && (user._id != info.id)){ %>
<br>
<form action="/follow/<%= info._id %>" method="post">
<button type="submit">Follow</button></form>
<%}%>
<br>
atras
List of Registered User
<%if (user) {%>
<h1>Hola <%= user.profile.fullname %> </h1>
<%}%>
<br>
<% users.forEach(function (user) {%>
<p><%= user.profile.fullname %></p>
<%});%>
Home
This is my index and in this view the user.follow doesn't work
<%if (!user) {%>
sign up
<br>
login
<%} else { %>
<h1>Hola <%= user.profile.fullname %> Eres lo Maximo</h1>
perfil
<br>
Logout
<br>
<%}%>
<br>
Lista de Usuarios
EDIT 4: new deserializeUser config.
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
FF.find({ follower:id }, function(err, follow) {
user.follow = follow;
});
done(err, user);
});
});
EDIT 5: This is my route code
router.get('/', function(req, res) {
res.render('index');
});
router.get('/login', userController.getLogin);
router.post('/login', userController.postLogin);
router.get('/logout', userController.logout);
router.get('/signup', userController.getSignup);
router.post('/signup', userController.postSignup);
router.get('/profile', passportConf.isAuthenticated, userController.getAccount);
router.post('/profile', passportConf.isAuthenticated, userController.postUpdateProfile);

You had friendController.getFollow which would've worked only for the request of '/login' page, so the follow object wouldn't have been persistently available on other routes. To fix that you had to put all that code inside the passport.deserializeUser function.
Inside the passport.deserializeUser function you could only call done once so you had to put the logic to find follow inside the callback of User.find so that you could attach follow to user.
This allowed you to remove the friendController.getFollow from your '/login' route which I think was the cause of your error.

Related

How to pass database values from node js to ejs file

Hi I am trying to add search bar in main page and search in the main page without changing to another page.
My user.js file
if (req.method == 'get'){
var username = req.query.username;
Users.find({username}, function (err, user) {
if(err) {
return res.render(template:'index')
}
res.render({template:'index', { user : user}});
})
}
my index.ejs file
<div class="search-user">
<% for user in user { %>
<div>
<p>Username : <%= user.username %></p>
<p>Age <%= user.age %></p>
<p>Status <%= user.status %></p>
</div>
<% } %>
</div>
This is giving me errors. May i know what did i do wrong?
Add a console message and check if you are getting data in user object
if (req.method == 'get'){
var username = req.query.username;
Users.find({username}, function (err, user) {
if(err) {
console.log('error', error)
return res.render('index')
}
console.log('user', user)
res.render('index', { user });
})
}
Further before iterating user of object just check something like this:
<div>
<p>Username : <%= JSON.stringfy(user) %></p>
</div>
By this you will get to know where error is being occured.
Refer to Res.render()
if (req.method == 'get'){
var username = req.query.username;
Users.find({username}, function (err, user) {
if(err) {
return res.render('index')
}
res.render('index', { user });
})
}

How to stop routing to the given route if validation fails

In my signup.ejs file, I have setup a form with post request and i have written /welcome route in signup.js file, I am trying to figure out how i can stop the post request to the given route if validation fails or how i can dynamically assign a different route like an error route (localhost:3000/signup/error instead of localhost:3000/signup/welcome if validation fails) as everytime signup fails, it is routing to localhost:3000/signup/welcome which is not right. I tried setting up variables in signup.ejs file to pass it in action, however, it only routes to /welcome and it doesn't route to /error. Basically, I just want to see error endpoint or just stop the POST request if validation fails. Please suggest.
signup.ejs
<h2>Sign Up</h2>
<% var route = ''; %>
<% if (!messages.error) { %>
<% route = '/welcome' %>
<% }else{ %>
<% route = '/error' %>
<% } %>
<form action="signup<%- route %>" method="post" name="form1">
signup.js
router.post('/welcome', function(req, res, next) {
req.checkBody('name', 'Name cannot be empty').notEmpty();
req.checkBody('email', 'Please enter valid email').isEmail();
req.checkBody('password', 'Password should be more than 5').isLength({ min: 5 });
req.checkBody('password1', 'Password do not match').equals(req.body.password);
var errors = req.validationErrors();
if(!errors) {
var user = {
name: req.sanitize('name').escape().trim(),
email: req.sanitize('email').escape().trim(),
password: req.sanitize('password').escape().trim()
}
connection.query('Insert into customers set ?', user, function(err, result) {
if(err) {
req.flash('error', err);
//render to signup
res.redirect('/signup', {
title: 'Add New User',
name: user.name,
email: user.email,
password: user.password
})
}
req.flash('success', 'Successfully signed up');
res.render('welcome', {
title: 'Signed In'
});
})
}else {
var error_msg = ''
errors.forEach(function(error) {
error_msg += error.msg + '<br>'
})
req.flash('error', error_msg);
res.render('signup', {
name: req.body.name,
email: req.body.email,
password: req.body.password
})
}
});

How to display all users database (mongodb) details on .ejs file

I have a node.js website that i build with this tutorial:
https://scotch.io/tutorials/easy-node-authentication-setup-and-local
now i want in one of my views to print/display all users data.
in routes.js:
var User = require('../app/models/user'); //the connection to users database
app.get('/profile', isLoggedIn, function (req, res) {
res.render('profile.ejs', {
Users: User // get the user out of session and pass to template
});
});
and this is in my profile.ejs file:
<ul>
<% Users.forEach( function(err, user) { %>
<li><%= user %> </li>
<% }); %>
i get an error: "undefined is not a function" because of the <% Users.forEach( function(err, user) { %> line
what am i doing wrong?
You need to actually query the user collection via the model's find() query function which will return an array of user documents when executed, i.e.
var User = require('../app/models/user'); //the connection to users database
app.get('/profile', isLoggedIn, function (req, res) {
User.find({}).exec(function(err, users) {
if (err) throw err;
res.render('profile.ejs', { "users": users });
}
});
then render the list of user documents in your profile.ejs as:
<% users.forEach(function (user) { %>
<li>
<h1><%= user.name %></h1>
</li>
<% }) %>

Why is User.follow only available in two view?

I'm using Passport to authenticate my users and pass their information to every view, beside the information stored in the user database. I'm trying to pass the friendship information related to the user (logged in user). The problem is that this only works in two of my views:
Single User page
//info is the profile information of a registered user
<%= info.profile.fullname %>
<br>
<%= info.email %>
<br>
<%= info.profile.country %>
<br>
<%= user.follow %>// just for testing
<br>
<% if(user && (user._id != info.id)){ %>
<br>
<form action="/follow/<%= info._id %>" method="post">
<button type="submit">Follow</button></form>
<%}%>
<br>
atras
List of Registered User
<%if (user) {%>
<h1>Hola <%= user.profile.fullname %> </h1>
<%}%>
<br>
<% users.forEach(function (user) {%>
<p><%= user.profile.fullname %></p>
<%});%>
<%= user.follow %>// just for testing
Home
This is my index and in this view the user.follow doesn't work
<%if (!user) {%>
sign up
<br>
login
<%} else { %>
<h1>Hola <%= user.profile.fullname %> Eres lo Maximo</h1>
perfil
<br>
Logout
<br>
<%}%>
<br>
Lista de Usuarios
<%= user.follow %>// just for testing
//in this view i got undefined
deserializeUser config.
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
FF.find({ follower:id }, function(err, follow) {
user.follow = follow;
});
done(err, user);
});
});
This is my route code
router.get('/', function(req, res) {
res.render('index');
});
router.get('/login', userController.getLogin);
router.post('/login', userController.postLogin);
router.get('/logout', userController.logout);
router.get('/signup', userController.getSignup);
router.post('/signup', userController.postSignup);
router.get('/profile', passportConf.isAuthenticated, userController.getAccount);
router.post('/profile', passportConf.isAuthenticated, userController.postUpdateProfile);
//Test Usuarios
router.get('/users', friendController.getListUsers);
router.get('/users/:id',friendController.getShowUser);
// Test Follow
router.post('/follow/:id', passportConf.isAuthenticated,friendController.postFollowUser);

passport.js authenticate popup window using sails.js

i need a help in passport.js authentication.
passort.js authentiction working fine.
but i dont know how can i create authentication login in popup window.
all the authentication process functions in backend.
please help me.
'linkedin': function(req, res) {
passport.authenticate('linkedin', {failureRedirect: '/login', scope: ['r_basicprofile', 'r_emailaddress']},
function(err, user) {
req.logIn(user, function(err) {
if (err) {
// console.log(err);
res.view('500');
return;
}
req.session.user = user;
return res.redirect('/user');
});
})(req, res);
},
'facebook': function(req, res) {
passport.authenticate('facebook', {failureRedirect: '/login', scope: ['email','publish_stream'],display:'popup' },
function(err, user) {
req.logIn(user, function(err) {
if (err) {
throw err;
res.view('500');
return;
}
req.session.user = user;
if (p) {
//write the post project function
}
return res.redirect('/user');
});
})(req, res);
},
this is my login page
<form action ="/auth/linkedin" method = "POST" class="columns small-12 iconized" >
<input type="hidden" value="test messge" name="title">
<button type="submit" class="icon-linkedin">Linkedin</button>
</form>
please help how can i resize the window .
One solution is jquery.lightbox_me.js found here http://www.freshdesignweb.com/demo/index.php?p=1379320109
Just follow the steps:
1) download the source code, and copy the .js file to assets/js, and copy the .css file to assets/style
2) change your html code to
<button id="loginBtn" class="btn btn-success btn-med">Login</button>
<form id="loginForm" action ="/auth/linkedin" method = "POST" class="columns small-12 iconized" display: none; >
<input type="text" value="test messge" name="title">
<button type="submit" class="icon-linkedin">Linkedin</button>
</form>
<script>
$('#loginBtn').click(function(e) {
$('#loginForm').lightbox_me({
centered: true,
onLoad: function() {
$('#loginForm').find('input:first').focus()
}
});
e.preventDefault();
});
</script>
3) This should do the trick. However eventually it will best if you keep your js scripts out of the html/ejs files, so things are more tidy.
Since Sails comes with ejs-locals, I would put the content within the tags in a separate file and make a call to <% block ... %> instead. Check this page for more info:
Sails.js - How to inject a js file to a specific route?

Resources