From 3bd2f530560a1c3eee796ae554d54c59c9e1e19b Mon Sep 17 00:00:00 2001 From: EvSpirit Date: Wed, 25 Mar 2015 20:18:15 +0300 Subject: [PATCH 01/24] #2893 increment --debug-brk port value when forking js-minifier child process --- src/meta/js.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/meta/js.js b/src/meta/js.js index 85188ab3f7..4f575faa41 100644 --- a/src/meta/js.js +++ b/src/meta/js.js @@ -129,7 +129,12 @@ module.exports = function(Meta) { Meta.js.minify = function(minify, callback) { if (nconf.get('isPrimary') === 'true') { - var minifier = Meta.js.minifierProc = fork('minifier.js'), + var forkProcessParams = {}; + if(global.v8debug) { + forkProcessParams = {execArgv: ['--debug-brk=' + (global.process.debugPort + 1)]}; + } + + var minifier = Meta.js.minifierProc = fork('minifier.js', [], forkProcessParams), onComplete = function(err) { if (err) { winston.error('[meta/js] Minification failed: ' + err.message); From 8a6c189d80d15e7c793997906155480cfcf4492b Mon Sep 17 00:00:00 2001 From: EvSpirit Date: Wed, 25 Mar 2015 20:40:42 +0300 Subject: [PATCH 02/24] #2893 increment --debug-brk port value when forking js-minifier child process --- src/meta/js.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/meta/js.js b/src/meta/js.js index 4f575faa41..ff6ef1e32f 100644 --- a/src/meta/js.js +++ b/src/meta/js.js @@ -129,9 +129,21 @@ module.exports = function(Meta) { Meta.js.minify = function(minify, callback) { if (nconf.get('isPrimary') === 'true') { + /** + * Check if the parent process is running with the debug option --debug (or --debug-brk) + */ var forkProcessParams = {}; if(global.v8debug) { - forkProcessParams = {execArgv: ['--debug-brk=' + (global.process.debugPort + 1)]}; + /** + * use the line below if you want to debug minifier.js script too (or even --debug-brk option, but + * you'll have to setup your debugger and connect to the forked process) + */ + //forkProcessParams = {execArgv: ['--debug=' + (global.process.debugPort + 1), '--nolazy']}; + + /** + * otherwise, just clean up --debug/--debug-brk options which are set up by default from the parent one + */ + forkProcessParams = {execArgv: []}; } var minifier = Meta.js.minifierProc = fork('minifier.js', [], forkProcessParams), From 550140ada7dade2fb7dae24c9c775ce6a3a67c4a Mon Sep 17 00:00:00 2001 From: A Catty Alpaca Date: Thu, 21 May 2015 01:10:56 +0200 Subject: [PATCH 03/24] General-Purpose Dockerfile --- Dockerfile | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000000..c44b71096d --- /dev/null +++ b/Dockerfile @@ -0,0 +1,8 @@ +FROM node:0.10-onbuild + +ENV NODE_ENV=production \ + daemon=false \ + silent=false + +CMD node app --setup && npm start +EXPOSE 4567 From c13589735d0a49dc70d8ffc742d4ce1f6bf74bb1 Mon Sep 17 00:00:00 2001 From: Mani Wang Date: Mon, 20 Jul 2015 16:57:35 +0800 Subject: [PATCH 04/24] allow use github module avoid `outdated` error when use github address as module. --- src/meta/dependencies.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/meta/dependencies.js b/src/meta/dependencies.js index 3bc9719890..487640ee81 100644 --- a/src/meta/dependencies.js +++ b/src/meta/dependencies.js @@ -23,7 +23,7 @@ module.exports = function(Meta) { var pkgData = JSON.parse(pkgData), ok = semver.satisfies(pkgData.version, pkg.dependencies[module]); - if (ok) { + if (ok || pkgData._fromGithub) { next(true); } else { process.stdout.write('[' + 'outdated'.yellow + '] ' + module.bold + ' v' + pkgData.version + ', requires ' + pkg.dependencies[module] + '\n') @@ -38,4 +38,4 @@ module.exports = function(Meta) { callback(!ok && global.env !== 'development' ? new Error('dependencies-out-of-date') : null); }); }; -}; \ No newline at end of file +}; From 92968dfd8d6db3fa28a409609abbe75ac55ea8b5 Mon Sep 17 00:00:00 2001 From: Mani Wang Date: Wed, 22 Jul 2015 19:49:15 +0800 Subject: [PATCH 05/24] avoid outdated error when use github address as module --- src/meta/dependencies.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/meta/dependencies.js b/src/meta/dependencies.js index 487640ee81..419708381f 100644 --- a/src/meta/dependencies.js +++ b/src/meta/dependencies.js @@ -23,7 +23,7 @@ module.exports = function(Meta) { var pkgData = JSON.parse(pkgData), ok = semver.satisfies(pkgData.version, pkg.dependencies[module]); - if (ok || pkgData._fromGithub) { + if (ok || pkgData._resolved.indexOf('//github.com') != -1) { next(true); } else { process.stdout.write('[' + 'outdated'.yellow + '] ' + module.bold + ' v' + pkgData.version + ', requires ' + pkg.dependencies[module] + '\n') From 29fcbf67507175be3526fcbefe000921115a1670 Mon Sep 17 00:00:00 2001 From: jsdream Date: Fri, 24 Jul 2015 18:18:22 +0300 Subject: [PATCH 06/24] Add 'filter:middleware.renderHeader' hook --- src/middleware/middleware.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/middleware/middleware.js b/src/middleware/middleware.js index 77951daf74..08241a7a59 100644 --- a/src/middleware/middleware.js +++ b/src/middleware/middleware.js @@ -286,7 +286,9 @@ middleware.renderHeader = function(req, res, callback) { templateValues.template = {name: res.locals.template}; templateValues.template[res.locals.template] = true; - app.render('header', templateValues, callback); + plugins.fireHook('filter:middleware.renderHeader', {templateValues: templateValues, req: req, res: res}, function(err, data) { + app.render('header', data.templateValues, callback); + }); }); }; @@ -495,4 +497,4 @@ module.exports = function(webserver) { middleware.admin = require('./admin')(webserver); return middleware; -}; \ No newline at end of file +}; From 5b87af4389b8c3dc0495cc51f86edc176b086c75 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Tue, 18 Aug 2015 14:17:16 -0400 Subject: [PATCH 07/24] closes #3447 recursively get all children calculate topic/post count from children new sorted set `cid::children` fix search query params --- public/src/app.js | 2 +- src/categories.js | 72 +++++++++++++++++++++++-------- src/categories/create.js | 5 ++- src/categories/delete.js | 17 ++++++++ src/categories/update.js | 48 ++++++++++++++++++++- src/controllers/categories.js | 17 ++------ src/controllers/search.js | 2 +- src/search.js | 11 +++-- src/sitemap.js | 2 +- src/socket.io/admin/categories.js | 2 +- src/socket.io/categories.js | 4 +- src/upgrade.js | 42 +++++++++++++++++- 12 files changed, 181 insertions(+), 43 deletions(-) diff --git a/public/src/app.js b/public/src/app.js index 5bcbb8201d..2e9b479ba6 100644 --- a/public/src/app.js +++ b/public/src/app.js @@ -503,7 +503,7 @@ app.cacheBuster = null; app.load = function() { $('document').ready(function () { - var url = ajaxify.start(window.location.pathname.slice(1), true, window.location.search); + var url = ajaxify.start(window.location.pathname.slice(1) + window.location.search, true); ajaxify.end(url, app.template); handleStatusChange(); diff --git a/src/categories.js b/src/categories.js index d30cd0c47a..f1a5ab23dd 100644 --- a/src/categories.js +++ b/src/categories.js @@ -103,10 +103,10 @@ var async = require('async'), }); }; - Categories.getCategoriesByPrivilege = function(uid, privilege, callback) { + Categories.getCategoriesByPrivilege = function(set, uid, privilege, callback) { async.waterfall([ function(next) { - db.getSortedSetRange('categories:cid', 0, -1, next); + db.getSortedSetRange(set, 0, -1, next); }, function(cids, next) { privileges.categories.filterCids(privilege, cids, uid, next); @@ -273,6 +273,7 @@ var async = require('async'), if (!category) { return; } + var postCount = parseInt(category.post_count, 10) || 0; var topicCount = parseInt(category.topic_count, 10) || 0; if (!Array.isArray(category.children) || !category.children.length) { @@ -282,9 +283,11 @@ var async = require('async'), } category.children.forEach(function(child) { - postCount += parseInt(child.post_count, 10) || 0; - topicCount += parseInt(child.topic_count, 10) || 0; + calculateTopicPostCount(child); + postCount += parseInt(child.totalPostCount, 10) || 0; + topicCount += parseInt(child.totalTopicCount, 10) || 0; }); + category.totalPostCount = postCount; category.totalTopicCount = topicCount; } @@ -308,23 +311,58 @@ var async = require('async'), }; Categories.getChildren = function(cids, uid, callback) { + var categories = cids.map(function(cid) { + return {cid: cid}; + }); + + async.each(categories, function(category, next) { + getChildrenRecursive(category, category.cid, uid, next); + }, function (err) { + callback(err, categories.map(function(c) { + return c && c.children; + })); + }); + }; + + function getChildrenRecursive(category, parentCid, uid, callback) { async.waterfall([ - async.apply(db.getSortedSetRange, 'categories:cid', 0, -1), - function(cids, next) { - privileges.categories.filterCids('find', cids, uid, next); + function (next) { + db.getSortedSetRange('cid:' + parentCid + ':children', 0, -1, next); }, - function (cids, next) { - Categories.getCategoriesData(cids, next); + function (children, next) { + privileges.categories.filterCids('find', children, uid, next); }, - function (categories, next) { - async.map(cids, function(cid, next) { - next(null, categories.filter(function(category) { - return category && parseInt(category.parentCid, 10) === parseInt(cid, 10); - })); + function (children, next) { + if (!children.length) { + category.children = []; + return callback(); + } + Categories.getCategoriesData(children, next); + }, + function (childrenData, next) { + category.children = childrenData; + async.each(category.children, function(child, next) { + getChildrenRecursive(child, child.cid, uid, next); }, next); } ], callback); - }; + } + + Categories.flattenCategories = function(allCategories, categoryData) { + categoryData.forEach(function(category) { + if (!category) { + return; + } + + if (!category.parent) { + allCategories.push(category); + } + + if (Array.isArray(category.children) && category.children.length) { + Categories.flattenCategories(allCategories, category.children); + } + }); + } /** * Recursively build tree @@ -335,13 +373,13 @@ var async = require('async'), Categories.getTree = function(categories, parentCid) { var tree = [], i = 0, len = categories.length, category; - for(i; i < len; ++i) { + for (i; i < len; ++i) { category = categories[i]; if (!category.hasOwnProperty('parentCid')) { category.parentCid = 0; } - if(category.parentCid == parentCid){ + if (category.parentCid == parentCid){ tree.push(category); category.children = Categories.getTree(categories, category.cid); } diff --git a/src/categories/create.js b/src/categories/create.js index 71eef4e72e..73a2591714 100644 --- a/src/categories/create.js +++ b/src/categories/create.js @@ -10,6 +10,8 @@ module.exports = function(Categories) { Categories.create = function(data, callback) { var category; + var parentCid = data.parentCid ? data.parentCid : 0; + async.waterfall([ function(next) { db.incrObjectField('global', 'nextCid', next); @@ -27,7 +29,7 @@ module.exports = function(Categories) { bgColor: data.bgColor || colours[0], color: data.color || colours[1], slug: slug, - parentCid: ( data.parentCid ? data.parentCid : 0 ), + parentCid: parentCid, topic_count: 0, post_count: 0, disabled: 0, @@ -48,6 +50,7 @@ module.exports = function(Categories) { async.series([ async.apply(db.setObject, 'category:' + category.cid, category), async.apply(db.sortedSetAdd, 'categories:cid', category.order, category.cid), + async.apply(db.sortedSetAdd, 'cid:' + parentCid + ':children', category.order, category.cid), async.apply(privileges.categories.give, defaultPrivileges, category.cid, 'administrators'), async.apply(privileges.categories.give, defaultPrivileges, category.cid, 'registered-users'), async.apply(privileges.categories.give, ['find', 'read'], category.cid, 'guests') diff --git a/src/categories/delete.js b/src/categories/delete.js index 1679ab6731..8483efaf72 100644 --- a/src/categories/delete.js +++ b/src/categories/delete.js @@ -30,15 +30,32 @@ module.exports = function(Categories) { function(next) { db.sortedSetRemove('categories:cid', cid, next); }, + function(next) { + removeFromParent(cid, next); + }, function(next) { db.deleteAll([ 'cid:' + cid + ':tids', 'cid:' + cid + ':tids:posts', 'cid:' + cid + ':pids', 'cid:' + cid + ':read_by_uid', + 'cid:' + cid + ':children', 'category:' + cid ], next); } ], callback); } + + function removeFromParent(cid, callback) { + async.waterfall([ + function(next) { + Categories.getCategoryField(cid, 'parentCid', next); + }, + function(parentCid, next) { + parentCid = parseInt(parentCid, 10) || 0; + db.sortedSetRemove('cid:' + parentCid + ':children', cid, next); + } + ], callback); + + } }; \ No newline at end of file diff --git a/src/categories/update.js b/src/categories/update.js index fb5cec5054..036b405c96 100644 --- a/src/categories/update.js +++ b/src/categories/update.js @@ -50,17 +50,63 @@ module.exports = function(Categories) { }; function updateCategoryField(cid, key, value, callback) { + if (key === 'parentCid') { + return updateParent(cid, value, callback); + } + db.setObjectField('category:' + cid, key, value, function(err) { if (err) { return callback(err); } if (key === 'order') { - db.sortedSetAdd('categories:cid', value, cid, callback); + updateOrder(cid, value, callback); } else { callback(); } }); } + function updateParent(cid, newParent, callback) { + Categories.getCategoryField(cid, 'parentCid', function(err, oldParent) { + if (err) { + return callback(err); + } + + async.series([ + function (next) { + oldParent = parseInt(oldParent, 10) || 0; + db.sortedSetRemove('cid:' + oldParent + ':children', cid, next); + }, + function (next) { + newParent = parseInt(newParent, 10) || 0; + db.sortedSetAdd('cid:' + newParent + ':children', cid, cid, next); + }, + function (next) { + db.setObjectField('category:' + cid, 'parentCid', newParent, next); + } + ], function(err, results) { + callback(err); + }); + }); + } + + function updateOrder(cid, order, callback) { + Categories.getCategoryField(cid, 'parentCid', function(err, parentCid) { + if (err) { + return callback(err); + } + + async.parallel([ + function (next) { + db.sortedSetAdd('categories:cid', order, cid, next); + }, + function (next) { + parentCid = parseInt(parentCid, 10) || 0; + db.sortedSetAdd('cid:' + parentCid + ':children', order, cid, next); + } + ], callback); + }); + } + }; diff --git a/src/controllers/categories.js b/src/controllers/categories.js index bbffcf1a86..bae16adc3b 100644 --- a/src/controllers/categories.js +++ b/src/controllers/categories.js @@ -33,7 +33,7 @@ categoriesController.list = function(req, res, next) { content: 'website' }]; - if(meta.config['brand:logo']) { + if (meta.config['brand:logo']) { res.locals.metaTags.push({ property: 'og:image', content: meta.config['brand:logo'] @@ -46,22 +46,13 @@ categoriesController.list = function(req, res, next) { var categoryData; async.waterfall([ function(next) { - categories.getCategoriesByPrivilege(req.uid, 'find', next); + categories.getCategoriesByPrivilege('cid:0:children', req.uid, 'find', next); }, function(_categoryData, next) { categoryData = _categoryData; + var allCategories = []; - - categoryData = categoryData.filter(function(category) { - if (!category.parent) { - allCategories.push(category); - } - - if (Array.isArray(category.children) && category.children.length) { - allCategories.push.apply(allCategories, category.children); - } - return category && !category.parent; - }); + categories.flattenCategories(allCategories, categoryData); categories.getRecentTopicReplies(allCategories, req.uid, next); } diff --git a/src/controllers/search.js b/src/controllers/search.js index 6637acbbc3..2148e6644b 100644 --- a/src/controllers/search.js +++ b/src/controllers/search.js @@ -17,7 +17,7 @@ searchController.search = function(req, res, next) { var breadcrumbs = helpers.buildBreadcrumbs([{text: '[[global:search]]'}]); - categories.getCategoriesByPrivilege(req.uid, 'read', function(err, categories) { + categories.getCategoriesByPrivilege('categories:cid', req.uid, 'read', function(err, categories) { if (err) { return next(err); } diff --git a/src/search.js b/src/search.js index 09e22a7a44..127588a5cd 100644 --- a/src/search.js +++ b/src/search.js @@ -417,11 +417,14 @@ function getChildrenCids(cids, uid, callback) { } var childrenCids = []; + var allCategories = []; + childrenCategories.forEach(function(childrens) { - childrenCids = childrenCids.concat(childrens.map(function(category) { - return category && category.cid; - })); - }); + categories.flattenCategories(allCategories, childrens); + childrenCids = childrenCids.concat(allCategories.map(function(category) { + return category && category.cid; + })); + }); callback(null, childrenCids); }); diff --git a/src/sitemap.js b/src/sitemap.js index eaf7686acd..a1fc3731d9 100644 --- a/src/sitemap.js +++ b/src/sitemap.js @@ -61,7 +61,7 @@ sitemap.getDynamicUrls = function(callback) { async.parallel({ categoryUrls: function(next) { var categoryUrls = []; - categories.getCategoriesByPrivilege(0, 'find', function(err, categoriesData) { + categories.getCategoriesByPrivilege('categories:cid', 0, 'find', function(err, categoriesData) { if (err) { return next(err); } diff --git a/src/socket.io/admin/categories.js b/src/socket.io/admin/categories.js index ea7ad27780..e1e72c5ec8 100644 --- a/src/socket.io/admin/categories.js +++ b/src/socket.io/admin/categories.js @@ -20,7 +20,7 @@ Categories.create = function(socket, data, callback) { Categories.getAll = function(socket, data, callback) { async.waterfall([ - async.apply(db.getSortedSetRangeByScore, 'categories:cid', 0, -1, 0, Date.now()), + async.apply(db.getSortedSetRange, 'categories:cid', 0, -1), async.apply(categories.getCategoriesData), function(categories, next) { //Hook changes, there is no req, and res diff --git a/src/socket.io/categories.js b/src/socket.io/categories.js index 0c1af11388..b437349ded 100644 --- a/src/socket.io/categories.js +++ b/src/socket.io/categories.js @@ -15,7 +15,7 @@ SocketCategories.getRecentReplies = function(socket, cid, callback) { }; SocketCategories.get = function(socket, data, callback) { - categories.getCategoriesByPrivilege(socket.uid, 'find', callback); + categories.getCategoriesByPrivilege('categories:cid', socket.uid, 'find', callback); }; SocketCategories.getWatchedCategories = function(socket, data, callback) { @@ -117,7 +117,7 @@ SocketCategories.getUsersInCategory = function(socket, cid, callback) { }; SocketCategories.getCategoriesByPrivilege = function(socket, privilege, callback) { - categories.getCategoriesByPrivilege(socket.uid, privilege, callback); + categories.getCategoriesByPrivilege('categories:cid', socket.uid, privilege, callback); }; SocketCategories.watch = function(socket, cid, callback) { diff --git a/src/upgrade.js b/src/upgrade.js index 6d985264b9..01c3da455c 100644 --- a/src/upgrade.js +++ b/src/upgrade.js @@ -21,7 +21,7 @@ var db = require('./database'), schemaDate, thisSchemaDate, // IMPORTANT: REMEMBER TO UPDATE VALUE OF latestSchema - latestSchema = Date.UTC(2015, 6, 3); + latestSchema = Date.UTC(2015, 7, 18); Upgrade.check = function(callback) { db.get('schemaDate', function(err, value) { @@ -446,6 +446,46 @@ Upgrade.upgrade = function(callback) { winston.info('[2015/07/03] Enabling default composer plugin skipped'); next(); } + }, + function(next) { + thisSchemaDate = Date.UTC(2015, 7, 18); + if (schemaDate < thisSchemaDate) { + updatesMade = true; + winston.info('[2015/08/18] Creating children category sorted sets'); + + db.getSortedSetRange('categories:cid', 0, -1, function(err, cids) { + if (err) { + return next(err); + } + + async.each(cids, function(cid, next) { + db.getObjectFields('category:' + cid, ['parentCid', 'order'], function(err, category) { + if (err) { + return next(err); + } + if (!category) { + return next(); + } + if (parseInt(category.parentCid, 10)) { + db.sortedSetAdd('cid:' + category.parentCid + ':children', parseInt(category.order, 10), cid, next); + } else { + db.sortedSetAdd('cid:0:children', parseInt(category.order, 10), cid, next); + } + }); + }, function(err) { + if (err) { + return next(err); + } + + winston.info('[2015/08/18] Creating children category sorted sets done'); + Upgrade.update(thisSchemaDate, next); + }); + }); + + } else { + winston.info('[2015/08/18] Creating children category sorted sets skipped'); + next(); + } } From 7bd98a25168a8b6c23d70152d4a37906d01bca60 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Tue, 18 Aug 2015 15:01:36 -0400 Subject: [PATCH 08/24] closes #3427 --- src/emailer.js | 1 + src/views/admin/settings/email.tpl | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/src/emailer.js b/src/emailer.js index a4f2c407bd..14c683d640 100644 --- a/src/emailer.js +++ b/src/emailer.js @@ -71,6 +71,7 @@ var fs = require('fs'), Plugins.fireHook('action:email.send', { to: email, from: meta.config['email:from'] || 'no-reply@localhost.lan', + from_name: meta.config['email:from_name'] || 'NodeBB', subject: translated[2], html: translated[0], plaintext: translated[1], diff --git a/src/views/admin/settings/email.tpl b/src/views/admin/settings/email.tpl index e86eba17cc..6d996900e4 100644 --- a/src/views/admin/settings/email.tpl +++ b/src/views/admin/settings/email.tpl @@ -14,6 +14,13 @@


+
+ +

+ The from name to display in the email. +

+
+

The test email will be sent to the currently logged in user's email address. From 830d27caef6fe041b0b82f81b085f2c0825bf2f9 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Tue, 18 Aug 2015 15:17:07 -0400 Subject: [PATCH 09/24] dont ignore error --- src/image.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/image.js b/src/image.js index 078b2d134d..d35040ff9d 100644 --- a/src/image.js +++ b/src/image.js @@ -18,12 +18,16 @@ image.resizeImage = function(path, extension, width, height, callback) { }); } else { lwip.open(path, function(err, image) { + if (err) { + return callback(err); + } + image.batch() .cover(width, height) .crop(width, height) .writeFile(path, function(err) { - callback(err) - }) + callback(err); + }); }); } }; @@ -41,7 +45,7 @@ image.normalise = function(path, extension, callback) { if (err) { return callback(err); } - image.writeFile(path, 'png', callback) + image.writeFile(path, 'png', callback); }); } }; From c45e182bab87b1e45b31ce58f9e667337f01a4f3 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Tue, 18 Aug 2015 16:46:06 -0400 Subject: [PATCH 10/24] Fix ./nodebb upgrade process to not use programmatic npm - Closes #3451 - Apparently, programmatically invoking npm is like opening Pandora's box. No thanks. --- nodebb | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/nodebb b/nodebb index a93e40c785..d19833d010 100755 --- a/nodebb +++ b/nodebb @@ -5,8 +5,7 @@ var colors = require('colors'), argv = require('minimist')(process.argv.slice(2)), fs = require('fs'), async = require('async'), - touch = require('touch'), - npm = require('npm'); + touch = require('touch'); var getRunningPid = function(callback) { fs.readFile(__dirname + '/pidfile', { @@ -119,15 +118,12 @@ switch(process.argv[2]) { case 'upgrade': async.series([ function(next) { - process.stdout.write('1. '.bold + 'Bringing base dependencies up to date\n'.yellow); - npm.load({ - loglevel: 'silent' - }, function() { - npm.commands.install(next); - }); + process.stdout.write('1. '.bold + 'Bringing base dependencies up to date... '.yellow); + require('child_process').execFile('/usr/bin/env', ['npm', 'i', '--production'], next); }, function(next) { - process.stdout.write('2. '.bold + 'Updating NodeBB data store schema\n'.yellow); + process.stdout.write('OK\n'.green); + process.stdout.write('2. '.bold + 'Updating NodeBB data store schema.\n'.yellow); var upgradeProc = cproc.fork('app.js', ['--upgrade'], { cwd: __dirname, silent: false @@ -136,7 +132,7 @@ switch(process.argv[2]) { upgradeProc.on('close', next) }, function(next) { - process.stdout.write('3. '.bold + 'Storing upgrade date in "package.json"\n'.yellow); + process.stdout.write('3. '.bold + 'Storing upgrade date in "package.json"... '.yellow); touch(__dirname + '/package.json', {}, next); } ], function(err) { @@ -145,6 +141,8 @@ switch(process.argv[2]) { } else { var message = 'NodeBB Upgrade Complete!', spaces = new Array(Math.floor(process.stdout.columns / 2) - (message.length / 2) + 1).join(' '); + + process.stdout.write('OK\n'.green); process.stdout.write('\n' + spaces + message.green.bold + '\n\n'.reset); } }); From 5ababdbdf06554b904b0388613a3968602790628 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Tue, 18 Aug 2015 17:05:28 -0400 Subject: [PATCH 11/24] prevent crash if data.enter is not string --- public/src/app.js | 2 +- src/socket.io/meta.js | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/public/src/app.js b/public/src/app.js index 2e9b479ba6..1ea9bb1976 100644 --- a/public/src/app.js +++ b/public/src/app.js @@ -92,7 +92,7 @@ app.cacheBuster = null; switch(url_parts[0]) { case 'user': - room = 'user/' + ajaxify.data ? ajaxify.data.theirid : 0; + room = 'user/' + (ajaxify.data ? ajaxify.data.theirid : 0); break; case 'topic': room = 'topic_' + url_parts[1]; diff --git a/src/socket.io/meta.js b/src/socket.io/meta.js index 1e1843a1ca..f0c9dd58ae 100644 --- a/src/socket.io/meta.js +++ b/src/socket.io/meta.js @@ -59,6 +59,10 @@ SocketMeta.rooms.enter = function(socket, data, callback) { return callback(new Error('[[error:invalid-data]]')); } + if (data.enter) { + data.enter = data.enter.toString(); + } + if (data.enter && data.enter.startsWith('uid_') && data.enter !== 'uid_' + socket.uid) { return callback(new Error('[[error:not-allowed]]')); } From 537d539512c192a419fbc749a1e608b81816a8cb Mon Sep 17 00:00:00 2001 From: barisusakli Date: Tue, 18 Aug 2015 18:43:14 -0400 Subject: [PATCH 12/24] fix custom homepage --- src/controllers/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/controllers/index.js b/src/controllers/index.js index e7ca7e075f..0b99fea291 100644 --- a/src/controllers/index.js +++ b/src/controllers/index.js @@ -42,9 +42,9 @@ Controllers.home = function(req, res, next) { if (route === 'categories') { Controllers.categories.list(req, res, next); } else if (route === 'recent') { - Controllers.categories.recent(req, res, next); + Controllers.recent.get(req, res, next); } else if (route === 'popular') { - Controllers.categories.popular(req, res, next); + Controllers.popular.get(req, res, next); } else { next(); } From 7a8cdfc0955719cb0c137570cbb46eacacef5290 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Wed, 19 Aug 2015 01:16:30 -0400 Subject: [PATCH 13/24] added core field --- src/controllers/users.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/controllers/users.js b/src/controllers/users.js index b2b9c32233..abff42a4de 100644 --- a/src/controllers/users.js +++ b/src/controllers/users.js @@ -157,6 +157,7 @@ usersController.getMap = function(req, res, next) { } data.room = validator.escape(categoryData.name); data.link = '/category/' + categoryData.slug; + data.core = false; next(null, data); }); } else if (roomName.startsWith('topic_')) { @@ -167,13 +168,18 @@ usersController.getMap = function(req, res, next) { } data.room = validator.escape(topicData.title); data.link = '/topic/' + topicData.slug; + data.core = false; next(null, data); }); } else { + data.core = true; next(null, data); } }); }, function(err, data) { + if (err) { + return next(err); + } data.sort(function(a, b) { return b.total - a.total; }); From d07fca6907e03979402b6936ffda5112800386cc Mon Sep 17 00:00:00 2001 From: barisusakli Date: Wed, 19 Aug 2015 01:21:12 -0400 Subject: [PATCH 14/24] update theme versions --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 0e47780a71..cfc263ae50 100644 --- a/package.json +++ b/package.json @@ -49,8 +49,8 @@ "nodebb-plugin-spam-be-gone": "0.4.1", "nodebb-rewards-essentials": "0.0.3", "nodebb-theme-lavender": "1.0.49", - "nodebb-theme-persona": "2.0.13", - "nodebb-theme-vanilla": "3.0.7", + "nodebb-theme-persona": "2.0.14", + "nodebb-theme-vanilla": "3.0.8", "nodebb-widget-essentials": "1.0.4", "npm": "^2.1.4", "passport": "^0.2.1", From aec4ee53921e2f35b56af52e18dd36a8cf1792c4 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Wed, 19 Aug 2015 12:47:57 -0400 Subject: [PATCH 15/24] crash fix --- src/middleware/middleware.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/middleware/middleware.js b/src/middleware/middleware.js index 6bab0678e6..e4e5ebbc6f 100644 --- a/src/middleware/middleware.js +++ b/src/middleware/middleware.js @@ -297,7 +297,7 @@ middleware.renderHeader = function(req, res, callback) { templateValues.customCSS = results.customCSS; templateValues.customJS = results.customJS; templateValues.maintenanceHeader = parseInt(meta.config.maintenanceMode, 10) === 1 && !results.isAdmin; - templateValues.defaultLang = res.locals.config.defaultLang; + templateValues.defaultLang = meta.config.defaultLang || 'en_GB'; templateValues.template = {name: res.locals.template}; templateValues.template[res.locals.template] = true; From 878690e5f7d006ee77f3e9f9cef45b9747746c19 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Wed, 19 Aug 2015 13:37:48 -0400 Subject: [PATCH 16/24] removed extra param --- src/categories.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/categories.js b/src/categories.js index f1a5ab23dd..0626de3349 100644 --- a/src/categories.js +++ b/src/categories.js @@ -316,7 +316,7 @@ var async = require('async'), }); async.each(categories, function(category, next) { - getChildrenRecursive(category, category.cid, uid, next); + getChildrenRecursive(category, uid, next); }, function (err) { callback(err, categories.map(function(c) { return c && c.children; @@ -324,10 +324,10 @@ var async = require('async'), }); }; - function getChildrenRecursive(category, parentCid, uid, callback) { + function getChildrenRecursive(category, uid, callback) { async.waterfall([ function (next) { - db.getSortedSetRange('cid:' + parentCid + ':children', 0, -1, next); + db.getSortedSetRange('cid:' + category.cid + ':children', 0, -1, next); }, function (children, next) { privileges.categories.filterCids('find', children, uid, next); @@ -342,7 +342,7 @@ var async = require('async'), function (childrenData, next) { category.children = childrenData; async.each(category.children, function(child, next) { - getChildrenRecursive(child, child.cid, uid, next); + getChildrenRecursive(child, uid, next); }, next); } ], callback); @@ -362,7 +362,7 @@ var async = require('async'), Categories.flattenCategories(allCategories, category.children); } }); - } + }; /** * Recursively build tree From 67e450a05b6c47a509f36e08610efb0c4ba31ed7 Mon Sep 17 00:00:00 2001 From: yariplus Date: Wed, 22 Jul 2015 04:52:54 -0400 Subject: [PATCH 17/24] Fix issues with acp category page strange name for background size variable invalid class selectors hijacking of background style --- public/src/admin/manage/category.js | 12 ++++++++---- src/views/admin/manage/category.tpl | 4 ++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/public/src/admin/manage/category.js b/public/src/admin/manage/category.js index 02dfeee2f3..301535314f 100644 --- a/public/src/admin/manage/category.js +++ b/public/src/admin/manage/category.js @@ -50,11 +50,11 @@ define('admin/manage/category', [ function enableColorPicker(idx, inputEl) { var $inputEl = $(inputEl), - previewEl = $inputEl.parents('[data-cid]').find('.preview-box'); + previewEl = $inputEl.parents('[data-cid]').find('.category-preview'); colorpicker.enable($inputEl, function(hsb, hex) { if ($inputEl.attr('data-name') === 'bgColor') { - previewEl.css('background', '#' + hex); + previewEl.css('background-color', '#' + hex); } else if ($inputEl.attr('data-name') === 'color') { previewEl.css('color', '#' + hex); } @@ -83,6 +83,11 @@ define('admin/manage/category', [ modified(ev.target); }); + // Update preview image size on change + $('[data-name="imageClass"]').on('change', function(ev) { + $('.category-preview').css('background-size', $(this).val()); + }); + // Colour Picker $('[data-name="bgColor"], [data-name="color"]').each(enableColorPicker); @@ -113,8 +118,7 @@ define('admin/manage/category', [ uploader.open(RELATIVE_PATH + '/api/admin/category/uploadpicture', { cid: cid }, 0, function(imageUrlOnServer) { inputEl.val(imageUrlOnServer); var previewBox = inputEl.parent().parent().siblings('.category-preview'); - previewBox.css('background', 'url(' + imageUrlOnServer + '?' + new Date().getTime() + ')') - .css('background-size', 'cover'); + previewBox.css('background', 'url(' + imageUrlOnServer + '?' + new Date().getTime() + ')'); modified(inputEl[0]); }); }); diff --git a/src/views/admin/manage/category.tpl b/src/views/admin/manage/category.tpl index ee53173869..781d0c349b 100644 --- a/src/views/admin/manage/category.tpl +++ b/src/views/admin/manage/category.tpl @@ -41,7 +41,7 @@

- +