From 828980f3e61e159a488ad6527bd1669361e236d5 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Tue, 21 Apr 2015 16:48:41 -0400 Subject: [PATCH 1/6] closes #3008 --- src/threadTools.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) 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) { From b604c9d5e1a8208efe8ac7bf1daf0bd99a0fdab5 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Wed, 22 Apr 2015 10:27:54 -0400 Subject: [PATCH 2/6] updated install script to accept environment variables updated upgrade script to execute callback when present updated install script to not fire upgrades unless necessary updated install script to write directly to console, and not through winston if a password is not provided, one is auto-generated --- app.js | 30 ++++++++++++++++++---- src/install.js | 68 ++++++++++++++++++++++++++++++++++++-------------- src/upgrade.js | 10 +++++--- 3 files changed, 80 insertions(+), 28 deletions(-) diff --git a/app.js b/app.js index 66f16da88c..70f6e7f0a8 100644 --- a/app.js +++ b/app.js @@ -227,15 +227,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 0) { - winston.info('Administrator found, skipping Admin setup'); + process.stdout.write('Administrator found, skipping Admin setup\n'); next(); } else { createAdmin(next); @@ -279,9 +289,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', @@ -323,7 +334,9 @@ function createAdmin(callback) { return callback(new Error('invalid-values')); } - Groups.join('administrators', uid, callback); + Groups.join('administrators', uid, function(err) { + callback(err, results); + }); }); }, retryPassword = function (originalResults) { @@ -348,11 +361,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')) { + 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'] || password, + 'password:confirm': install.values['admin:password:confirm'] || password }; success(null, results); @@ -368,11 +387,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) { @@ -423,7 +442,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', @@ -462,6 +481,8 @@ function setCopyrightWidget(next) { } install.setup = function (callback) { + var upgrade = require('./upgrade'); + async.series([ checkSetupFlag, checkCIFlag, @@ -475,14 +496,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); } }); }; @@ -500,7 +530,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/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(); + } }); }; From d7444e5edf6eb2d5b4cad5a36847afac35a53535 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Wed, 22 Apr 2015 10:30:42 -0400 Subject: [PATCH 3/6] removed from required values for env setup --- src/install.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/install.js b/src/install.js index d2566f0e4f..866fd1d567 100644 --- a/src/install.js +++ b/src/install.js @@ -52,7 +52,7 @@ questions.optional = [ ]; function checkSetupFlag(next) { - var envSetupKeys = ['url', 'database'], + var envSetupKeys = ['database'], setupVal; try { setupVal = JSON.parse(nconf.get('setup')); From 7632997a999ad9d11fda831d8972c566a5cd67e3 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Wed, 22 Apr 2015 10:41:44 -0400 Subject: [PATCH 4/6] closes #3045 --- public/src/app.js | 2 ++ public/src/client/account/edit.js | 4 ++-- src/groups.js | 4 ++++ src/messaging.js | 6 ++++++ src/socket.io/user.js | 27 +++++++++++++++++---------- 5 files changed, 31 insertions(+), 12 deletions(-) diff --git a/public/src/app.js b/public/src/app.js index 0460e440d7..f054575011 100644 --- a/public/src/app.js +++ b/public/src/app.js @@ -66,6 +66,8 @@ app.cacheBuster = null; }, 1000); }); + socket.on('event:logout', app.logout); + socket.on('event:alert', function(data) { app.alert(data); }); diff --git a/public/src/client/account/edit.js b/public/src/client/account/edit.js index e44d9f3f81..42dd151e6f 100644 --- a/public/src/client/account/edit.js +++ b/public/src/client/account/edit.js @@ -157,8 +157,8 @@ define('forum/account/edit', ['forum/account/header', 'uploader', 'translator'], return false; } else { socket.emit('user.deleteAccount', {}, function(err) { - if (!err) { - app.logout(); + if (err) { + app.alertError(err.message); } }); } diff --git a/src/groups.js b/src/groups.js index 90053643d3..a66555104e 100644 --- a/src/groups.js +++ b/src/groups.js @@ -115,6 +115,10 @@ var async = require('async'), return next(err); } + uids = uids.filter(function(uid) { + return uid && parseInt(uid, 10); + }); + if (options.truncateUserList) { var userListCount = parseInt(options.userListCount, 10) || 4; if (uids.length > userListCount) { 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/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); } }; From 8f5c393b12f61cdfd6e18e9fce2bb58fcb41e261 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Wed, 22 Apr 2015 10:58:40 -0400 Subject: [PATCH 5/6] only exposing password at setup end if one is autogenerated --- src/install.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/install.js b/src/install.js index 866fd1d567..e5226cb78e 100644 --- a/src/install.js +++ b/src/install.js @@ -335,7 +335,7 @@ function createAdmin(callback) { } Groups.join('administrators', uid, function(err) { - callback(err, results); + callback(err, password ? results : undefined); }); }); }, @@ -362,7 +362,7 @@ function createAdmin(callback) { 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')) { + 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); } @@ -370,8 +370,8 @@ function createAdmin(callback) { var results = { username: install.values['admin:username'] || 'admin', email: install.values['admin:email'] || '', - password: install.values['admin:password'] || password, - 'password:confirm': install.values['admin:password:confirm'] || password + 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); From a2497b050edd010d2a6fe9dead509fed4de96cec Mon Sep 17 00:00:00 2001 From: barisusakli Date: Wed, 22 Apr 2015 11:10:42 -0400 Subject: [PATCH 6/6] crash fix --- src/socket.io/posts.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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;