From c74d32a1728fb9d20c19136bf1bb30377634209d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Thu, 7 May 2015 14:44:01 -0400 Subject: [PATCH 01/11] fix off by 1 error on user/topics posts #3120 --- src/controllers/accounts.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controllers/accounts.js b/src/controllers/accounts.js index a0283f0401..5552fa53be 100644 --- a/src/controllers/accounts.js +++ b/src/controllers/accounts.js @@ -298,7 +298,7 @@ function getFromUserSet(tpl, set, method, type, req, res, next) { }, data: function(next) { var start = (page - 1) * itemsPerPage; - var stop = start + itemsPerPage; + var stop = start + itemsPerPage - 1; method(setName, req.uid, start, stop, next); } }, function(err, results) { From b08774763ace2a380c8ab17a348177c59b4a1d23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Thu, 7 May 2015 15:27:01 -0400 Subject: [PATCH 02/11] added tpl to ajaxify.content-loaded --- public/src/ajaxify.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/src/ajaxify.js b/public/src/ajaxify.js index 43190850da..5ab08eb0fa 100644 --- a/public/src/ajaxify.js +++ b/public/src/ajaxify.js @@ -158,7 +158,7 @@ $(document).ready(function() { $(window).trigger('action:ajaxify.end', {url: url}); }); - $(window).trigger('action:ajaxify.contentLoaded', {url: url}); + $(window).trigger('action:ajaxify.contentLoaded', {url: url, tpl: tpl_url}); app.processPage(); }; From 9d273d3a32f3a1a19a0a71a7d230632d65c46d95 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Thu, 7 May 2015 22:40:32 -0400 Subject: [PATCH 03/11] fixed date log --- src/upgrade.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/upgrade.js b/src/upgrade.js index da5edb4a36..c0aa5b1d86 100644 --- a/src/upgrade.js +++ b/src/upgrade.js @@ -989,7 +989,7 @@ Upgrade.upgrade = function(callback) { thisSchemaDate = Date.UTC(2015, 4, 7); if (schemaDate < thisSchemaDate) { updatesMade = true; - winston.info('[2015/02/25] Upgrading uid mappings to sorted set'); + winston.info('[2015/05/07] Upgrading uid mappings to sorted set'); async.series([ async.apply(upgradeHashToSortedSet, 'email:uid'), From ffac8eb41d0fe2664bb2bf0b1ec51c89c2a08692 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Thu, 7 May 2015 23:24:33 -0400 Subject: [PATCH 04/11] closes #3118 --- public/src/client/account/settings.js | 6 +++--- src/groups.js | 21 +++++++++++---------- src/user/settings.js | 13 +++++++++++++ 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/public/src/client/account/settings.js b/public/src/client/account/settings.js index 20b33a613b..f5f9ab4e32 100644 --- a/public/src/client/account/settings.js +++ b/public/src/client/account/settings.js @@ -41,8 +41,8 @@ define('forum/account/settings', ['forum/account/header'], function(header) { if (newSettings.hasOwnProperty(key)) { if (key === 'userLang' && config.userLang !== newSettings.userLang) { requireReload = true; - } - config[key] = newSettings[key]; + } + config[key] = newSettings[key]; } } app.exposeConfigToTemplates(); @@ -70,7 +70,7 @@ define('forum/account/settings', ['forum/account/header'], function(header) { var setting = input.attr('data-property'); if (setting) { if (input.is('select')) { - input.val(settings[setting]); + input.val(settings[setting] || ''); return; } diff --git a/src/groups.js b/src/groups.js index 632a51f805..4f52d2bc9f 100644 --- a/src/groups.js +++ b/src/groups.js @@ -760,17 +760,18 @@ var async = require('async'), tasks.push(async.apply(db.setAdd, 'group:' + groupName + ':owners', uid)); } async.parallel(tasks, next); + }, + function(results, next) { + user.setGroupTitle(groupName, uid, next); + }, + function(next) { + plugins.fireHook('action:group.join', { + groupName: groupName, + uid: uid + }); + next(); } - ], function(err, results) { - if (err) { - return callback(err); - } - plugins.fireHook('action:group.join', { - groupName: groupName, - uid: uid - }); - callback(); - }); + ], callback); } callback = callback || function() {}; diff --git a/src/user/settings.js b/src/user/settings.js index 7c12cbfd00..ec493457aa 100644 --- a/src/user/settings.js +++ b/src/user/settings.js @@ -143,4 +143,17 @@ module.exports = function(User) { User.setSetting = function(uid, key, value, callback) { db.setObjectField('user:' + uid + ':settings', key, value, callback); }; + + User.setGroupTitle = function(groupName, uid, callback) { + if (groupName === 'registered-users') { + return callback(); + } + db.getObjectField('user:' + uid + ':settings', 'groupTitle', function(err, currentTitle) { + if (err || (currentTitle || currentTitle === '')) { + return callback(err); + } + + User.setSetting(uid, 'groupTitle', groupName, callback); + }); + }; }; From 27bf1c1b2edb76239f333286f7c14c4136f1c32b Mon Sep 17 00:00:00 2001 From: barisusakli Date: Fri, 8 May 2015 13:35:54 -0400 Subject: [PATCH 05/11] fix privilege upgrade script --- src/upgrade.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/upgrade.js b/src/upgrade.js index c0aa5b1d86..c6574ab574 100644 --- a/src/upgrade.js +++ b/src/upgrade.js @@ -233,18 +233,17 @@ Upgrade.upgrade = function(callback) { var privs = ['find', 'read', 'topics:reply', 'topics:create']; async.each(privs, function(priv, next) { - categoryHasPrivilegesSet(cid, priv, function(err, privilegesSet) { if (err || privilegesSet) { return next(err); } async.eachLimit(groups, 50, function(group, next) { - if (group && !group.hidden) { - if (group.name === 'guests' && (priv === 'topics:reply' || priv === 'topics:create')) { + if (group) { + if (group === 'guests' && (priv === 'topics:reply' || priv === 'topics:create')) { return next(); } - Groups.join('cid:' + cid + ':privileges:groups:' + priv, group.name, next); + Groups.join('cid:' + cid + ':privileges:groups:' + priv, group, next); } else { next(); } From 732f6d7d80c75e19c8579954dcf2d27634be1dee Mon Sep 17 00:00:00 2001 From: pichalite Date: Fri, 8 May 2015 11:18:43 -0700 Subject: [PATCH 06/11] Update plugins.tpl --- src/views/admin/extend/plugins.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/admin/extend/plugins.tpl b/src/views/admin/extend/plugins.tpl index 72c7228d0e..90611e6d47 100644 --- a/src/views/admin/extend/plugins.tpl +++ b/src/views/admin/extend/plugins.tpl @@ -73,7 +73,7 @@ Latest {plugins.latest} -

For more information: {plugins.url}

+

For more information: {plugins.url}

From 0083d4ff1c136a7b46e33fd617458a1da7a3c5a2 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Fri, 8 May 2015 14:53:08 -0400 Subject: [PATCH 07/11] return user settings in api --- public/src/client/account/settings.js | 25 ---------- src/controllers/accounts.js | 71 +++++++++++++++++---------- src/socket.io/user.js | 20 -------- 3 files changed, 46 insertions(+), 70 deletions(-) diff --git a/public/src/client/account/settings.js b/public/src/client/account/settings.js index f5f9ab4e32..848bf8c1ef 100644 --- a/public/src/client/account/settings.js +++ b/public/src/client/account/settings.js @@ -61,31 +61,6 @@ define('forum/account/settings', ['forum/account/header'], function(header) { return false; }); - - socket.emit('user.getSettings', {uid: ajaxify.variables.get('theirid')}, function(err, settings) { - var inputs = $('.account').find('input, textarea, select'); - - inputs.each(function(index, input) { - input = $(input); - var setting = input.attr('data-property'); - if (setting) { - if (input.is('select')) { - input.val(settings[setting] || ''); - return; - } - - switch (input.attr('type')) { - case 'text' : - case 'textarea' : - input.val(settings[setting]); - break; - case 'checkbox' : - input.prop('checked', !!settings[setting]); - break; - } - } - }); - }); }; return AccountSettings; diff --git a/src/controllers/accounts.js b/src/controllers/accounts.js index 5552fa53be..f159058586 100644 --- a/src/controllers/accounts.js +++ b/src/controllers/accounts.js @@ -375,38 +375,59 @@ accountsController.accountEdit = function(req, res, next) { }; accountsController.accountSettings = function(req, res, next) { - accountsController.getBaseUser(req.params.userslug, req.uid, function(err, userData) { + var userData; + async.waterfall([ + function(next) { + accountsController.getBaseUser(req.params.userslug, req.uid, next); + }, + function(_userData, next) { + userData = _userData; + if (!userData) { + return helpers.notFound(req, res); + } + async.parallel({ + settings: function(next) { + user.getSettings(userData.uid, next); + }, + userGroups: function(next) { + groups.getUserGroups([userData.uid], next); + }, + languages: function(next) { + languages.list(next); + } + }, next); + }, + function(results, next) { + userData.languages = results.languages; + userData.userGroups = results.userGroups[0]; + plugins.fireHook('filter:user.settings', {settings: results.settings, uid: req.uid}, next); + }, + function(data, next) { + userData.settings = data.settings; + userData.disableEmailSubscriptions = parseInt(meta.config.disableEmailSubscriptions, 10) === 1; + next(); + } + ], function(err) { if (err) { return next(err); } - if (!userData) { - return helpers.notFound(req, res); - } + userData.dailyDigestFreqOptions = [ + {value: 'off', name: '[[user:digest_off]]', selected: 'off' === userData.settings.dailyDigestFreq}, + {value: 'day', name: '[[user:digest_daily]]', selected: 'day' === userData.settings.dailyDigestFreq}, + {value: 'week', name: '[[user:digest_weekly]]', selected: 'week' === userData.settings.dailyDigestFreq}, + {value: 'month', name: '[[user:digest_monthly]]', selected: 'month' === userData.settings.dailyDigestFreq} + ]; - async.parallel({ - settings: function(next) { - plugins.fireHook('filter:user.settings', [], next); - }, - userGroups: function(next) { - groups.getUserGroups([userData.uid], next); - }, - languages: function(next) { - languages.list(next); - } - }, function(err, results) { - if (err) { - return next(err); - } - - userData.settings = results.settings; - userData.languages = results.languages; - userData.userGroups = results.userGroups[0]; - - userData.disableEmailSubscriptions = parseInt(meta.config.disableEmailSubscriptions, 10) === 1; + userData.userGroups.forEach(function(group) { + group.selected = group.name === userData.settings.groupTitle; + }); - res.render('account/settings', userData); + userData.languages.forEach(function(language) { + language.selected = language.code === userData.settings.language; }); + + res.render('account/settings', userData); }); }; diff --git a/src/socket.io/user.js b/src/socket.io/user.js index 0df36121e8..65af901b08 100644 --- a/src/socket.io/user.js +++ b/src/socket.io/user.js @@ -340,26 +340,6 @@ function toggleFollow(method, uid, theiruid, callback) { }); } -SocketUser.getSettings = function(socket, data, callback) { - if (socket.uid) { - if (socket.uid === parseInt(data.uid, 10)) { - return user.getSettings(socket.uid, callback); - } - - user.isAdministrator(socket.uid, function(err, isAdmin) { - if (err) { - return callback(err); - } - - if (!isAdmin) { - return callback(new Error('[[error:no-privileges]]')); - } - - user.getSettings(data.uid, callback); - }); - } -}; - SocketUser.saveSettings = function(socket, data, callback) { if (!socket.uid || !data) { return callback(new Error('[[error:invalid-data]]')); From 7b550b13b98ea9b34dcf85ba645f3ed80215ea04 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Fri, 8 May 2015 15:36:06 -0400 Subject: [PATCH 08/11] display both redis/mongo info if available --- src/controllers/admin.js | 25 ++++++++++++-- src/database/mongo.js | 18 ++++++++++ src/database/mongo/main.js | 18 ---------- src/database/redis.js | 22 +++++++++++++ src/database/redis/main.js | 20 ------------ src/views/admin/advanced/database.tpl | 47 +++++++++++++++++++-------- 6 files changed, 96 insertions(+), 54 deletions(-) diff --git a/src/controllers/admin.js b/src/controllers/admin.js index 52cf194353..4487167873 100644 --- a/src/controllers/admin.js +++ b/src/controllers/admin.js @@ -211,8 +211,29 @@ adminController.flags.get = function(req, res, next) { }; adminController.database.get = function(req, res, next) { - db.info(function (err, data) { - res.render('admin/advanced/database', data); + async.parallel({ + redis: function(next) { + if (nconf.get('redis')) { + var rdb = require('../database/redis'); + var cxn = rdb.connect(); + rdb.info(cxn, next); + } else { + next(); + } + }, + mongo: function(next) { + if (nconf.get('mongo')) { + var mdb = require('../database/mongo'); + mdb.info(mdb.client, next); + } else { + next(); + } + } + }, function(err, results) { + if (err) { + return next(err); + } + res.render('admin/advanced/database', results); }); }; diff --git a/src/database/mongo.js b/src/database/mongo.js index e031132b99..63fdc8b9c2 100644 --- a/src/database/mongo.js +++ b/src/database/mongo.js @@ -158,6 +158,24 @@ }); }; + module.info = function(db, callback) { + db.stats({scale:1024}, function(err, stats) { + if(err) { + return callback(err); + } + + stats.avgObjSize = (stats.avgObjSize / 1024).toFixed(2); + stats.dataSize = (stats.dataSize / 1024).toFixed(2); + stats.storageSize = (stats.storageSize / 1024).toFixed(2); + stats.fileSize = (stats.fileSize / 1024).toFixed(2); + stats.indexSize = (stats.indexSize / 1024).toFixed(2); + stats.raw = JSON.stringify(stats, null, 4); + stats.mongo = true; + + callback(null, stats); + }); + }; + module.close = function() { db.close(); }; diff --git a/src/database/mongo/main.js b/src/database/mongo/main.js index eba0b3b14b..7ba58499d3 100644 --- a/src/database/mongo/main.js +++ b/src/database/mongo/main.js @@ -79,24 +79,6 @@ module.exports = function(db, module) { db.dropDatabase(callback); }; - module.info = function(callback) { - db.stats({scale:1024}, function(err, stats) { - if(err) { - return callback(err); - } - - stats.avgObjSize = (stats.avgObjSize / 1024).toFixed(2); - stats.dataSize = (stats.dataSize / 1024).toFixed(2); - stats.storageSize = (stats.storageSize / 1024).toFixed(2); - stats.fileSize = (stats.fileSize / 1024).toFixed(2); - stats.indexSize = (stats.indexSize / 1024).toFixed(2); - stats.raw = JSON.stringify(stats, null, 4); - stats.mongo = true; - - callback(null, stats); - }); - }; - module.exists = function(key, callback) { if (!key) { return callback(); diff --git a/src/database/redis.js b/src/database/redis.js index 8e06ce837a..1c224276cc 100644 --- a/src/database/redis.js +++ b/src/database/redis.js @@ -115,6 +115,28 @@ redisClient.quit(); }; + module.info = function(cxn, callback) { + cxn.info(function (err, data) { + if (err) { + return callback(err); + } + + var lines = data.toString().split("\r\n").sort(); + var redisData = {}; + lines.forEach(function (line) { + var parts = line.split(':'); + if (parts[1]) { + redisData[parts[0]] = parts[1]; + } + }); + + redisData.raw = JSON.stringify(redisData, null, 4); + redisData.redis = true; + + callback(null, redisData); + }); + }; + module.helpers = module.helpers || {}; module.helpers.redis = require('./redis/helpers'); }(exports)); diff --git a/src/database/redis/main.js b/src/database/redis/main.js index 84e31eaae4..503d515569 100644 --- a/src/database/redis/main.js +++ b/src/database/redis/main.js @@ -35,27 +35,7 @@ module.exports = function(redisClient, module) { }); }; - module.info = function(callback) { - redisClient.info(function (err, data) { - if(err) { - return callback(err); - } - - var lines = data.toString().split("\r\n").sort(); - var redisData = {}; - lines.forEach(function (line) { - var parts = line.split(':'); - if (parts[1]) { - redisData[parts[0]] = parts[1]; - } - }); - - redisData.raw = JSON.stringify(redisData, null, 4); - redisData.redis = true; - callback(null, redisData); - }); - }; module.exists = function(key, callback) { redisClient.exists(key, function(err, exists) { diff --git a/src/views/admin/advanced/database.tpl b/src/views/admin/advanced/database.tpl index e08daac3f7..740418fc35 100644 --- a/src/views/admin/advanced/database.tpl +++ b/src/views/admin/advanced/database.tpl @@ -1,5 +1,23 @@
+ +
+
Mongo
+
+
+ Collections {collections}
+ Objects {objects}
+ Avg. Object Size {avgObjSize} kb
+
+ Data Size {dataSize} mb
+ Storage Size {storageSize} mb
+ Index Size {indexSize} mb
+ File Size {fileSize} mb
+
+
+
+ +
Redis
@@ -31,29 +49,30 @@
-
Mongo
-
-
- Collections {collections}
- Objects {objects}
- Avg. Object Size {avgObjSize} kb
-
- Data Size {dataSize} mb
- Storage Size {storageSize} mb
- Index Size {indexSize} mb
- File Size {fileSize} mb
+
+

MongoDB Raw Info

+
+ +
+
+
{mongo.raw}
+
-
Raw Info
-
+
+

Redis Raw Info

+
+ +
-
{raw}
+
{redis.raw}
+
From c6a05930aac1238096c39f5ad9a1c62d9e08c60f Mon Sep 17 00:00:00 2001 From: barisusakli Date: Fri, 8 May 2015 16:14:32 -0400 Subject: [PATCH 09/11] fix \uff0e in emails --- src/upgrade.js | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/src/upgrade.js b/src/upgrade.js index c6574ab574..0d6e0a8312 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, 4, 7); + latestSchema = Date.UTC(2015, 4, 8); Upgrade.check = function(callback) { db.get('schemaDate', function(err, value) { @@ -1008,6 +1008,39 @@ Upgrade.upgrade = function(callback) { winston.info('[2015/05/07] Upgrading uid mappings to sorted set skipped'); next(); } + }, + function(next) { + if (schemaDate < thisSchemaDate) { + updatesMade = true; + winston.info('[2015/05/08] Fixing emails'); + + db.getSortedSetRangeWithScores('email:uid', 0, -1, function(err, users) { + if (err) { + return next(err); + } + + var newEmail = user.value.replace(/\uff0E/g, '.'); + if (newEmail === user.value) { + return next(); + } + async.series([ + async.apply(db.sortedSetRemove, 'email:uid', user.value), + async.apply(db.sortedSetAdd, 'email:uid', user.score, newEmail) + ], next); + + }, function(err) { + if (err) { + return next(err); + } + winston.info('[2015/05/08] Fixing emails done'); + Upgrade.update(thisSchemaDate, next); + }); + }); + + } else { + winston.info('[2015/05/08] Fixing emails skipped'); + next(); + } } // Add new schema updates here From 74d610407294ebf50324e90e39b1b20ffbdafe63 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Fri, 8 May 2015 16:14:48 -0400 Subject: [PATCH 10/11] correct upgrade date --- src/upgrade.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/upgrade.js b/src/upgrade.js index 0d6e0a8312..1044cde651 100644 --- a/src/upgrade.js +++ b/src/upgrade.js @@ -1010,6 +1010,7 @@ Upgrade.upgrade = function(callback) { } }, function(next) { + thisSchemaDate = Date.UTC(2015, 4, 8); if (schemaDate < thisSchemaDate) { updatesMade = true; winston.info('[2015/05/08] Fixing emails'); @@ -1019,6 +1020,7 @@ Upgrade.upgrade = function(callback) { return next(err); } + async.eachLimit(users, 100, function(user, next) { var newEmail = user.value.replace(/\uff0E/g, '.'); if (newEmail === user.value) { return next(); From 9518c006b5ed5e44b9ac6b4517f530e5c1ebbd54 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Fri, 8 May 2015 18:42:44 -0400 Subject: [PATCH 11/11] fix userlang --- src/controllers/accounts.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controllers/accounts.js b/src/controllers/accounts.js index f159058586..e8071ec8ad 100644 --- a/src/controllers/accounts.js +++ b/src/controllers/accounts.js @@ -424,7 +424,7 @@ accountsController.accountSettings = function(req, res, next) { }); userData.languages.forEach(function(language) { - language.selected = language.code === userData.settings.language; + language.selected = language.code === userData.settings.userLang; }); res.render('account/settings', userData);