Skip to content

Instantly share code, notes, and snippets.

@tbjers
Created September 3, 2012 17:12
Show Gist options
  • Save tbjers/3610934 to your computer and use it in GitHub Desktop.
Save tbjers/3610934 to your computer and use it in GitHub Desktop.
Express resources with authentication middleware
module.exports = {
menu: {
'wall': { title: 'Wall', name: 'wall' },
'logs': { title: 'Logs', name: 'logs', submenu: {
'system': { title: 'System', name: 'system' }
} },
'stats': { title: 'Stats', name: 'stats' },
'admin': { title: 'Admin', name: 'admin', submenu: {
'users': { title: 'Users', name: 'users' },
'grants': { title: 'Grants', name: 'grants' }
} }
}
};
var express = require('express');
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var bcrypt = require('bcrypt');
var routes = require('./routes');
exports.boot = function (app) {
bootApplication(app);
};
function bootApplication (app) {
// Serialize User
passport.serializeUser(function (user, done) {
done(null, user._id);
});
// Deserialize User by loading them from the database
passport.deserializeUser(function (id, done) {
User.find(id, function (error, user) {
done(error, user);
});
});
// Set up the local passport strategy
passport.use(new LocalStrategy(function (username, password, done) {
process.nextTick(function () {
User.findOne({ screen_name: username }, null, null, function (error, user) {
if (error) return done(error);
if (!user || (user && !user.password)) return done(null, false, { message: 'Unknown user: ' + username });
bcrypt.compare(password, user.password, function (error, result) {
if (result === true) {
return done(null, user);
}
return done(null, false, { message: 'Invalid password' });
});
});
});
}));
// Ensure that a user is authenticated
function ensureAuthenticated (req, res, next) {
var path, method, hierarchy, controller, action;
if (req.isAuthenticated()) {
if (req.user.is_admin === true) {
return next();
} else {
if (!req.user.permissions) {
console.log('%s: User %s has no permissions.', Date(Date.now()), req.user.screen_name);
return res.redirect('/login');
}
method = req.route.method;
path = req.route.path.substring(1).replace(/[\*]+/g, '');
hierarchy = path.split('/');
if (hierarchy.length == 1) {
hierarchy[1] = 'index';
}
controller = hierarchy[0];
action = hierarchy[1];
if (req.user.permissions[controller] && req.user.permissions[controller][action]) {
return next();
} else {
res.render('401', { title: '401 - Unauthorized', user: req.user });
}
}
} else {
res.redirect('/login');
}
}
// Configure the application server
app.configure(function () {
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.cookieParser());
app.use(express.session({ secret: 'keyboard_cat' }));
app.use(passport.initialize());
app.use(passport.session());
app.use(require('stylus').middleware({ src: __dirname + '/public' }));
app.use(app.router);
app.use(express.static(__dirname + '/public'));
app.enable('case sensitive routing');
// Configure development environment
app.configure('development', function () {
app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});
// Configure the production environment
app.configure('production', function () {
app.use(express.logger());
app.use(express.errorHandler());
});
// Set up special routes handling
app.get('/', routes.index);
app.get('/login', routes.get_login);
app.post('/login', passport.authenticate('local', { failureRedirect: '/login', failureFlash: true }), routes.post_login);
app.get('/login/password', routes.get_password);
app.post('/login/password', routes.post_password);
app.get('/login/recover/:id', routes.get_recover);
app.post('/login/recover/:id', routes.post_recover);
app.get('/logout', routes.logout);
app.get('/img/:name.svgz', function (req, res, next) {
res.setHeader('Content-Encoding', 'x-gzip');
next();
});
app.set('menu', config.menu);
// Create resources for each menu item
for (i in config.menu) {
var item = config.menu[i], subitem;
app.all('/' + item.name + '*', ensureAuthenticated, function (req, res, next) {
next();
});
app.resource(item.name, require('./controllers/' + item.name));
if (item.submenu) {
for (j in item.submenu) {
subitem = item.submenu[j];
app.all('/' + item.name + '/' + subitem.name + '*', ensureAuthenticated, function (req, res, next) {
next();
});
app.resource(item.name + '/' + subitem.name, require('./controllers/' + item.name + '/' + subitem.name));
}
}
}
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment