I would like to pass the session object to all my views so i don't have to pass them manually in each routes.
In the book i used to learn nodejs there was an example but for express 2 :
//session routes
module.exports = function(app){
app.dynamicHelpers({
session: function(req, res){
return req.session;
}
});
app.get(......
res.render(....
....
}
So dynamicHelpers have been replaced. I found something on stackoverflow :
app.use(function(req, res, next){
res.locals.session = req.session;
next();
});
I found also on express docs
app.use(function(req, res, next){
app.locals.session = req.session;
next();
});
Anyway, in my view i have something like <%=session.user%> and somewhere in my route i do req.session.user = "John" and i always get 500 internal error : session not defined.
Any thoughts ?
I figured it out. The problem is that the res.locals has to be set before the app.router in the app.js file (not in routes files) !
By setting my app.js file like this :
app.use(express.cookieParser(hash));
app.use(express.session({
secret: hash,
maxAge: 3600000
}));
app.use(function(req, res, next){
res.locals.session = req.session;
next();
});
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
I don't even need to touch my routes files to send out the session object. In my view i can just use <%=session.whatever%> and it will be displayed (as only if I already set up that session variable in some of my route for ie after a login).
Related
I am trying to allow users to save and download static files. But have the files be accessible only for logged in (authorized) users.
routes/files.js
var express = require('express');
var router = express.Router();
/* Get files */
router.get('/*', isLoggedIn, function(req, res, next) {
console.log('get files called ');
express.static(path.join(__dirname, 'files'));
});
function isLoggedIn(req, res, next){
if(req.isAuthenticated()) return next();
res.redirect('/');
}
module.exports = router;
This works with any get request but not static files. They can be accessed with out being logged in.
app.js
var filesRouter = require('./routes/files');
app.use(express.static(__dirname));
app.use('/files', filesRouter);
I must be missing something simple - Thanks!!
Calling express.static(path.join(__dirname, 'files')); just returns a middleware function. It doesn't actually execute anything more than that. It doesn't serve any files until you call the function that it returns. You could get that middleware function once and then execute it conditionally, but it's easier to just do this:
/* Get files */
router.get('/*', isLoggedIn, express.static(path.join(__dirname, 'files')));
You should use express.static as a middleware.
And then to only allow authenticated users to access files, you coulld register isLoggedIn middleware before it. Please , see the code bellow, this should work.
var express = require('express');
var router = express.Router();
router.use(isLoggedIn); // this must come before express.static
router.use(express.static(path.join(__dirname, 'files')));
/* Get files */
router.get('/*', function(req, res, next) {
console.log('get files called ');
});
function isLoggedIn(req, res, next){
if(req.isAuthenticated()) return next();
res.redirect('/');
}
module.exports = router;
I want to add a login feature to this web app https://github.com/squallooo/MT5 and protect the '/' route by adding isAuthenticated using passport.js, but no luck. I even deleted the index route to see what happens, but the index view still shows, thus I think I'm modifying the wrong code? Could anyone give me the tips where I need to modify the code in this case? I want the users to be redirected to the '/login' route when accessing '/' route.
my /config/auth file.
module.exports = {
ensureAuthenticated: function(req, res, next){
if(req.isAuthenticated()){
return next();
}
req.flash('error_msg', 'Please login to view this resource');
res.redirect('/login');
}
}
my index route
// Passport, Session
var session = require('express-session');
var passport = require('passport');
// session config
app.use(session({
secret: "secret",
saveUninitialized: true,
resave: true
}));
// Passport
app.use(passport.initialize());
app.use(passport.session());
var { ensureAuthenticated } = require('./config/auth');
// I want to protect the routing by adding 'ensureAuthenticated'
app.get('/', ensureAuthenticated, function (req, res) {
res.sendfile(__dirname + '/index.html');
});
I think I have found a temporary answer. For some reason, app.get('/', ...) route was not working. When I installed ejs (template engine) and then app.get('/', ...) route is working. I am able to protect this route from non-authenticated users now.
i have a some problem
i'm using express-session middleware in my app
it work
but
It did not work on any particular router.
my code is follows
//app.js
app.use(session({
secret: 'D$YTRH#%#$#^$#YR',
resave: false,
saveUninitialized: true,
}))
//assign session in outside
app.get(/*, (req, res, next)=>{
req.session.outSide = "outSideBlah"
next()
}
//my session Check middleware
app.get('/*', (req, res, next)=>{
console.log(req.session._inSide)
console.log(req.session._outSide)
next()
}
const auth = require('./routes/auth.js')(express)
app.use('/auth', auth)
//auth.js (my router)
//assign session in router ( inside)
module.exports = (express) => {
const auth = express.Router()
auth.post('/login', (req, res)=>{
req.session._inside = 'insideBlah' //Assign a session here
............some auth code ......
}
return auth
}
after login
in my session Check middleware
console.log(req.session.inSide) // undefined
console.log(req.session.outSide) // "outSideBlah"
Even though I assigned req.session.inSide in auth.js
req.session.inside is undefined
What is the problem?
Why can not I access a session assigned by my router (auth.js)?
somebody help me.. thank you...
Also I think you should use * instead of /*.
I have the following in app.js:
app.use(express.static(path.join(__dirname, 'public')));
app.use(function(req, res, next) {
console.log('app.use');
...
next();
});
app.use(app.router);
public folder have subfolder images, css and js.
After app.use(app.router);, I have route definition for returning an image from Amazon S3.
app.get('/images/:type/:id', image);
The problem is that when a page contain image, app.use was called twice. How to prevent it? I want to ignore /images/* calling app.use(function(req, res, next) {});
In general Express uses middleware connect architecture. Every middleware accepts next function which if is called passes the flow to the next middleware. So, in theory if you miss it you could archive what you want:
app.use(function(req, res, next) {
// check if the route matches amazon file
if(...amazon file...) {
// serve image
} else {
next();
}
});
app.use(express.static(path.join(__dirname, 'public')));
I have the usual middleware stack for my app:
app.configure(function() {
app.use(express.static(PUBLIC_DIR));
app.use(express.favicon());
app.use(express.bodyParser({
keepExtensions: true,
uploadDir: '/tmp/neighr'
}));
app.use(express.methodOverride());
app.use(express.cookieParser());
app.use(express.session({
secret: '***REDACTED***',
store: sessionStore,
}));
app.use(express.csrf());
app.use((require('connect-flash'))());
app.use(passport.initialize());
app.use(passport.session());
app.use(function(req, res, next) {
app.locals({
_csrf: req.session._csrf,
url: req.url,
user: req.user,
authenticated: req.isAuthenticated(),
messages: {
info: req.flash('info'),
error: req.flash('error'),
success: req.flash('success')
}
});
next();
});
app.use(app.router);
app.use(express.logger());
app.use(express.errorHandler());
});
As you can see, the express.static is one of the first in the stack, so that static resources will be served without going through the entire session stuff which only makes loading times longer.
I do have, however, some dynamic data I'd like to serve without all the session stuff:
app.get('/avatar/:id', function(req, res) {
var fid = res.params.id;
/* load binary from database */
res.send(data);
});
This route is within app.router, at the end of the stack. I would like to keep the way to declare this and other routes, but how can I get express to parse these before the session middleware?
There might be more such dynamic routes in the future, with more parameters.
Once you declare a route, Express inserts the router middleware into the middleware stack at that point, so if you were to declare a single route before loading the session middleware, all route requests would skip the session middleware:
app.get('/one', ...); // inserts `app.router` into the stack at this point
app.use(express.session(...));
app.get('/two', ...); // will skip the session middleware
There's two solutions I can think of: create your own middleware to handle the requests which shouldn't be passed through the session middleware, or explicitly set the session middleware for each route you want to run through it.
First solution:
app.use(function(req, res, next) {
if (req.path.indexOf('/avatar/') === 0) {
// parse out the `id` and return a response
}
next();
});
This obviously isn't very flexible.
Second solution:
// instantiate the session middleware:
var sessionMiddleware = express.session(...);
// default setup: insert the router before the session middleware:
app.use(app.router);
app.use(sessionMiddleware);
// Pass it explicitly to the route:
app.get('/two', sessionMiddleware, function(req, res) {
...
});
In your situation, where you also use Passport, you might want an array of middleware:
var authMiddleware = [
express.session(...),
passport.initialize(),
passport.session()
];
app.get('/two', authMiddleware, ...);
Looking at how Express is implemented, I don't think it's possible to instantiate a second router (and get it to function properly).