nodejs express.router with parameters - node.js

Problem
I am using a nodejs application with the express module. To have a structure I split the routes into a extern routes.js. I want give this route.js next to the req and res parameters some other parameters who will be needed. But I donĀ“t know how I can do it.
Index.js
const app = express();
app.use(session({
secret: uuidv4(),
resave: true,
saveUninitialized: true
}));
app.use(helmet());
app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
}));
app.use('/', express.static(path.join(__dirname, '/site/static')));
app.use('/', routes);
routes.js
module.exports = (function() {
'use strict';
let router = require('express').Router();
router.get('/', (req, res) => {
if(!req.session || req.session.key !== loginkey) {
res.redirect('/login');
} else {
res.redirect('dashboard');
};
});
router.get('/dashboard', (req, res) => {
if(req.session && req.session.key === loginkey) {
helper.render(req, res, "sites/dashboard");
} else {
res.redirect('/');
};
});
router.get('/login', (req, res) => {
log.LogLine(3, "GET /login");
helper.render(req, res, "sites/login");
});
router.get('/logout', (req, res, next) => {
log.LogLine(3, "GET /logout");
if (req.session) {
req.session.destroy(function(err) {
if(err) {
return next(err);
} else {
return res.redirect('/');
};
});
};
});
return router;
})();

If you want to pass something along from index.js to your routes in routes.js then you can do the following.
In your routes.js, you could accept some parameters:
module.exports = function(arg1, arg2) {
let router = require('express').Router();
router.get('/', (req, res) => {
// You can now use arg1 and arg2 here
});
// ...
return router;
};
Note, you'll need to remove your IIFE to stop the function from being immediately invoked.
Then in index.js, you can invoke the function and pass in whatever you want:
app.use('/', routes('something', 'something else'));
I hope this helps.

Related

error 404 while authenticating with passport js local

Really stuck on the same issue for much time. Tried many things but all to no use. Please help.
The register module works fine but the login doesn't. It returns 404 error upon hitting submit button. Attached are the appropriate code documents.
The login module is supposed to redirect to contactlist upon successful authentication.
Thank you very much!.
app.js
let createError = require('http-errors');
let express = require('express');
let path = require('path');
let cookieParser = require('cookie-parser');
let logger = require('morgan');
var bodyParser = require('body-parser');
let Login = require('../models/login')
let passport = require('passport');
let LocalStrategy = require('passport-local').Strategy;
passport.use(new LocalStrategy(
function(username, password, done) {
User.findOne({ username: username }, function (err, user) {
if (err) { return done(err); }
if (!user) { return done(null, false); }
if (!user.verifyPassword(password)) { return done(null, false); }
return done(null, user);
});
}
));
//database setup
let mongoose = require('mongoose');
let DB = require('./db');
//point mongoose to the db URI
mongoose.connect(DB.URI);
let mongoDB = mongoose.connection;
mongoDB.on('error',console.error.bind(console,'Connection Error in Mongo'));
mongoDB.once('open',()=>{
console.log("Connected to MongoDB");
})
let indexRouter = require('../routes/index');
let usersRouter = require('../routes/users');
let loginRouter = require('../routes/login');
let authRouter = require('../routes/auth');
const exp = require('constants');
let app = express();
// view engine setup
app.set('views', path.join(__dirname, '../views'));
app.set('view engine', 'ejs');
app.use(bodyParser.json());
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(require('express-session')({
secret: 'keyboard cat',
resave: false,
saveUninitialized: false
}));
app.use(express.static(path.join(__dirname, '../../public')));
app.use(express.static(path.join(__dirname,'../../node_modules')));
app.use(passport.initialize());
app.use(passport.session());
app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/login', loginRouter);
app.use('/', authRouter);
// passport config
passport.serializeUser(Login.serializeUser());
passport.deserializeUser(Login.deserializeUser());
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// 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',{ title: 'error' });
});
module.exports = app;
auth.js
let express = require('express');
let router = express.Router();
let passport = require('passport');
let user = require('../models/user');
router.post('/register',(req,res,next)=>{
user.register(new user({
username:req.body.username,
}),
req.body.password,(err, newUser) =>{
if(err){
return res.redirect('/login/register')
}
else{
req.login(newUser,(err) => {
res.redirect('/login/contactlist')
})
}
}
)
});
router.post('/', passport.authenticate('local', { failureRedirect: '/login/contactlist' }),
function(req, res) {
res.redirect('/login/contactlist');
});
module.exports = router;
login.js
let express = require('express');
let router = express.Router();
let passport = require('passport');
/* GET index page. */
let Login = require('../models/login')
let Contact = require('../models/contact')
router.get('/', function(req, res, next) {
Login.find((err,loginList)=>{
if(err){
return console.error(err);
}
else {
//console.log(loginList);
res.render('login/login', { title: 'Login',loginList: loginList,user: req.user });
}
});
});
router.get('/register', function(req, res, next) {
res.render('login/register')
});
/* GET contactlist page. */
router.get('/contactlist', function(req, res, next) {
Contact.find((err,contactList)=>{
if(err){
return console.error(err);
}
else {
res.render('login/contactlist', { title: 'contactlist',contactList: contactList });
}
});
});
/* GET update page. */
router.get('/update/:id', function(req, res, next) {
let id = req.params.id;
Contact.findById(id, (err, contactToEdit) => {
if(err)
{
console.log(err);
res.end(err);
}
else
{
//show the edit view
res.render('login/update', {title: 'Update', contact:contactToEdit })
}
});
});
router.get('/delete/:id', function(req, res, next) {
let id = req.params.id;
Contact.remove({_id: id}, (err) => {
if(err)
{
console.log(err);
res.end(err);
}
else
{
// refresh the contacts list
res.redirect('/login/contactlist');
}
});
});
/* POST update page. */
router.post('/update/:id', function(req, res, next) {
let id = req.params.id
let newContact = Contact({
"_id":id,
"email":req.body.email,
"number": req.body.number,
"name":req.body.name
});
Contact.updateOne({_id: id},newContact,(err)=>{
console.log(newContact);
if(err){
console.log(err);
res.end(err);
}
else{
console.log(id)
console.log("POST update");
res.redirect('/login');
}
});
});
/* POST contactlist page. */
router.post('/contactlist', function(req, res, next) {
res.render('login/contactlist', { title: 'contactlist' });
});
module.exports = router;

Node.js - Why checkAuthenticated middleware function cannot be exported from another file?

I have a node.js app that uses express, handlebars and passport.js for authentication. I have setup a routes folder for login
app.js
app.use('/login', require('./routes/login'));
routes/ login.js
const checkAuthenticated = (req, res, next) => {
if (req.isAuthenticated()) {
return res.redirect("/");
}
next();
};
router.get("/", checkAuthenticated, (req, res) => {
res.render("login");
});
module.exports = router;
This works fine.
However, if I put the checkAuthenticated middleware function in app.js then export and require it in login.js I get this error.
router.get() requires callback
app.js
app.use('/login', require('./routes/login.js'));
const checkAuthenticated = (req, res, next) => {
if (req.isAuthenticated()) {
return res.redirect("/");
}
next();
};
module.exports = { checkAuthenticated };
routes/login.js
const { checkAuthenticated } = require('../app.js');
router.get("/", checkAuthenticated, (req, res) => {
res.render("login");
});
module.exports = router;
Why doesn't it work when this function is required from another file like a normal function? I am trying to avoid duplication as I need exact same function for routes/register.js

apply authenicate method on all routers in express

I'm very new to node.
I want to apply custom authentication using passport.js to all router.
using this example. -> https://github.com/passport/express-4.x-http-bearer-example
the code below is my server/index.js.
const express = require('express');
const path = require('path');
const index = require('./routes/index.js');
const downloadRouter = require('./routes/fileDownload.js');
const app = express();
app.disable("x-powered-by");
app.use('/', express.static(path.join(__dirname, '..', 'dist')));
app.set("src", path.join(__dirname, "../src"));
var passport = require('passport');
var Strategy = require('passport-http-bearer').Strategy;
var db = require('./adminDB');
passport.use(new Strategy(
function(token, cb) {
db.users.findByToken(token, function(err, user) {
if (err) { return cb(err); }
if (!user) { return cb(null, false); }
return cb(null, user);
});
}));
// app.use('/api-test', passport.authenticate('bearer', { session: false
}), function(req, res) {
// res.json({ username: req.user.username, value:
req.user.emails[0].value });
// res.end();
// });
app.use('*', passport.authenticate('bearer', { session: false }),
function(req, res, next) {
console.log("api all before action")
if(!err) {
next();
} else {
res.status(401).end();
}
});
app.use('/download', downloadRouter);
const { PORT = 8080 } = process.env;
app.listen(PORT, () => console.log(`Listening on port ${PORT}`));
// export default app;
what I want to ask is this part.
The annotated api-test parts handles authenication very well. However, the "app.use(*)" part does not handle it. console.log is also not working. Returns 200, regardless of the certification procedure, outputting the original screen(index.html).
How do I authenticate across all my routers and get all of my screens back to their original output?
I leave an answer because there may be someone in a similar situation.
app.use('*', passport.authenticate('bearer', { session: false }), function(req, res, next) {
next();
});
put this code, upper then router code.

Route callbacks not executing but middleware is

So this project was working fine before today, but after a bit of a nooby mistake with git I broke my project, and was unable to recover the commit. After spending some time getting everything fixed, my routes are now broken. My issue is that when calling my API routes now the server hangs for exactly 1 minute, then times out and logs a 404 on the server.
To give some background I'm using this boilerplate. In my debugging process I basically put console.logs everywhere I possibly could, and it looks like all my initialization middleware for express and passport are working fine, and my code is getting to where the routes are defined with no errors.
Middleware with app.use works and all checks out when a request is made, and all console.logs I've put there show fine. The console.logs only stop appearing in the final route definition like in this example:
app.get('/route', function(req, res, next) {
console.log('this never shows');
next();
}, function(req, res, next) {
console.log('this never shows');
})
My actual routes do have a res.send(), this is just an example to show you. All the console.logs I put in the middleware before this route show when the request is made, so it is hanging somewhere in app here.
It's a rather large project, so if you want specific code examples just ask and I'll post it. But I was able to recover all the important files that I had saved somewhere else and I'm pretty sure all my code is back to how it was before now.
edit:
Here is my file with express middleware definitions:
config/express.js
/**
* Module dependencies.
*/
var express = require('express');
var MongoStore = require('connect-mongo')(express);
var flash = require('connect-flash');
var helpers = require('view-helpers');
var swig = require('swig');
var session = require('express-session');
module.exports = function (app, config, passport) {
app.set('showStackError', true);
// should be placed before express.static
app.use(express.compress({
filter: function (req, res) {
return /json|text|javascript|css/.test(res.getHeader('Content-Type'));
},
level: 9
}));
app.use(express.favicon());
app.use(express.static(config.root + '/public'));
app.use('/uploads', express.static(config.root + '/uploads'));
var allowCrossDomain = function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header("Access-Control-Allow-Headers", "Access-Control-Allow-Methods, Access-Control-Allow-Headers, Access-Control-Allow-Origin, Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers");
// intercept OPTIONS method
if ('OPTIONS' == req.method) {
res.status(204).end();
}
else {
next();
}
};
app.use(allowCrossDomain);
// don't use logger for test env
if (process.env.NODE_ENV !== 'test') {
app.use(express.logger('dev'));
}
// set views path, template engine and default layout
app.engine('html', swig.renderFile);
app.set('view engine', 'html');
app.set('views', config.root + '/app/views');
app.set('view cache', process.env.NODE_ENV !== 'development');
app.configure(function () {
// dynamic helpers
// app.use(function(req,res,next){
// req.locals.session = "eeeeeeee";
// next();
// });
// cookieParser should be above session
app.use(express.cookieParser());
// bodyParser should be above methodOverride
app.use(express.bodyParser());
app.use(express.methodOverride());
// express/mongo session storage
app.use(function(req, res, next) {
if(!req.cookies['_ga']) {
next();
}
else {
session({
secret: 'secrettexthere',
saveUninitialized: true,
resave: true,
store: new MongoStore({
url: 'mongodb://localhost/traderdb',
db: 'traderdb',
collection: 'sessions',
auto_reconnect: true
})
})(req, res, next);
}
});
// connect flash for flash messages
app.use(flash());
app.use(function (req, res, next) {
res.locals.session = req.session;
res.locals.req = req;
next();
});
app.use(function(req, res, next) {
if(!req.cookies['_ga']) {
next();
}
else {
passport.initialize()(req, res, next);
}
});
//app.use(helpers('app name'));
//
// use passport session
app.use(function(req, res, next) {
if(!req.cookies['_ga']) {
next();
}
else {
passport.session()(req, res, next);
}
});
// routes should be at the last
app.use(app.router);
// assume "not found" in the error msgs
// is a 404. this is somewhat silly, but
// valid, you can do whatever you like, set
// properties, use instanceof etc.
app.use(function(err, req, res, next) {
// treat as 404
if (~err.message.indexOf('not found')) return next();
// log it
console.error(err.stack);
// error page
res.status(500).render('500', { error: err.stack });
});
// assume 404 since no middleware responded
app.use(function(req, res, next) {
res.status(404).render('404', { url: req.originalUrl, error: 'Not found' })
});
})
}
I also have another file with passport route definitions if you'd like to see that too, but all that is tested and works okay too.
edit 2:
This is my entry point file:
server.js
/**
* Module dependencies.
*/
var express = require('express')
, fs = require('fs')
, passport = require('passport');
/**
* Main application entry file.
* Please note that the order of loading is important.
*/
// Load configurations
// if test env, load example file
var env = process.env.NODE_ENV || 'development'
, config = require('./config/config')[env]
, auth = require('./config/middlewares/authorization')
, mongoose = require('mongoose');
// Bootstrap db connection
mongoose.connect(config.db);
// Bootstrap models
var models_path = __dirname + '/app/models'
fs.readdirSync(models_path).forEach(function (file) {
require(models_path+'/'+file);
});
// bootstrap passport config
require('./config/passport')(passport, config);
var app = express();
// express settings
require('./config/express')(app, config, passport);
// Bootstrap routes
require('./config/routes')(app, passport, auth);
// Start the app by listening on <port>
var port = 3002;
app.listen(port);
console.log('Express app started on port '+port);
// expose app
exports = module.exports = app;
edit 3:
Here are my route definitions:
config/routes.js
var express = require('express');
var path = require('path');
var fileManager = require('express-file-manager');
var mongoose = require('mongoose');
var Session = mongoose.model('Session');
module.exports = function (app, passport, auth) {
var users = require('../app/controllers/users');
var coupons = require('../app/controllers/coupons');
var magazines = require('../app/controllers/magazines');
var zones = require('../app/controllers/zones');
var transactions = require('../app/controllers/transactions');
var favorites = require('../app/controllers/favorites');
var banners = require('../app/controllers/banners');
var reports = require('../app/controllers/reports');
var coverContest = require('../app/controllers/coverContest');
var contactMessage = require('../app/controllers/contactMessage');
app.post('/api/users/login', users.login);
app.post('/api/users/register', users.register);
app.post('/api/users/logout', users.logout);
app.post('/api/users/sendResetEmail', users.sendResetEmail);
app.post('/api/users/changePassword', users.changePassword);
app.post('/api/users/redeemCoupon', isValidAppUser(), users.redeemCoupon);
app.get('/api/users/validate', isLoggedIn(0), function(req, res) {
res.send(req.user);
});
app.post('/api/coupons', coupons.get);
app.post('/api/coupons/import', isLoggedIn(0), coupons.import);
app.post('/api/coupons/remove', isLoggedIn(0), coupons.remove);
app.post('/api/coupons/upload', isLoggedIn(0), coupons.upload);
app.post('/api/transactions', transactions.get);
app.post('/api/allTransactions', isLoggedIn(0), transactions.getAll);
app.post('/api/magazines', magazines.get);
app.post('/api/magazines/import', isLoggedIn(0), magazines.import);
app.post('/api/magazines/remove', isLoggedIn(0), magazines.remove);
app.post('/api/banners', banners.get);
app.post('/api/banners/import', isLoggedIn(0), banners.import);
app.post('/api/banners/remove', isLoggedIn(0), banners.remove);
app.post('/api/favorites', isValidAppUser(), favorites.get);
app.post('/api/favorites/import', isValidAppUser(), favorites.import);
app.post('/api/zones', zones.get);
app.post('/api/zones/add', zones.add);
app.post('/api/zones/addCoupon', zones.addCoupon);
app.post('/api/zones/addMagazine', zones.addMagazine);
app.post('/api/mail/ccSubmit', coverContest.ccSubmit);
app.post('/api/mail/contactSubmit', contactMessage.contactSubmit);
//app.get('/api/reports/siteUsers', reports.siteUsers);
app.get('/auth/facebook', passport.authenticate('facebook', { scope: [ 'email', 'user_about_me'], failureRedirect: '/login' }), users.signin);
app.get('/auth/facebook/callback', passport.authenticate('facebook', { failureRedirect: '/login' }), users.authCallback);
app.get('/auth/github', passport.authenticate('github', { failureRedirect: '/login' }), users.signin);
app.get('/auth/github/callback', passport.authenticate('github', { failureRedirect: '/login' }), users.authCallback);
app.get('/auth/twitter', passport.authenticate('twitter', { failureRedirect: '/login' }), users.signin);
app.get('/auth/twitter/callback', passport.authenticate('twitter', { failureRedirect: '/login' }), users.authCallback);
app.get('/auth/google', passport.authenticate('google', { scope: ['profile', 'email'] }));
app.get('/auth/google/callback', passport.authenticate('google', { failureRedirect: '/', successRedirect: '/main.html' }));
}
function isLoggedIn(secLvl) {
return function(req, res, next) {
if(req.isAuthenticated() && req.user.secLvl <= secLvl && req.user.google.email.includes('#bizpub36.com')) {
return next();
}
res.redirect('https://accounts.google.com/logout');
}
}
function isValidAppUser() {
return function(req, res, next) {
Session.findOne({ sess_id: req.body.sess_id }).exec(function(err, session) {
if(!err && session) {
next();
}
else {
res.end({ status: 'error', message: 'invalid session' });
}
});
}
}
If app.use works, my guess would be your protocol, is the app.get correct? You issue is otherwise located somewhere else in your code base as your sample runs fine as a single route express app.
It sounds like one of three things:
Somewhere in your middleware chain, you are not calling next() to allow it to advance to the next level of handlers and thus the request just eventually times out waiting for that middleware to finish (this seems to match the symptoms you describe).
Somehow, your app.get() doesn't actually match the route you expect it to or is not specified correctly.
You're using a router, but have not configured it correctly.
But, because you don't get an immediate 404, but rather it times out, it is probably option #1 above.

next() omits middleware sub-stack in route.param

In below example for GET /api/users/i request secondMw is never executed even there is a next() call in firstMw. Why is that? How am I supposed to be able to run the secondMw?
var apiRouter = require('express').Router();
apiRouter.param('user', function firstMw(req, res, next, param) {
if(param === 'i'){
return next(); //jump to next mw sub-stack
}
next('route'); //continue with another matching route
}, function secondMw(req, res, next, param) {
console.log('NO, I AM NOT HERE. NEVER');
next();
});
apiRouter.get('/users/:user', function (req, res, next) {
res.json({
id: req.params.user
});
});
app.use('/api', apiRouter);
I don't see that router.params supports middleware stack (compare definition with app.get). But you can use ordered definition for same route.
'use strict';
let express = require('express');
let app = express();
app.use(require('body-parser').urlencoded({extended: false}));
var apiRouter = express.Router();
apiRouter.param('user', function mw1(req, res, next, param) {
console.log('MW1', param);
if (param === 'i')
next();
else
next('Error message'); // better next( new Error('Error message'));
});
apiRouter.param('user', function mw2(req, res, next, param) {
console.log('MW2', param);
next();
})
// If next() have params then Express calls handler error
apiRouter.use(function (err, req, res, next) {
console.log('Error: ', err)
res.send(err.message || err);
});
apiRouter.get('/users/:user', function (req, res, next) {
res.json({id: req.params.user});
});
app.use('/api', apiRouter);
app.listen(3000, function () {
console.log('Listening on port 3000');
});

Resources