diff --git a/app.js b/app.js index 68ffe6faea..693032f857 100644 --- a/app.js +++ b/app.js @@ -225,15 +225,35 @@ function setup() { var install = require('./src/install'); - winston.info('Welcome to NodeBB!'); - winston.info('This looks like a new installation, so you\'ll have to answer a few questions about your environment before we can proceed.'); - winston.info('Press enter to accept the default setting (shown in brackets).'); + process.stdout.write('\nWelcome to NodeBB!\n'); + process.stdout.write('\nThis looks like a new installation, so you\'ll have to answer a few questions about your environment before we can proceed.\n'); + process.stdout.write('Press enter to accept the default setting (shown in brackets).\n'); + + install.setup(function (err, data) { + var separator = ' '; + if (process.stdout.columns > 10) { + for(var x=0,cols=process.stdout.columns-10;x userListCount) { diff --git a/src/install.js b/src/install.js index 262ec0c749..972f59c7be 100644 --- a/src/install.js +++ b/src/install.js @@ -52,7 +52,8 @@ questions.optional = [ ]; function checkSetupFlag(next) { - var setupVal; + var envSetupKeys = ['database'], + setupVal; try { setupVal = JSON.parse(nconf.get('setup')); } catch (err) { @@ -82,6 +83,15 @@ function checkSetupFlag(next) { process.exit(); } + } else if (envSetupKeys.every(function(key) { + return nconf.stores.env.store.hasOwnProperty(key); + })) { + install.values = envSetupKeys.reduce(function(config, key) { + config[key] = nconf.stores.env.store[key]; + return config; + }, {}); + + next(); } else { next(); } @@ -225,7 +235,7 @@ install.installDbDependencies = function(server_conf, next) { }; function setupDefaultConfigs(next) { - winston.info('Populating database with default configs, if not already set...'); + process.stdout.write('Populating database with default configs, if not already set...\n'); var meta = require('./meta'), defaults = require(path.join(__dirname, '../', 'install/data/defaults.json')); @@ -255,11 +265,11 @@ function enableDefaultTheme(next) { meta.configs.get('theme:id', function(err, id) { if (err || id) { - winston.info('Previous theme detected, skipping enabling default theme'); + process.stdout.write('Previous theme detected, skipping enabling default theme\n'); return next(err); } - winston.info('Enabling default theme: Lavender'); + process.stdout.write('Enabling default theme: Lavender\n'); meta.themes.set({ type: 'local', id: 'nodebb-theme-lavender' @@ -271,7 +281,7 @@ function createAdministrator(next) { var Groups = require('./groups'); Groups.get('administrators', {}, function (err, groupObj) { if (!err && groupObj && groupObj.memberCount > 0) { - winston.info('Administrator found, skipping Admin setup'); + process.stdout.write('Administrator found, skipping Admin setup\n'); next(); } else { createAdmin(next); @@ -281,9 +291,10 @@ function createAdministrator(next) { function createAdmin(callback) { var User = require('./user'), - Groups = require('./groups'); + Groups = require('./groups'), + password; - winston.warn('No administrators have been detected, running initial user setup'); + winston.warn('No administrators have been detected, running initial user setup\n'); var questions = [{ name: 'username', @@ -325,7 +336,9 @@ function createAdmin(callback) { return callback(new Error('invalid-values')); } - Groups.join('administrators', uid, callback); + Groups.join('administrators', uid, function(err) { + callback(err, password ? results : undefined); + }); }); }, retryPassword = function (originalResults) { @@ -350,11 +363,17 @@ function createAdmin(callback) { if (!install.values) { prompt.get(questions, success); } else { + // If automated setup did not provide a user password, generate one, it will be shown to the user upon setup completion + if (!install.values.hasOwnProperty('admin:password') && !nconf.get('admin:password')) { + process.stdout.write('Password was not provided during automated setup, generating one...\n') + password = utils.generateUUID().slice(0, 8); + } + var results = { - username: install.values['admin:username'], - email: install.values['admin:email'], - password: install.values['admin:password'], - 'password:confirm': install.values['admin:password:confirm'] + username: install.values['admin:username'] || 'admin', + email: install.values['admin:email'] || '', + password: install.values['admin:password'] || nconf.get('admin:password') || password, + 'password:confirm': install.values['admin:password:confirm'] || nconf.get('admin:password') || password }; success(null, results); @@ -370,11 +389,11 @@ function createCategories(next) { } if (Array.isArray(categoryData) && categoryData.length) { - winston.info('Categories OK. Found ' + categoryData.length + ' categories.'); + process.stdout.write('Categories OK. Found ' + categoryData.length + ' categories.\n'); return next(); } - winston.warn('No categories found, populating instance with default categories'); + process.stdout.write('No categories found, populating instance with default categories\n'); fs.readFile(path.join(__dirname, '../', 'install/data/categories.json'), function (err, default_categories) { if (err) { @@ -425,7 +444,7 @@ function createWelcomePost(next) { function enableDefaultPlugins(next) { var Plugins = require('./plugins'); - winston.info('Enabling default plugins'); + process.stdout.write('Enabling default plugins\n'); var defaultEnabled = [ 'nodebb-plugin-markdown', @@ -464,6 +483,8 @@ function setCopyrightWidget(next) { } install.setup = function (callback) { + var upgrade = require('./upgrade'); + async.series([ checkSetupFlag, checkCIFlag, @@ -477,14 +498,23 @@ install.setup = function (callback) { enableDefaultPlugins, setCopyrightWidget, function (next) { - require('./upgrade').upgrade(next); + upgrade.check(function(uptodate) { + if (!uptodate) { upgrade.upgrade(next); } + else { next(); } + }); } - ], function (err) { + ], function (err, results) { if (err) { winston.warn('NodeBB Setup Aborted.\n ' + err.stack); process.exit(); } else { - callback(); + var data = {}; + if (results[6]) { + data.username = results[6].username + data.password = results[6].password; + } + + callback(null, data); } }); }; @@ -502,7 +532,7 @@ install.save = function (server_conf, callback) { return callback(err); } - winston.info('Configuration Saved OK'); + process.stdout.write('Configuration Saved OK\n'); nconf.file({ file: path.join(__dirname, '..', 'config.json') diff --git a/src/messaging.js b/src/messaging.js index d80cf4a78c..cd3e1f96e2 100644 --- a/src/messaging.js +++ b/src/messaging.js @@ -250,6 +250,12 @@ var db = require('./database'), return callback(err); } + results.users.forEach(function(user, index) { + if (user && !parseInt(user.uid, 10)) { + Messaging.markRead(uid, uids[index]); + } + }); + results.users = results.users.filter(function(user) { return user && parseInt(user.uid, 10); }); diff --git a/src/socket.io/posts.js b/src/socket.io/posts.js index 314028b14c..14b294da39 100644 --- a/src/socket.io/posts.js +++ b/src/socket.io/posts.js @@ -234,7 +234,7 @@ SocketPosts.sendNotificationToPostOwner = function(pid, fromuid, notification) { async.parallel({ username: async.apply(user.getUserField, fromuid, 'username'), topicTitle: async.apply(topics.getTopicField, postData.tid, 'title'), - postObj: async.apply(postTools.parsePost, postData) + postObj: async.apply(posts.parsePost, postData) }, function(err, results) { if (err) { return; diff --git a/src/socket.io/user.js b/src/socket.io/user.js index 02a7aee65e..0df36121e8 100644 --- a/src/socket.io/user.js +++ b/src/socket.io/user.js @@ -24,20 +24,27 @@ SocketUser.exists = function(socket, data, callback) { }; SocketUser.deleteAccount = function(socket, data, callback) { - if (socket.uid) { - user.isAdministrator(socket.uid, function(err, isAdmin) { - if (err || isAdmin) { - return callback(err || new Error('[[error:cant-delete-admin]]')); - } - - socket.broadcast.emit('event:user_status_change', {uid: socket.uid, status: 'offline'}); - user.deleteAccount(socket.uid, callback); - }); + if (!socket.uid) { + return; } + user.isAdministrator(socket.uid, function(err, isAdmin) { + if (err || isAdmin) { + return callback(err || new Error('[[error:cant-delete-admin]]')); + } + + socket.broadcast.emit('event:user_status_change', {uid: socket.uid, status: 'offline'}); + user.deleteAccount(socket.uid, function(err) { + if (err) { + return callback(err); + } + websockets.in('uid_' + socket.uid).emit('event:logout'); + callback(); + }); + }); }; SocketUser.emailExists = function(socket, data, callback) { - if(data && data.email) { + if (data && data.email) { user.email.exists(data.email, callback); } }; diff --git a/src/threadTools.js b/src/threadTools.js index ea66ac9239..c98e62dbcc 100644 --- a/src/threadTools.js +++ b/src/threadTools.js @@ -26,9 +26,10 @@ var async = require('async'), return callback(err); } - var alreadyDeletedOrRestored = (parseInt(topicData.deleted, 10) && isDelete) || (!parseInt(topicData.deleted, 10) && !isDelete); - if (alreadyDeletedOrRestored) { - return callback(null, {tid: tid}); + if (parseInt(topicData.deleted, 10) === 1 && isDelete) { + return callback(new Error('[[error:topic-already-deleted]]')); + } else if(parseInt(topicData.deleted, 10) !== 1 && !isDelete) { + return callback(new Error('[[error:topic-already-restored]]')); } topics[isDelete ? 'delete' : 'restore'](tid, function(err) { diff --git a/src/upgrade.js b/src/upgrade.js index 3a52020ca5..a11e890a52 100644 --- a/src/upgrade.js +++ b/src/upgrade.js @@ -971,23 +971,25 @@ Upgrade.upgrade = function(callback) { } else { winston.info('[upgrade] Schema already up to date!'); } - - process.exit(); } else { switch(err.message) { case 'upgrade-not-possible': winston.error('[upgrade] NodeBB upgrade could not complete, as your database schema is too far out of date.'); winston.error('[upgrade] Please ensure that you did not skip any minor version upgrades.'); winston.error('[upgrade] (e.g. v0.1.x directly to v0.3.x)'); - process.exit(); break; default: winston.error('[upgrade] Errors were encountered while updating the NodeBB schema: ' + err.message); - process.exit(); break; } } + + if (typeof callback === 'function') { + callback(err); + } else { + process.exit(); + } }); };