nodejs sessions after refresh a page - node.js

This is simple login form. I have validated a email, if email is not valid it gives an error( no problem here). After refreshing that page instead of showing login form it also shows error along with login form on that page.
app.js
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var hbs = require('express-handlebars');
var expressValidator = require('express-validator');
var expressSession = require('express-session');
var routes = require('./routes/index');
var app = express();
// view engine setup
//app.engine('hbs', hbs({extname: 'ejs'}));
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
//app.set('views', path.join(__dirname, 'views'));
//app.set('view engine', 'hbs');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(expressValidator());
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(expressSession({secret: 'max', saveUninitialized: false, resave: false}));
app.use('/', routes);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
module.exports = app;
index.js file
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
console.log(req.session);
res.render('student_login', { success: req.session.success, errors: req.session.errors });
req.session.errors = null;
console.log(req.session);
});
router.get('/submit', function(req, res, next) {
req.check('e', 'Invalid email address').isEmail();
//req.check('p', 'Password is invalid').isLength({min: 4}).equals(req.body.confirmPassword);
var errors = req.validationErrors();
if (errors) {
console.log(req.session);
req.session.errors = errors;
req.session.success = false;
console.log(req.session);
} else {
console.log(req.session);
req.session.success = true;
console.log(req.session);
}
res.redirect('/');
});
module.exports = router;
student_login.ejs
<!DOCTYPE html>
<html >
<% if(success ){ %>
<h1>validation succesful</h1>
<% }
else{ %>
<ul>
<% if(errors) {%>
<h1> errors </h1>
<% } %>
</ul>
<h1>Login</h1>
<form action="/submit" method="get">
<input type="text" name="e" placeholder="Email" required="required" > <br>
<input type="password" name="p" placeholder="Password" required="required" > <br>
<button type="submit" >Let me in.</button>
</form>
<% } %>
</html>

The problem here is that you are saving your error in the session which means it will remain in the session unless you clear it out or the session ends.
What you need here is flash messages. These are similar messages stored in the session, but they are cleared once shown to the user, so they are shown only once.
I have used the connect-flash node module before. It is easy to set up and does the job perfectly.

Related

Extract data from form and add to database using Mongoose

I want to simply display usernames and age on the webpage using Express Node.js and Mongoose/
The view should get updated on the left while the form is at the right. Refer this image.
Below is my users.js (/users route) followed by html of the form.
Bodyparser has been included in app.js of this application.
On clicking submit, 404 not found is thrown.
Refer this error image
var express = require('express');
var router = express.Router();
/* GET users listing. */
router.get('/', function(req, res, next) {
res.render('userview');
});
router.post('#', function(req, res, next) {
//User is the model created in app.js of this project
var newUser = userModel({
name:req.body.name,
age: req.body.age
});
console.log(newUser);
// save the user
newUser.save(function(err) {
if (err) throw err;
console.log('User created!');
});
});
module.exports = router;
<form method="post">
Name:
<input type="text" name="name"><br><br>
Age:
<input type="number" name="age"><br><br>
<input type="submit" value="Submit">
</form>
Here is my app.js
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var index = require('./routes/index');
var users = require('./routes/users');
var applist = require('./routes/applist');
var mongoose=require('mongoose');
var app = express();
//set database connection
mongoose.connect('mongodb://localhost:27017/users');
mongoose.connection.on('error',function(){
console.log('MongoDB Connection Error. Please make sure that MongoDB is running');
process.exit(1);
});
mongoose.connection.once('open',function(callback){
console.log('Connected to Database');
});
var userSchema = new mongoose.Schema({
name:{type:String,uppercase:true},
age:Number
},{collection:'userlist'});
//make model
var userModel = mongoose.model('userModel',userSchema);
app.get('/users', function(req, res, next) {
userModel.find({},function(err,userModel){
res.render('userview',{userlist:userModel});
})
});
module.exports = userModel;
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', index);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
userModel is present in app.js
On the view change
name = "fullname" to name="name"
userview
<form method="post">
Name <input type="text" name="name"><br><br>
Age<input type="number" name="age"><br><br>
<input type="submit" value="Submit">
</form>
First of all, to use req.body you need to use body-parser or busboy, connect-busboy, multiparty, connect-multiparty, formidable, multer etc. - see:
https://github.com/expressjs/body-parser
Also, what is this route supposed to be:
router.post('#', function(req, res, next) {
This character is not valid in the URL path amd needs to be URL-encoded on the client side to work. Are you sure that this is the route your need?
If you are thinking about the fragment part of the URL (as in http://host/path#fragment) then it is not sent during the HTTP request at all. See:
https://en.wikipedia.org/wiki/Fragment_identifier

Express.js request.body not working

I have a simple form for login, the problem is when i press "Submit", the request.body on server side is empty.I saw that bodyParser is a fundamental part but in my case it's declared before the routes, so i think the problem is another. this is my server page App.js
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var index = require('./routes/index');
var users = require('./routes/users');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', index);
app.use('/users', users);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
app.listen(3000);
module.exports = app;
this is index.js
var express = require('express');
var router = express.Router();
function Login(req, res){
var mongoClient = require('mongodb').MongoClient;
mongoClient.connect('mongodb://localhost:27017/squaredDB', function(err, db) {
if(err) throw err;
db.collection('users').find({email: req.body.email}, function(err, data){
console.log(req.body);
});
});
}
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
router.post('/', function(req, res, next) {
Login(req, res);
res.render('app-home', { title: '' });
});
module.exports = router;
this is my jade template form:
form(method="post" action="/")
label Email
input(type="text" placeholder="Email")
label Password
input(type="password" placeholder="Password")
input(type="submit" value="login")
You're missing name attributes for your input fields in your template. Without those the browser won't submit them in the form.
Add a name attribute to your input field it will now be able to access the field via request like req.body.name
<form action="/", method="POST">
<input type="text" placeholder="name" name="name">
<button type="submit">Submit</button>
</form>

nodejs error 404 on post (not via url)

Whenever i try to submit from the index i get an error.
im trying to get the values from the username and password inputs.
this should be the code to handle the post:
app.post('/', function(req, res){
var username=req.body.username;
var password=req.body.password;
res.render("the username and password you posted:" +password+username);
});
my app.js
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var routes = require('./routes/index');
var users = require('./routes/users');
var patienten = require('./routes/patienten');
var form = require('./routes/form');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(bodyParser.json());
app.use('/', routes);
app.use('/users', users);
app.use('/patienten', patienten);
app.use('/form', form);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
app.get("/", function(req, res) {
res.send("i am from /get");
});
app.get("/", function(req, res){
res.sendfile("/");
});
app.post('/', function(req, res){
var username=req.body.username;
var password=req.body.password;
res.render("the username and password you posted:" +password+username);
});
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
module.exports = app;
The form.js
var express = require('express');
var router = express.Router();
var mysqlModel = require('mysql-model');
var request = require('request');
var ejs = require('querystring');
/* GET home page. */
router.get('/form', function(req, res) {
res.render('form', {
title: 'EPD - Login',
});
});
module.exports = router;
The form.ejs (the submit page)
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
<form action="/" method="GET">
<input type="text" name="username">
<input type="password" name="password">
<input type="submit" name="submit" value="gogo">
</form>
</body>
</html>
This middleware for handling your 404, should be placed after your last route. Otherwise as per your code, all your hits will return 404.
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
Besides, your form should send POST request not GET
<form action="/" method="POST">
Also, res.render is used to render a view. You can use res.send or res.json as you prefer.
app.post('/', function(req, res){
var username=req.body.username;
var password=req.body.password;
res.send("the username and password you posted:" +password+username);
});
You don't use res.render() for regular responses back to the client. Use res.send() instead. This is why you are receiving your error. res.render() is for use with a view engine in Express and sends back the rendered view template to the client. IE ejs in this case is the defined view engine and thats what the below code is doing
// view engine setup
// Tells express to render from the views directory
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
Your 404 handler should be your 2nd to last route in your express main file as it is a catch all for any routes that didn't match your defined routes since Express goes through routes Top-Down. Along with your 404 handler being defined in the wrong location within your Express app, you should examine possible collisions with your routes.
You have the following Router Middleware
app.use('/', routes);
and then subsequently the following GET route
app.get("/", function(req, res) {
res.send("i am from /get");
});
Depending on the contents of your routes file there could be collisions and the app.get() will never be executed.
You should set your routes up as follows:
app.use('/', routes);
app.use('/users', users);
app.use('/patienten', patienten);
app.use('/form', form);
// If you have a GET inside your 'routes' file
// from above, then this may never get called if
// it also contains a route for GET '/'
app.get("/", function(req, res) {
console.log('I am from get');
return res.render('index');
});
// My comment from above about your GET '/' would
// also apply to this POST route
app.post('/', function(req, res){
var username=req.body.username;
var password=req.body.password;
return res.status(200).send("the username and password you posted: " + password + ' ' + username);
});
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
return next(err);
});
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
return res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
return res.render('error', {
message: err.message,
error: {}
});
});
You'll also need to change your HTTP Method specified in your form.ejs file from GET to POST
<form action="/" method="POST">

Nodejs and Expressjs print session out on site

Hello i am trying to do a simple log in system without(password) in nodejs and expressjs, using sessions. My problem is that when I try to print the log in name on to the next page it dosent come out.
login html:
<form method="post">
<label for="">UserName:</label>
<input type="text" name="username" placeholder="Enter username" >
<input type="Submit" value="Submit">
</form>
main.html:
<h3> Welcome: <%= user %> </h3>
index.js:
var express = require('express');
var jokes = require('../model/jokes');
var session = require("express-session")
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res) {
res.render('main', { title: 'Express', user: session.loggedin });
})
router.get('/login',function(req,res){
res.render('login');
})
router.get('/joke', function(req,res){
res.render('randomJoke',{ jokesObj : jokes.getRandomJoke()});
})
router.get('/allJokes', function(req,res){
res.render('Jokes',{ jokesObj1: jokes.allJokes});
})
router.get('/addNewJoke', function(req,res){
res.render('addJokes');
})
router.post('/storeJoke', function(req,res){
var funJoke = req.body;
var jsonJoke = JSON.stringify(funJoke);
jokes.addJoke(jsonJoke);
res.redirect('/addNewJoke');
})
module.exports = router;
app.js
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var session = require("express-session");
var routes = require('./routes/index');
var users = require('./routes/users');
var app = express();
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(session({secret:'secret_3162735',saveUninitialized:true, resave: true}));
app.use('/', routes);
app.use('/users', users);
app.use(function (req,res,next) {
var usernameLogged = req.session.loggedin;
var inputName = req.body.username;
if(usernameLogged){
return next();.
}else if(inputName){
usernameLogged = inputName;
session.userName = req.body.username;
return res.redirect("/");
}else{
req.url = "/login";
return next();
}
});
// error handlers
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
module.exports = app;
So in main.html i cant se the user, i tried to print the session(usernameLogged) out in my main.html does not work.
As far as I can see it looks like your using middleware in a way it's not really supposed to be used. Middleware in Express is normally used to do an action for every (or a sub-section) of requests e.g logging, setting custom headers and so on, you can read more about Express-middleware from the documentation.
You need to have a route to respond to POST requests (which your login form should send):
Firstly, your login template needs to send the form input to /login like so:
<form method="post" action="/login">
<label for="">UserName:</label>
<input type="text" name="username" placeholder="Enter username" >
<input type="Submit" value="Submit">
</form>
To display the form you have a route like so to simply render the login template:
router.get('/login', function(req, res) {
// Show the login form
res.render('login');
})
Finally, you should have a route to accept the user-input from the form. As the form sends a POST request, you need to use router.post:
router.post('/login', function(req, res) {
if (req.session.loggedin) {
// User is already logged in, send them to the main page
return res.redirect('/')
}
else if (req.body.username) {
// User is not logged in, set the username for the user's session
req.session.userName = req.body.username;
// Then redirect to the main page
return res.redirect('/')
}
else {
// No username was entered
res.send('Please enter a username')
}
})
And finally,
You then should be safe to delete your middleware (the app.use section) of your app.js file.
Edit:
A user correctly spotted that questions (and answers) were using session rather than using req.session - Session refers to the express-session module, whereas req.session refers to the user's session.
So your '/' route should look like this:
res.render('main', { title: 'Express', user: req.session.loggedin });
If you want to show if the user is logged in or not.
Or you can do the following to show the current user's username.
res.render('main', { title: 'Express', user: req.session.userName });

ejs template not rendering properly

I am trying to replicate a tutorial on using passport to create user authentication.
whenever i try including the below snippet in signup.ejs:
<% if (message.length > 0) { %>
<div class="alert alert-danger"><%= message %></div>
<% } %>
it throws error and as soon as i remove this from signup.ejs, it renders.
below is my app.js(includes all the configurations), index.js(routing part), signup.ejs and passport.js(link to this file is mentioned)
app.js
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var routes = require('./routes/index');
var users = require('./routes/users');
var app = express();
var mongoose = require("mongoose");
var passport = require('passport');
var flash = require('connect-flash');
var session = require('express-session');
mongoose.connect("mongodb://jer:jer#ds061611.mongolab.com:61611/passport1");
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
require('./config/passport')(passport);
app.use(logger('dev'));
app.use(cookieParser());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static(path.join(__dirname, 'public')));
// required for passport
app.use(session({ secret: 'zxcv' })); // session secret
app.use(passport.initialize());
app.use(passport.session()); // persistent login sessions
app.use(flash()); // use connect-flash for flash messages stored in session
app.use('/', routes);
app.use('/users', users);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
app.listen(8000);
module.exports = app;
index.js
var express = require('express');
var router = express.Router();
var passport = require('passport');
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index.ejs', { title: 'Express' });
});
router.get('/signup', function(req, res) {
// render the page and pass in any flash data if it exists
res.render('signup.ejs');
});
// process the signup form
console.log("entering signup");
router.post('/signup', passport.authenticate('local-signup', {
successRedirect : '/profile', // redirect to the secure profile section
failureRedirect : '/signup', // redirect back to the signup page if there is an error
failureFlash : true // allow flash messages
}));
router.get('/profile', isLoggedIn, function(req, res) {
console.log("going to profile page.................................................................");
res.render('profile.ejs', {
user : req.user // get the user out of session and pass to template
});
});
function isLoggedIn(req, res, next) {
// if user is authenticated in the session, carry on
if (req.isAuthenticated())
return next();
// if they aren't redirect them to the home page
res.redirect('/');
}
module.exports = router;
signup.ejs
<!doctype html>
<html>
<head>
<title>Node Authentication</title>
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap.min.css"> <!-- load bootstrap css -->
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css"> <!-- load fontawesome -->
<style>
body { padding-top:80px; }
</style>
</head>
<body>
<div class="container">
<div class="col-sm-6 col-sm-offset-3">
<h1><span class="fa fa-sign-in"></span> Signup</h1>
<% if (message.length > 0) { %>
<div class="alert alert-danger"><%= message %></div>
<% } %>
<!-- LOGIN FORM -->
<form action="/signup" method="post">
<div class="form-group">
<label>Email</label>
<input type="text" class="form-control" name="email">
</div>
<div class="form-group">
<label>Password</label>
<input type="password" class="form-control" name="password">
</div>
<button type="submit" class="btn btn-warning btn-lg">Signup</button>
</form>
<hr>
</div>
</div>
</body>
</html>
passport.js (at below link:)
https://scotch.io/tutorials/easy-node-authentication-setup-and-local
Any help would really help me in completing this tutorial.
Thanks in advance.
Finally, digged out the fault...... was a very simple and basic error.Happy i did not waste other's time...
error: i was not passing the variable into the template while rendering.
codeChange:
in index.js for the /signup path
res.render('signup.ejs'); changes to res.render('signup.ejs',{message:'errorMessage'});

Resources