diff --git a/package.json b/package.json index 761b21a0fe..c503019f29 100644 --- a/package.json +++ b/package.json @@ -20,8 +20,7 @@ "connect-flash": "^0.1.1", "cron": "~1.0.4", "daemon": "~1.1.0", - "express": "3.2.0", - "express-namespace": "~0.1.1", + "express": "4.4.5", "gm": "1.14.2", "gravatar": "1.0.6", "less": "~1.6.3", @@ -41,6 +40,17 @@ "prompt": "~0.2.11", "request": "~2.34.0", "rimraf": "~2.2.6", + + + "cookie-parser": "^1.0.1", + "body-parser": "^1.0.1", + "serve-favicon": "^2.0.1", + "express-session": "^1.0.2", + "csurf": "^1.1.0", + "compression": "^1.0.1", + + "morgan": "^1.0.0", + "rss": "~0.2.0", "semver": "~2.2.1", "sitemap": "~0.7.3", diff --git a/public/src/templates.js b/public/src/templates.js index 3d02dfcc87..5cf10aeb4b 100644 --- a/public/src/templates.js +++ b/public/src/templates.js @@ -36,7 +36,7 @@ Please use the npm module instead - require('templates.js') } callback(parse(loaded, obj, bind)); - }); + }); } else { callback(parse(templates.cache[template], obj, bind)); } @@ -62,6 +62,7 @@ Please use the npm module instead - require('templates.js') }; function express(filename, options, fn) { + console.log(filename, options, fn); var fs = require('fs'), tpl = filename.replace(options.settings.views + '/', ''); @@ -185,7 +186,7 @@ Please use the npm module instead - require('templates.js') while (block = template.match(regex)) { block = block[0].replace(makeBlockRegex(key), ''); - + var numblocks = array[key].length - 1, iterator = 0, result = '', @@ -193,7 +194,7 @@ Please use the npm module instead - require('templates.js') do { parsedBlock = parse(block, array[key][iterator], bind, namespace, {iterator: iterator, total: numblocks}) + ((iterator < numblocks) ? '\r\n':''); - + result += (!bind) ? parsedBlock : setBindContainer(parsedBlock, bind + namespace + iterator); result = parseFunctions(block, result, { data: array[key][iterator], @@ -213,7 +214,7 @@ Please use the npm module instead - require('templates.js') template = template.replace(regex, result); } - + return template; } @@ -247,14 +248,14 @@ Please use the npm module instead - require('templates.js') this['__' + key] = value; var els = document.querySelectorAll('[data-binding="' + (this.__iterator !== false ? (bind + this.__namespace + this.__iterator) : bind) + '"]'); - + for (var el in els) { if (els.hasOwnProperty(el)) { if (this.__parent) { var parent = this.__parent(); els[el].innerHTML = parse(parent.template, parent.data, false); } else { - els[el].innerHTML = parse(this.__template, obj, false, this.__namespace); + els[el].innerHTML = parse(this.__template, obj, false, this.__namespace); } } } @@ -294,7 +295,7 @@ Please use the npm module instead - require('templates.js') template = parse(template, obj[key], bind, namespace + key + '.'); } else { template = parseValue(template, namespace + key, obj[key]); - + if (bind && obj[key]) { setupBindings({ obj: obj, diff --git a/src/database/mongo.js b/src/database/mongo.js index 5b25ae9284..a9f765e1dd 100644 --- a/src/database/mongo.js +++ b/src/database/mongo.js @@ -6,7 +6,7 @@ var winston = require('winston'), async = require('async'), nconf = require('nconf'), - express = require('express'), + session = require('express-session'), db, mongoClient, mongoStore; @@ -41,7 +41,7 @@ module.init = function(callback) { try { mongoClient = require('mongodb').MongoClient; - mongoStore = require('connect-mongo')(express); + mongoStore = require('connect-mongo')({session: session}); } catch (err) { winston.error('Unable to initialize MongoDB! Is MongoDB installed? Error :' + err.message); process.exit(); diff --git a/src/database/redis.js b/src/database/redis.js index 2c0e9bd1cc..078f0a54d6 100644 --- a/src/database/redis.js +++ b/src/database/redis.js @@ -5,7 +5,7 @@ var winston = require('winston'), nconf = require('nconf'), path = require('path'), - express = require('express'), + session = require('express-session'), utils = require('./../../public/src/utils.js'), redis, connectRedis, @@ -40,7 +40,7 @@ module.init = function(callback) { try { redis = require('redis'); - connectRedis = require('connect-redis')(express); + connectRedis = require('connect-redis')({session: session}); reds = require('reds'); } catch (err) { winston.error('Unable to initialize Redis! Is Redis installed? Error :' + err.message); diff --git a/src/install.js b/src/install.js index b6d062cbb0..15005e8999 100644 --- a/src/install.js +++ b/src/install.js @@ -11,7 +11,7 @@ var async = require('async'), DATABASES = { "redis": { - "dependencies": ["redis@~0.10.1", "connect-redis@~1.4"] + "dependencies": ["redis@~0.10.1", "connect-redis@~2.0.0"] }, "mongo": { "dependencies": ["mongodb", "connect-mongo"] diff --git a/src/logger.js b/src/logger.js index 90926dd5fd..f1da65555e 100644 --- a/src/logger.js +++ b/src/logger.js @@ -10,7 +10,8 @@ var fs = require('fs'), winston = require('winston'), util = require('util'), socketio = require('socket.io'), - meta = require('./meta'); + meta = require('./meta'), + morgan = require('morgan'); var opts = { /* @@ -124,7 +125,7 @@ var opts = { /* * Always initialize "ofn" (original function) with the original logger function */ - opts.express.ofn = express.logger({stream : opts.streams.log.f}); + opts.express.ofn = morgan({stream : opts.streams.log.f}); }; Logger.expressLogger = function(req,res,next) { diff --git a/src/middleware/index.js b/src/middleware/index.js index 844e46cdd8..5131d0e449 100644 --- a/src/middleware/index.js +++ b/src/middleware/index.js @@ -15,6 +15,12 @@ var utils = require('./../../public/src/utils'), winston = require('winston'), flash = require('connect-flash'), templates = require('templates.js'), + bodyParser = require('body-parser'), + cookieParser = require('cookie-parser'), + compression = require('compression'), + favicon = require('serve-favicon'), + csrf = require('csurf'), + session = require('express-session'), relativePath, viewsPath, @@ -188,65 +194,63 @@ module.exports = function(app, data) { themesPath = nconf.get('themes_path'); baseTemplatesPath = nconf.get('base_templates_path'); - app.configure(function() { - app.engine('tpl', templates.__express); - app.set('view engine', 'tpl'); - app.set('views', viewsPath); - app.use(flash()); - app.enable('view cache'); + app.engine('tpl', templates.__express); + app.set('view engine', 'tpl'); + app.set('views', viewsPath); + app.use(flash()); - app.use(express.compress()); + app.enable('view cache'); - app.use(express.favicon(path.join(__dirname, '../../', 'public', meta.config['brand:favicon'] ? meta.config['brand:favicon'] : 'favicon.ico'))); - app.use(relativePath + '/apple-touch-icon', middleware.routeTouchIcon); + app.use(compression()); - app.use(express.bodyParser()); - app.use(express.cookieParser()); + app.use(favicon(path.join(__dirname, '../../', 'public', meta.config['brand:favicon'] ? meta.config['brand:favicon'] : 'favicon.ico'))); + app.use(relativePath + '/apple-touch-icon', middleware.routeTouchIcon); - app.use(express.session({ - store: db.sessionStore, - secret: nconf.get('secret'), - key: 'express.sid', - cookie: { - maxAge: 1000 * 60 * 60 * 24 * parseInt(meta.configs.loginDays || 14, 10) - } - })); + app.use(bodyParser()); + app.use(cookieParser()); - app.use(express.csrf()); // todo, make this a conditional middleware + app.use(session({ + store: db.sessionStore, + secret: nconf.get('secret'), + key: 'express.sid', + cookie: { + maxAge: 1000 * 60 * 60 * 24 * parseInt(meta.configs.loginDays || 14, 10) + } + })); - app.use(function (req, res, next) { - res.locals.csrf_token = req.session._csrf; - res.setHeader('X-Powered-By', 'NodeBB'); + app.use(csrf()); - res.setHeader('X-Frame-Options', 'SAMEORIGIN'); - if (meta.config['allow-from-uri']) { - res.setHeader('ALLOW-FROM', meta.config['allow-from-uri']); - } + app.use(function (req, res, next) { + res.locals.csrf_token = req.session._csrf; + res.setHeader('X-Powered-By', 'NodeBB'); - next(); - }); + res.setHeader('X-Frame-Options', 'SAMEORIGIN'); + if (meta.config['allow-from-uri']) { + res.setHeader('ALLOW-FROM', meta.config['allow-from-uri']); + } - app.use(middleware.processRender); + next(); + }); - auth.initialize(app); + app.use(middleware.processRender); - routeCurrentTheme(app, data.currentThemeId, data.themesData); - routeThemeScreenshots(app, data.themesData); + auth.initialize(app); - plugins.getTemplates(function(err, pluginTemplates) { - compileTemplates(pluginTemplates); - }); + routeCurrentTheme(app, data.currentThemeId, data.themesData); + routeThemeScreenshots(app, data.themesData); - app.use(relativePath, app.router); + plugins.getTemplates(function(err, pluginTemplates) { + compileTemplates(pluginTemplates); + }); - app.use(relativePath, express.static(path.join(__dirname, '../../', 'public'), { - maxAge: app.enabled('cache') ? 5184000000 : 0 - })); + app.use(relativePath, express.static(path.join(__dirname, '../../', 'public'), { + maxAge: app.enabled('cache') ? 5184000000 : 0 + })); + + //app.use(catch404); + //app.use(handleErrors); - app.use(catch404); - app.use(handleErrors); - }); return middleware; }; diff --git a/src/routes/api.js b/src/routes/api.js index 001cb5a01b..47e7b5f045 100644 --- a/src/routes/api.js +++ b/src/routes/api.js @@ -4,6 +4,7 @@ var path = require('path'), async = require('async'), fs = require('fs'), nconf = require('nconf'), + express = require('express'), user = require('../user'), topics = require('../topics'), @@ -178,17 +179,19 @@ function getRecentPosts(req, res, next) { } module.exports = function(app, middleware, controllers) { - app.namespace('/api', function () { - app.get('/config', controllers.api.getConfig); - app.get('/user/uid/:uid', middleware.checkGlobalPrivacySettings, controllers.accounts.getUserByUID); - app.get('/get_templates_listing', getTemplatesListing); - app.get('/categories/:cid/moderators', getModerators); - app.get('/recent/posts/:term?', getRecentPosts); + var router = express.Router(); - app.post('/post/upload', uploadPost); - app.post('/topic/thumb/upload', uploadThumb); - app.post('/user/:userslug/uploadpicture', middleware.authenticate, middleware.checkGlobalPrivacySettings, middleware.checkAccountPermissions, controllers.accounts.uploadPicture); - }); + router.get('/config', controllers.api.getConfig); + + router.get('/user/uid/:uid', middleware.checkGlobalPrivacySettings, controllers.accounts.getUserByUID); + router.get('/get_templates_listing', getTemplatesListing); + router.get('/categories/:cid/moderators', getModerators); + router.get('/recent/posts/:term?', getRecentPosts); + + router.post('/post/upload', uploadPost); + router.post('/topic/thumb/upload', uploadThumb); + router.post('/user/:userslug/uploadpicture', middleware.authenticate, middleware.checkGlobalPrivacySettings, middleware.checkAccountPermissions, controllers.accounts.uploadPicture); + app.use('/api', router); }; diff --git a/src/routes/debug.js b/src/routes/debug.js index ccaa4209a6..d0e24c5494 100644 --- a/src/routes/debug.js +++ b/src/routes/debug.js @@ -1,60 +1,63 @@ "use strict"; -var user = require('./../user'), +var express = require('express'), + user = require('./../user'), categories = require('./../categories'), topics = require('./../topics'), posts = require('./../posts'); module.exports = function(app, middleware, controllers) { - app.namespace('/debug', function() { - app.get('/uid/:uid', function (req, res) { - if (!req.params.uid) { - return res.redirect('/404'); - } + var router = express.Router(); - user.getUserData(req.params.uid, function (err, data) { - if (data) { - res.send(data); - } else { - res.json(404, { - error: "User doesn't exist!" - }); - } - }); - }); + router.get('/uid/:uid', function (req, res) { + if (!req.params.uid) { + return res.redirect('/404'); + } - app.get('/cid/:cid', function (req, res) { - categories.getCategoryData(req.params.cid, function (err, data) { - if (data) { - res.send(data); - } else { - res.send(404, "Category doesn't exist!"); - } - }); + user.getUserData(req.params.uid, function (err, data) { + if (data) { + res.send(data); + } else { + res.json(404, { + error: "User doesn't exist!" + }); + } }); + }); - app.get('/tid/:tid', function (req, res) { - topics.getTopicData(req.params.tid, function (err, data) { - if (data) { - res.send(data); - } else { - res.send(404, "Topic doesn't exist!"); - } - }); + router.get('/cid/:cid', function (req, res) { + categories.getCategoryData(req.params.cid, function (err, data) { + if (data) { + res.send(data); + } else { + res.send(404, "Category doesn't exist!"); + } }); + }); - app.get('/pid/:pid', function (req, res) { - posts.getPostData(req.params.pid, function (err, data) { - if (data) { - res.send(data); - } else { - res.send(404, "Post doesn't exist!"); - } - }); + router.get('/tid/:tid', function (req, res) { + topics.getTopicData(req.params.tid, function (err, data) { + if (data) { + res.send(data); + } else { + res.send(404, "Topic doesn't exist!"); + } }); + }); - app.get('/test', function(req, res) { - res.redirect('404'); + router.get('/pid/:pid', function (req, res) { + posts.getPostData(req.params.pid, function (err, data) { + if (data) { + res.send(data); + } else { + res.send(404, "Post doesn't exist!"); + } }); }); + + router.get('/test', function(req, res) { + res.redirect('404'); + }); + + return router; }; diff --git a/src/routes/index.js b/src/routes/index.js index 9166d340c1..9c94e74054 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -4,6 +4,7 @@ var nconf = require('nconf'), controllers = require('./../controllers'), meta = require('./../meta'), plugins = require('./../plugins'), + express = require('express'), metaRoutes = require('./meta'), apiRoutes = require('./api'), @@ -151,38 +152,89 @@ function groupRoutes(app, middleware, controllers) { module.exports = function(app, middleware) { - app.namespace(nconf.get('relative_path'), function() { - plugins.ready(function() { - app.all('/api/*', middleware.updateLastOnlineTime, middleware.prepareAPI); - app.all('/api/admin/*', middleware.admin.isAdmin, middleware.prepareAPI); - app.all('/admin/*', middleware.admin.isAdmin); - app.get('/admin', middleware.admin.isAdmin); - - plugins.fireHook('action:app.load', app, middleware, controllers); - - adminRoutes(app, middleware, controllers); - metaRoutes(app, middleware, controllers); - apiRoutes(app, middleware, controllers); - feedRoutes(app, middleware, controllers); - pluginRoutes(app, middleware, controllers); - authRoutes.createRoutes(app, middleware, controllers); - - /** - * Every view has an associated API route. - * - */ - mainRoutes(app, middleware, controllers); - staticRoutes(app, middleware, controllers); - topicRoutes(app, middleware, controllers); - tagRoutes(app, middleware, controllers); - categoryRoutes(app, middleware, controllers); - accountRoutes(app, middleware, controllers); - userRoutes(app, middleware, controllers); - groupRoutes(app, middleware, controllers); - }); - if (process.env.NODE_ENV === 'development') { - require('./debug')(app, middleware, controllers); - } + var router = express.Router(); + + plugins.ready(function() { + + app.all('/api/*', middleware.updateLastOnlineTime, middleware.prepareAPI); + app.all('/api/admin/*', middleware.admin.isAdmin, middleware.prepareAPI); + app.all('/admin/*', middleware.admin.isAdmin); + app.get('/admin', middleware.admin.isAdmin); + + plugins.fireHook('action:app.load', app, middleware, controllers); + + adminRoutes(app, middleware, controllers); + metaRoutes(app, middleware, controllers); + apiRoutes(app, middleware, controllers); + feedRoutes(app, middleware, controllers); + pluginRoutes(app, middleware, controllers); + authRoutes.createRoutes(app, middleware, controllers); + + /** + * Every view has an associated API route. + * + */ + mainRoutes(app, middleware, controllers); + staticRoutes(app, middleware, controllers); + topicRoutes(app, middleware, controllers); + tagRoutes(app, middleware, controllers); + categoryRoutes(app, middleware, controllers); + accountRoutes(app, middleware, controllers); + userRoutes(app, middleware, controllers); + groupRoutes(app, middleware, controllers); + + app.use(catch404); + app.use(handleErrors); + + app.use(nconf.get('relative_path'), router); }); + + if (process.env.NODE_ENV === 'development') { + app.use('/debug', require('./debug')(middleware, controllers)); + } + }; + +function handleErrors(err, req, res, next) { + // we may use properties of the error object + // here and next(err) appropriately, or if + // we possibly recovered from the error, simply next(). + console.error(err.stack); + + var status = err.status || 500; + res.status(status); + + req.flash('errorMessage', err.message); + + res.redirect('500'); +} + +function catch404(req, res, next) { + var isLanguage = new RegExp('^' + relativePath + '/language/[\\w]{2,}/.*.json'), + isClientScript = new RegExp('^' + relativePath + '\\/src\\/forum(\\/admin)?\\/.+\\.js'); + + res.status(404); + + if (isClientScript.test(req.url)) { + res.type('text/javascript').send(200, ''); + } else if (isLanguage.test(req.url)) { + res.json(200, {}); + } else if (req.accepts('html')) { + if (process.env.NODE_ENV === 'development') { + winston.warn('Route requested but not found: ' + req.url); + } + + res.redirect(relativePath + '/404'); + } else if (req.accepts('json')) { + if (process.env.NODE_ENV === 'development') { + winston.warn('Route requested but not found: ' + req.url); + } + + res.json({ + error: 'Not found' + }); + } else { + res.type('txt').send('Not found'); + } +} \ No newline at end of file diff --git a/src/socket.io/index.js b/src/socket.io/index.js index 3b872c2cac..750b8eeb11 100644 --- a/src/socket.io/index.js +++ b/src/socket.io/index.js @@ -7,8 +7,7 @@ var SocketIO = require('socket.io'), path = require('path'), fs = require('fs'), nconf = require('nconf'), - express = require('express'), - socketCookieParser = express.cookieParser(nconf.get('secret')), + socketCookieParser = require('cookie-parser')(nconf.get('secret')), winston = require('winston'), db = require('../database'), @@ -60,7 +59,7 @@ Sockets.init = function(server) { winston.error(err.message); } - sessionID = socket.handshake.signedCookies["express.sid"]; + sessionID = socket.handshake.signedCookies['express.sid']; db.sessionStore.get(sessionID, function(err, sessionData) { if (!err && sessionData && sessionData.passport && sessionData.passport.user) { uid = parseInt(sessionData.passport.user, 10); diff --git a/src/webserver.js b/src/webserver.js index e7c19359f0..9b50f0b553 100644 --- a/src/webserver.js +++ b/src/webserver.js @@ -2,7 +2,6 @@ var path = require('path'), fs = require('fs'), nconf = require('nconf'), express = require('express'), - express_namespace = require('express-namespace'), WebServer = express(), server, winston = require('winston'),