I'm trying to access session variables in EJS views, but facing lots of problems.
To access the req.session locally I'm using middleware as described here Accessing Express.js req or session from Jade template
var express = require('express');
var mongoose = require('mongoose');
var db = require('./models/db.js');
var routes = require('./routes/route.js');
var user = require('./routes/user.js');
var story = require('./routes/story.js');
var bodyParser = require('body-parser');
var session = require('express-session');
var cookieParser = require('cookie-parser');
mongoose.connect('mongodb://localhost/test');
var app = express();
app.use(function(req,res,next){
res.locals.session = req.session;
next();
});
app.set('view engine','ejs');
app.use(express.static(__dirname + '/public'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended:false}));
app.use(cookieParser());
app.use(session({secret:"qazwsxedcrfvtgbyhnujm"}));
app.get('/',routes.home);
app.get('/register',routes.register);
app.post('/newUser',user.doCreate);
app.get('/login',routes.login);
app.post('/authenticate',user.login);
app.get('/new-story',routes.newStory);
app.post('/add-story',story.addStory);
app.get('/stories/:story',story.getStory);
app.post('/stories/:slug/saveComment',story.saveComment);
var port = process.env.PORT || 3000;
var server=app.listen(port,function(req,res){
console.log("Catch the action at http://localhost:"+port);
});
Here is the route.js for handling home route
var mongoose = require( 'mongoose' );
var Story = mongoose.model( 'Story' );
exports.home=function(req,res){
Story.find({}, function(err,stories){
res.render('home',{stories:stories});
});
}
In the home.ejs I am checking whether user is logged in or note by checking whether username property is set or not.
<% if( typeof(session.username) !== 'undefined' ) {%
<h1>Welcome</h1><%=session.username%>
<%}%>
But, on accessing the main page I get error saying
Cannot read property 'username' of undefined error
I am setting the username in session once is user is authenticated.
exports.login=function(req,res){
var email=req.body.email;
var password=req.body.password;
User.findOne({email:email}, function(err,user){
if(err){
res.redirect("/login");
}
user.comparePassword(password,function(err,isMatch){
if(isMatch && isMatch==true){
console.log("Authentication Sucessfull");
req.session.username=user.username;
console.log("Got USer : "+req.session.username);
res.redirect("/");
}else{
console.log("Authentication UnSucessfull");
res.redirect("/login");
}
});
});
}
Express runs middleware in order of their declaration.
You have this:
app.use(function(req,res,next){
res.locals.session = req.session;
next();
});
...
app.use(session({secret:"qazwsxedcrfvtgbyhnujm"}));
Your middleware runs before the session middleware (it's declared before it), so you create res.locals.session before the session middleware gets a chance to create req.session.
Try moving your middleware to after the session middleware:
app.use(session({secret:"qazwsxedcrfvtgbyhnujm"}));
app.use(function(req,res,next){
res.locals.session = req.session;
next();
});
Related
I am trying to run a query in a view (.ejs file). However, since the keyword require is not defined in a .ejs file, I need to export it from my main file, server.js.
The whole code for my server.js file is below and this is the specific snippet with which I need help.
app.engine('html', require('ejs').renderFile);
exports.profile = function(req, res) {
res.render('profile', { mysql: mysql });
}
I need to be able to use the mysql.createConnection in my profile.ejs file.
Any help would be great.
// server.js
// set up ======================================================================
// get all the tools we need
var express = require('express');
var app = express();
var port = process.env.PORT || 8080;
var mongoose = require('mongoose');
var passport = require('passport');
var flash = require('connect-flash');
var morgan = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var session = require('express-session');
var configDB = require('./config/database.js');
var Connection = require('tedious').Connection;
var config = {
userName: 'DESKTOP-S6CM9A9\\Yash',
password: '',
server: 'DESKTOP-S6CM9A9\\SQLEXPRESS',
};
var Request = require('tedious').Request;
var TYPES = require('tedious').TYPES;
var mysql = require('mysql');
var con = mysql.createConnection({
host: "localhost",
user: "root",
password: "yashm"
});
con.connect(function(err) {
if (err) throw err;
console.log("Connected!");
var sql="Select * from test.productlist";
con.query(sql, function (err, result) {
if (err) throw err;
console.log(result);
});
});
app.engine('html', require('ejs').renderFile);
exports.profile = function(req, res) {
res.render('profile', { mysql: mysql });
}
//--------------------------------------------------------------------------------
// configuration ===============================================================
mongoose.connect(configDB.url); // connect to our database
require('./config/passport')(passport); // pass passport for configuration
// set up our express application
app.use(morgan('dev')); // log every request to the console
app.use(cookieParser()); // read cookies (needed for auth)
app.use(bodyParser()); // get information from html forms
app.set('view engine', 'ejs'); // set up ejs for templating
// required for passport
app.use(session({ secret: 'test run' })); // 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
// routes ======================================================================
require('./app/routes.js')(app, passport); // load our routes and pass in our app and fully configured passport
// launch ======================================================================
app.listen(port);
console.log('The magic happens on port ' + port);
Like already said in the comment, you have to do your query logic in your server.js and then pass the data to your view (or maybe even pre-process it!)
exports.profile = function(req, res) {
con.query('SELECT 1', function (error, results, fields) {
if (error) throw error;
// connected!
res.render('profile', { data: results });
});
}
In your ejs you can loop trough the data, and acces the fields as data[i]['fieldname']
<ul>
<% for(var i=0; i<data.length; i++) {%>
<li><%= data[i]['id'] %></li>
<% } %>
</ul>
I have a simple server application running with NodeJS, and I tried to implement the route protecting that is in this tutorial, I already have the token that works every time I login.
So this middleware should be called to all routes except register and login. So I did this in my initial setup:
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 debug = require('debug')('express-sequelize');
var http = require('http');
var models = require('./models');
var jwt = require('jsonwebtoken');
var jwtPermission = require('./controller/jwtPermission');
var fotos = require('./routes/fotos');
var app = express();
var router = express.Router();
// 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('/',require('./routes/index'));
app.use(jwtPermission);
app.use('/fotos',fotos);
The middleware that doesn't get called is jwtPermission. So I have a routes folder where I have a index, and the authentication file(that has login and register). For the jwtPermission I just have the controller set as you guys can see.
I have a console.log inside that controller but it never gets called.
jwtPermission
var jwt = require('jsonwebtoken');
var jwtConfig = require('../config/jwt');
module.exports = function(req, res, next) {
console.log("entered");
// check header or url parameters or post parameters for token
var token = req.body.token || req.query.token || req.headers['x-access-token'];
console.log(req.headers['x-access-token']);
// decode token
if (token) {
// verifies secret and checks exp
jwt.verify(token,jwtConfig.secret, function (err, decoded) {
if (err) {
return res.json({ success: false, message: 'Failed to authenticate token.' });
} else {
// if everything is good, save to request for use in other routes
req.decoded = decoded;
next();
}
});
} else {
// if there is no token
// return an error
return res.status(403).send({
success: false,
message: 'No token provided.'
});
}
}
You configure your routes in the Route object, but you have to attach it in your app object.
So, in this case, change route.use to app.use.
Don't need to use the route object.
I'm having a small problem when building a CRUD Api with node.js and express.
When I post to my API I get "ReferenceError: Phone is not defined"
// server.js
// BASE SETUP
// =============================================================================
// call the packages we need
var express = require('express'); // call express
var app = express(); // define our app using express
var bodyParser = require('body-parser');
var phone = require('./models/phone');
var mongoose = require('mongoose');
mongoose.connect('mongodb://<userID>:<pass>#apollo.modulusmongo.net:27017/ugygY5qe');
// configure app to use bodyParser()
// this will let us get the data from a POST
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
var port = process.env.PORT || 8080; // set our port
// ROUTES FOR OUR API
// =============================================================================
var router = express.Router(); // get an instance of the express Router
router.use(function(req,res,next){
console.log('Something is happening');
next();
});
router.route('/phones').post(function(req, res){
var phone = new Phone();
phone.name = req.body.name;
phone.save(function(err){
if(err){
res.send(err);
}
res.json({message: 'Phone Create'});
});
});
// test route to make sure everything is working (accessed at GET http://localhost:8080/api)
router.get('/', function(req, res) {
res.json({ message: 'hooray! welcome to our api!' });
});
// more routes for our API will happen here
// REGISTER OUR ROUTES -------------------------------
// all of our routes will be prefixed with /api
app.use('/api', router);
// START THE SERVER
// =============================================================================
app.listen(port);
console.log('Magic happens on port ' + port);
And here is my schema file.
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var phoneSchema = new Schema({
name: String
});
module.exports = mongoose.model('Phone', phoneSchema);
I'm not sure where the error is. I've consulted the mongoose docs, search around but still can't get anything to work.
Just a typo ! check line no 4.
var Phone = require('./models/phone');
I'm working through a basic node tutorial and am having difficulty getting my routes.js file to work.
It was working earlier today. The server Node is reading the file. For some reason, though it is not utilizing it. My code looks exactly like the tutorial -- though the teacher is on a PC and I am on a Mac (though I can't see why that would matter).
Before this issue started to occur, I hooked up my database (file below) -- but again, I can't see why that would screw with my routes. When I put this code in server.js, I can get the proper routing.
Help me stackoverflow, you're my only hope! All I see is "Cannot GET /"
My routes.js file
var User = require('../models/user');
module.exports = function(app){
app.get('/', function(req, res){
res.send("Hello World");
});
// app.get('/:username/:password', function(req, res){
// var newUser = new User();
// newUser.local.username = req.params.username;
// newUser.local.password = req.params.password;
// console.log(newUser.local.username + " " + newUser.local.password);
// newUser.save(function(err){
// if(err)
// throw err;
// });
// res.send('Success!')
// });
};
server.js
var express = require('express');
var app = express();
var port = process.env.PORT || 8080;
var cookieParser = require('cookie-parser');
var session = require('express-session');
var morgan = require('morgan');
var mongoose = require('mongoose');
//Config Database
var configDB = require('./config/database.js');
mongoose.connect(configDB.url);
//MIDDLEWARE is run during every interaction;
app.use(morgan('dev'));
//sets req.cookies
app.use(cookieParser());
app.use(session({
//secret for user session
secret: "ist0",
//if the server goes down, the user can remain logged on -- still save to database
saveUninitialized: true,
//even if nothing has changed, resave
resave: true
}));
//ROUTES
require('./app/routes/routes');
// app.use('/', function(req, res){
// //send is express function
// res.send("Our first express program");
// console.log(req.cookies);
// console.log("============");
// console.log(req.session);
// });
app.listen(port);
console.log('The magic happens on ' + port)
My database.js file:
module.exports = {
'url': 'mongodb://localhost/meanboil'
}
You are exporting a function (one that expects app as an argument):
module.exports = function(app) { ... }
But you're just importing that function and don't actually call it:
require('./app/routes/routes');
Instead, you need to call it and pass app as argument:
require('./app/routes/routes')(app);
I have been staring at the same SO questions/answers for too long.
I am trying to set my user ID in a req.session variable
here is my app.js stack
/**
* Module dependencies.
*/
var express = require('express')
, routes = require('./routes')
, cors = require('cors')
, mongoose = require('mongoose')
, User = require('./user-model')
, path = require('path')
, mysql = require('mysql');
app = express()
/**
* Middleware.
*/
app.use(cors());
app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.session({ secret: 'supercalafragalistic' }));
app.locals.pretty = true;
app.use(express.static(path.join(__dirname, 'public')));
app.set('view engine', 'jade');
...
app.get('/someRoute', routes.someRoute)
I have moved the app.router from top to bottom. Currently it is implied (I just deleted it as I stripped my code looking for error). I have exported app, included app in routes (also erased) . I added middleware. I am lost.....
here is my route stack
//routes/index.js
//requires
var User = require('../user-model')
,qs = require('querystring')
,http = require('http')
,mysql = require('mysql')
,connection = mysql.createConnection({
edited
});
/**
* Set up application.
*/
connection.connect(function(err){
if(err) console.log('failed to connect to mysql because'+ err);
else console.log('connected to mysql');
})
I save the id in the login route:
//login processing route
exports.logIn = function(req, res, next){
console.log('log in request from '+req.body.name);
User.findOne({name:req.body.name}, function(err, user, next){
if(err) return next(err);
if(!user) return res.end();
//check password
user.comparePassword(req.body.password, function(err, isMatch){
if(err) res.send('failed to find user');
console.log(""+isMatch);
if(isMatch){
console.log(user._id.toString()+' user loggd in');
//set session cookie
req.session.loggedIn = user._id.toString();
console.log('req.session.loggedIn set to :'+req.session.loggedIn );
res.send(user);
}else {
res.send('User not found try again');
}
});
});
However, in all other routes the variable is undefined:
// clock status
exports.clockStatus = function(req, res, next){
var user = req.session.loggedIn;
console.log('Status route, userID: '+user);
if(user){
I found the answer in "Cannot access req.session variables in Express/NodeJS" but the last part trails off:
In your case, you have assigned req.session.user = user; only in
/login request. It will not be available for further requests(/auth).
You have to get user information in /auth request too by session id.
(Or) Better you can use passport for authentication.
HOW? How do you "get user information in /auth request too by session id"?
Please ask for anything else you need to straighten me out.
I'm stumped. I have tried some dumb stuff already!
The variable is undefined in other routes if you don't log in first in the browser. Here is my test code:
var express = require('express');
var cors = require('cors');
app = express();
app.use(cors());
app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.session({ secret: 'this is a test' }));
app.use(express.static(require('path').join(__dirname, 'public')));
app.get('/login', function(req, res) {
req.session.uid = 'user001';
res.send(req.session);
});
app.get('*', function(req, res) {
res.send(req.session);
});
app.listen(8080);
First visit http://localhost/login in the browser. Then visit other URLs(e.g., http://localhost/test) in this browser, the user id in the session is returned. So maybe there is something wrong in other parts of your code.
Test settings:
Ubuntu Desktop 13.10, 64 bit
Node 0.10.26
NPM 1.4.4
Express 3.4.8
cors 2.2.0