diff --git a/public/src/modules/composer.js b/public/src/modules/composer.js index 8326ec0245..924cf94fec 100644 --- a/public/src/modules/composer.js +++ b/public/src/modules/composer.js @@ -187,7 +187,15 @@ define(['taskbar'], function(taskbar) { switch(action) { case 'post': composer.post(uuid); break; case 'minimize': composer.minimize(uuid); break; - case 'discard': composer.discard(uuid); break; + case 'discard': + if (postContentEl.value.length > 0) { + bootbox.confirm('Are you sure you wish to discard this post?', function(discard) { + if (discard) composer.discard(uuid); + }); + } else { + composer.discard(uuid); + } + break; } }); diff --git a/src/plugins.js b/src/plugins.js index c8e77de3f7..645c90952f 100644 --- a/src/plugins.js +++ b/src/plugins.js @@ -26,7 +26,6 @@ var fs = require('fs'), function(plugins, next) { if (plugins && Array.isArray(plugins) && plugins.length > 0) { async.each(plugins, function(plugin, next) { - // TODO: Update this check to also check node_modules var pluginPath = path.join(__dirname, '../plugins/', plugin), modulePath = path.join(__dirname, '../node_modules/', plugin); if (fs.existsSync(pluginPath)) _self.loadPlugin(pluginPath, next); @@ -57,11 +56,13 @@ var fs = require('fs'), if (global.env === 'development') winston.info('[plugins] Plugins OK'); + _self.initialized = true; _self.readyEvent.emit('ready'); }); }, ready: function(callback) { - this.readyEvent.once('ready', callback); + if (!this.initialized) this.readyEvent.once('ready', callback); + else callback(); }, initialized: false, loadPlugin: function(pluginPath, callback) { @@ -161,7 +162,7 @@ var fs = require('fs'), } } - callback(returnVal); + callback(err, returnVal); }); break; case 'action': @@ -184,7 +185,7 @@ var fs = require('fs'), } else { // Otherwise, this hook contains no methods var returnVal = (Array.isArray(args) ? args[0] : args); - if (callback) callback(returnVal); + if (callback) callback(err, returnVal); } }, isActive: function(id, callback) { diff --git a/src/postTools.js b/src/postTools.js index 8913a1e787..8f41608391 100644 --- a/src/postTools.js +++ b/src/postTools.js @@ -102,8 +102,8 @@ var RDB = require('./redis.js'), PostTools.privileges(pid, uid, function(privileges) { if (privileges.editable) { - plugins.fireHook('filter:post.save', content, function(parsedContent) { - content = parsedContent; + plugins.fireHook('filter:post.save', content, function(err, parsedContent) { + if (!err) content = parsedContent; success(); }); } @@ -193,8 +193,8 @@ var RDB = require('./redis.js'), PostTools.parse = function(raw, callback) { raw = raw || ''; - plugins.fireHook('filter:post.parse', raw, function(parsed) { - callback(null, parsed); + plugins.fireHook('filter:post.parse', raw, function(err, parsed) { + callback(null, !err ? parsed : raw); }); } diff --git a/src/posts.js b/src/posts.js index 29989fb8e2..957d2790b9 100644 --- a/src/posts.js +++ b/src/posts.js @@ -122,8 +122,9 @@ var RDB = require('./redis.js'), Posts.getPostData = function(pid, callback) { RDB.hgetall('post:' + pid, function(err, data) { if (err === null) { - plugins.fireHook('filter:post.get', data, function(data) { - callback(data); + plugins.fireHook('filter:post.get', data, function(err, newData) { + if (!err) callback(newData); + else callback(data); }); } else console.log(err); @@ -287,7 +288,9 @@ var RDB = require('./redis.js'), RDB.incr('global:next_post_id', function(err, pid) { RDB.handle(err); - plugins.fireHook('filter:post.save', content, function(content) { + plugins.fireHook('filter:post.save', content, function(err, newContent) { + if (!err) content = newContent; + var timestamp = Date.now(), postData = { 'pid': pid, @@ -337,7 +340,9 @@ var RDB = require('./redis.js'), async.parallel({ content: function(next) { - plugins.fireHook('filter:post.get', postData, function(postData) { + plugins.fireHook('filter:post.get', postData, function(err, newPostData) { + if (!err) postData = newPostData; + postTools.parse(postData.content, function(err, content) { next(null, content); }); diff --git a/src/webserver.js b/src/webserver.js index b9116e7906..a9b7488f90 100644 --- a/src/webserver.js +++ b/src/webserver.js @@ -22,7 +22,8 @@ var express = require('express'), meta = require('./meta.js'), feed = require('./feed'), plugins = require('./plugins'), - nconf = require('nconf'); + nconf = require('nconf'), + winston = require('winston'); (function (app) { var templates = null, @@ -72,54 +73,104 @@ var express = require('express'), }; // Middlewares - app.use(express.compress()); - app.use(express.favicon(path.join(__dirname, '../', 'public', 'favicon.ico'))); - app.use(require('less-middleware')({ - src: path.join(__dirname, '../', 'public'), - prefix: nconf.get('relative_path'), - yuicompress: true - })); - app.use(nconf.get('relative_path'), express.static(path.join(__dirname, '../', 'public'))); - app.use(express.bodyParser()); // Puts POST vars in request.body - - app.use(express.cookieParser()); // If you want to parse cookies (res.cookies) - app.use(express.session({ - store: new RedisStore({ - client: RDB, - ttl: 60 * 60 * 24 * 30 - }), - secret: nconf.get('secret'), - key: 'express.sid', - cookie: { - maxAge: 60 * 60 * 24 * 30 * 1000 // 30 days - } - })); - app.use(express.csrf()); - app.use(function (req, res, next) { - res.locals.csrf_token = req.session._csrf; - next(); - }); + app.configure(function() { + async.series([ + function(next) { + // Pre-router middlewares + app.use(express.compress()); + app.use(express.favicon(path.join(__dirname, '../', 'public', 'favicon.ico'))); + app.use(require('less-middleware')({ + src: path.join(__dirname, '../', 'public'), + prefix: nconf.get('relative_path'), + yuicompress: true + })); + app.use(nconf.get('relative_path'), express.static(path.join(__dirname, '../', 'public'))); + app.use(express.bodyParser()); // Puts POST vars in request.body + app.use(express.cookieParser()); // If you want to parse cookies (res.cookies) + app.use(express.session({ + store: new RedisStore({ + client: RDB, + ttl: 60 * 60 * 24 * 30 + }), + secret: nconf.get('secret'), + key: 'express.sid', + cookie: { + maxAge: 60 * 60 * 24 * 30 * 1000 // 30 days + } + })); + app.use(express.csrf()); + + // Local vars, other assorted setup + app.use(function (req, res, next) { + nconf.set('https', req.secure); + res.locals.csrf_token = req.session._csrf; + next(); + }); - // Static Directories for NodeBB Plugins - app.configure(function () { - var tailMiddlewares = []; - - plugins.ready(function () { - // Remove some middlewares until the router is gone - // This is not recommended behaviour: http://stackoverflow.com/a/13691542/122353 - // Also: https://www.exratione.com/2013/03/nodejs-abusing-express-3-to-enable-late-addition-of-middleware/ - tailMiddlewares.push(app.stack.pop()); - tailMiddlewares.push(app.stack.pop()); - tailMiddlewares.push(app.stack.pop()); - for (d in plugins.staticDirs) { - app.use(nconf.get('relative_path') + '/plugins/' + d, express.static(plugins.staticDirs[d])); - } + // Authentication Routes + auth.initialize(app); + + next(); + }, + function(next) { + // Static Directories for NodeBB Plugins + plugins.ready(function () { + for (d in plugins.staticDirs) { + app.use(nconf.get('relative_path') + '/plugins/' + d, express.static(plugins.staticDirs[d])); + winston.info('Static directory routed for plugin: ' + d); + } + + next(); + }); + }, + function(next) { + // Router & post-router middlewares + app.use(app.router); + + // 404 catch-all + app.use(function (req, res, next) { + res.status(404); + + // respond with html page + if (req.accepts('html')) { + res.redirect(nconf.get('relative_path') + '/404'); + return; + } + + // respond with json + if (req.accepts('json')) { + res.send({ + error: 'Not found' + }); + return; + } - // Push the removed middlewares back onto the application stack - tailMiddlewares.reverse(); - app.stack.push(tailMiddlewares.shift()); - app.stack.push(tailMiddlewares.shift()); - app.stack.push(tailMiddlewares.shift()); + // default to plain-text. send() + res.type('txt').send('Not found'); + }); + + app.use(function (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); + + res.status(err.status || 500); + + res.json('500', { + error: err.message + }); + }); + + next(); + } + ], function(err) { + if (err) { + winston.error('Errors were encountered while attempting to initialise NodeBB.'); + } else { + winston.info('Middlewares loaded.'); + } }); }); @@ -137,59 +188,10 @@ var express = require('express'), server.listen(nconf.get('PORT') || nconf.get('port')); } - auth.initialize(app); - - app.use(function (req, res, next) { - - nconf.set('https', req.secure); - - next(); - }); - - app.use(app.router); - - app.use(function (req, res, next) { - res.status(404); - - // respond with html page - if (req.accepts('html')) { - //res.json('404', { url: req.url }); - res.redirect(nconf.get('relative_path') + '/404'); - return; - } - - // respond with json - if (req.accepts('json')) { - res.send({ - error: 'Not found' - }); - return; - } - - // default to plain-text. send() - res.type('txt').send('Not found'); - }); - - app.use(function (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); - - res.status(err.status || 500); - - res.json('500', { - error: err.message - }); - }); - - app.create_route = function (url, tpl) { // to remove return ''; }; - app.namespace(nconf.get('relative_path'), function () { auth.create_routes(app);