From 7d90a94261c8c75c53ec8724c93e44bc94a884a5 Mon Sep 17 00:00:00 2001 From: Ben Lubar Date: Wed, 14 Sep 2016 20:57:51 -0500 Subject: [PATCH 01/43] Include page number in redirected topics --- src/controllers/topics.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/controllers/topics.js b/src/controllers/topics.js index 9d106a85f2..8e4dd1d518 100644 --- a/src/controllers/topics.js +++ b/src/controllers/topics.js @@ -58,6 +58,9 @@ topicsController.get = function(req, res, callback) { if (req.params.post_index){ url += '/'+req.params.post_index; } + if (currentPage > 1) { + url += '?page=' + currentPage; + } return helpers.redirect(res, url); } From 9c646ce39c86bf46791836bb56e5980b0b3c0f9a Mon Sep 17 00:00:00 2001 From: Anil Mandepudi Date: Mon, 26 Sep 2016 15:56:36 -0700 Subject: [PATCH 02/43] redirect to correct route on Chats.leave --- public/src/client/chats.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/src/client/chats.js b/public/src/client/chats.js index 2435042289..7f94eb1b66 100644 --- a/public/src/client/chats.js +++ b/public/src/client/chats.js @@ -290,7 +290,7 @@ define('forum/chats', [ return app.alertError(err.message); } if (parseInt(roomId, 10) === ajaxify.data.roomId) { - ajaxify.go('chats'); + ajaxify.go('user/' + ajaxify.data.userslug + '/chats'); } else { el.remove(); } From 2ef09de48d35bfc74c6e39e76ce8125b3cccf80b Mon Sep 17 00:00:00 2001 From: Anil Mandepudi Date: Mon, 26 Sep 2016 17:06:31 -0700 Subject: [PATCH 03/43] fix route on chat search --- public/src/client/chats/search.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/src/client/chats/search.js b/public/src/client/chats/search.js index 3645db282f..947959f7a4 100644 --- a/public/src/client/chats/search.js +++ b/public/src/client/chats/search.js @@ -75,7 +75,7 @@ define('forum/chats/search', ['components'], function(components) { return app.alertError(err.message); } if (roomId) { - ajaxify.go('chats/' + roomId); + Chats.switchChat(roomId); } else { app.newChat(userObj.uid); } @@ -84,4 +84,4 @@ define('forum/chats/search', ['components'], function(components) { } return search; -}); \ No newline at end of file +}); From 1eddf4c7207d1eb3e370cde51afe385d84b05d95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Tue, 27 Sep 2016 13:31:50 +0300 Subject: [PATCH 04/43] closes #5060 --- src/socket.io/admin/user.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/socket.io/admin/user.js b/src/socket.io/admin/user.js index 42dcd23266..5ebe40665b 100644 --- a/src/socket.io/admin/user.js +++ b/src/socket.io/admin/user.js @@ -1,7 +1,8 @@ "use strict"; - var async = require('async'); +var validator = require('validator'); + var db = require('../../database'); var groups = require('../../groups'); var user = require('../../user'); @@ -204,7 +205,7 @@ User.search = function(socket, data, callback) { userData.forEach(function(user, index) { if (user && userInfo[index]) { - user.email = userInfo[index].email || ''; + user.email = validator.escape(String(userInfo[index].email || '')); user.flags = userInfo[index].flags || 0; } }); From e2cbc8bc69c2e32841a0961de1107f79649974e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Tue, 27 Sep 2016 13:39:48 +0300 Subject: [PATCH 05/43] fix timeago on acp users --- public/src/admin/manage/users.js | 2 +- src/views/admin/manage/users.tpl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/public/src/admin/manage/users.js b/public/src/admin/manage/users.js index 45abb0e254..d41913ebc0 100644 --- a/public/src/admin/manage/users.js +++ b/public/src/admin/manage/users.js @@ -319,7 +319,7 @@ define('admin/manage/users', ['admin/modules/selectable', 'translator'], functio } templates.parse('admin/manage/users', 'users', data, function(html) { - $('#users-container').html(html); + $('#users-container').html(html).find('.timeago').timeago(); $('.fa-spinner').addClass('hidden'); diff --git a/src/views/admin/manage/users.tpl b/src/views/admin/manage/users.tpl index 2911403f6d..02ba3ad45c 100644 --- a/src/views/admin/manage/users.tpl +++ b/src/views/admin/manage/users.tpl @@ -79,7 +79,7 @@ {users.username} ({users.uid})
- {users.email} + {users.email}
joined
From ad2b44220d505779c39f012884652f4c7a693d9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Tue, 27 Sep 2016 14:23:48 +0300 Subject: [PATCH 06/43] escape event data --- src/events.js | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/events.js b/src/events.js index 9ef6a05385..7f0f3a7ec2 100644 --- a/src/events.js +++ b/src/events.js @@ -1,13 +1,13 @@ 'use strict'; -var async = require('async'), - - db = require('./database'), - batch = require('./batch'), - user = require('./user'), - utils = require('../public/src/utils'); - +var async = require('async'); +var validator = require('validator'); + +var db = require('./database'); +var batch = require('./batch'); +var user = require('./user'); +var utils = require('../public/src/utils'); (function(events) { events.log = function(data, callback) { @@ -54,6 +54,11 @@ var async = require('async'), }, function(eventsData, next) { eventsData.forEach(function(event) { + Object.keys(event).forEach(function(key) { + if (typeof event[key] === 'string') { + event[key] = validator.escape(String(event[key] || '')); + } + }); var e = utils.merge(event); e.eid = e.uid = e.type = e.ip = e.user = undefined; event.jsonString = JSON.stringify(e, null, 4); From a3e1c847b937bcc10e917e4d2bd185bfd53cd3d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Tue, 27 Sep 2016 14:24:14 +0300 Subject: [PATCH 07/43] fix wrong callback --- src/events.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/events.js b/src/events.js index 7f0f3a7ec2..9767f9093a 100644 --- a/src/events.js +++ b/src/events.js @@ -128,7 +128,7 @@ var utils = require('../public/src/utils'); callback = callback || function() {}; batch.processSortedSet('events:time', function(eids, next) { - events.deleteEvents(eids, callback); + events.deleteEvents(eids, next); }, {alwaysStartAt: 0}, callback); }; From 2f432d79948d04a89ac2aaefde4d5775a1cc9638 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Tue, 27 Sep 2016 14:36:33 +0300 Subject: [PATCH 08/43] up vanilla --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fb117469dd..0582f20cb4 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,7 @@ "nodebb-rewards-essentials": "0.0.9", "nodebb-theme-lavender": "3.0.14", "nodebb-theme-persona": "4.1.50", - "nodebb-theme-vanilla": "5.1.33", + "nodebb-theme-vanilla": "5.1.34", "nodebb-widget-essentials": "2.0.11", "nodemailer": "2.0.0", "nodemailer-sendmail-transport": "1.0.0", From 4938b006354b0decf6e93946114b1b0cf2fec024 Mon Sep 17 00:00:00 2001 From: Jorge Meireles Date: Tue, 27 Sep 2016 17:56:18 +0200 Subject: [PATCH 09/43] Fix language path (#5032) --- src/routes/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/index.js b/src/routes/index.js index 47fad11e6c..b4248120c9 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -142,7 +142,7 @@ module.exports = function(app, middleware, hotswapIds) { } app.use(middleware.privateUploads); - app.use('/language/:code', middleware.processLanguages); + app.use(relativePath + '/language/:code', middleware.processLanguages); app.use(relativePath, express.static(path.join(__dirname, '../../', 'public'), { maxAge: app.enabled('cache') ? 5184000000 : 0 })); From eb61c4e267a6f30c370faa0950ad0e9e0807a663 Mon Sep 17 00:00:00 2001 From: Anil Mandepudi Date: Tue, 27 Sep 2016 14:36:31 -0700 Subject: [PATCH 10/43] redirect main window to correct url on chat pop out --- public/src/client/chats.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/src/client/chats.js b/public/src/client/chats.js index 7f94eb1b66..754018d96b 100644 --- a/public/src/client/chats.js +++ b/public/src/client/chats.js @@ -62,7 +62,7 @@ define('forum/chats', [ var roomId = ajaxify.data.roomId; if (app.previousUrl && app.previousUrl.match(/chats/)) { - ajaxify.go('chats', function() { + ajaxify.go('user/' + ajaxify.data.userslug + '/chats', function() { app.openChat(roomId); }, true); } else { From 351504bd6c671d76a565737352c4916a6a6ce236 Mon Sep 17 00:00:00 2001 From: Anil Mandepudi Date: Tue, 27 Sep 2016 17:02:38 -0700 Subject: [PATCH 11/43] fix error on icon to picture change in profile --- public/src/client/account/edit.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/src/client/account/edit.js b/public/src/client/account/edit.js index 6cbea282d0..51632481cb 100644 --- a/public/src/client/account/edit.js +++ b/public/src/client/account/edit.js @@ -140,7 +140,7 @@ define('forum/account/edit', ['forum/account/header', 'uploader', 'translator', return app.alertError(err.message); } - updateHeader(type === 'default' ? '' : src); + updateHeader(type === 'default' ? '' : modal.find('.list-group-item.active img').attr('src')); ajaxify.refresh(); }); } From 0d09fcbee749b734c88739924f65715f40a5fe8a Mon Sep 17 00:00:00 2001 From: barisusakli Date: Wed, 28 Sep 2016 12:17:56 +0300 Subject: [PATCH 12/43] fix setAdd on redis for empty arrays --- src/database/redis/sets.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/database/redis/sets.js b/src/database/redis/sets.js index 9443ed928f..1eaab00cc5 100644 --- a/src/database/redis/sets.js +++ b/src/database/redis/sets.js @@ -5,6 +5,12 @@ module.exports = function(redisClient, module) { module.setAdd = function(key, value, callback) { callback = callback || function() {}; + if (!Array.isArray(value)) { + value = [value]; + } + if (!value.length) { + return callback(); + } redisClient.sadd(key, value, function(err, res) { callback(err); }); From d45fcb8fbef8665cbb933778b0911b72bfb34102 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Wed, 28 Sep 2016 10:50:07 -0400 Subject: [PATCH 13/43] up persona --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0582f20cb4..1ef4b640d2 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "nodebb-plugin-spam-be-gone": "0.4.10", "nodebb-rewards-essentials": "0.0.9", "nodebb-theme-lavender": "3.0.14", - "nodebb-theme-persona": "4.1.50", + "nodebb-theme-persona": "4.1.51", "nodebb-theme-vanilla": "5.1.34", "nodebb-widget-essentials": "2.0.11", "nodemailer": "2.0.0", From f9083dc3643b2b20b4f458ed2afdbe15b100e2f2 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Wed, 28 Sep 2016 18:22:22 +0300 Subject: [PATCH 14/43] up persona --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1ef4b640d2..80d8ba223d 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "nodebb-plugin-spam-be-gone": "0.4.10", "nodebb-rewards-essentials": "0.0.9", "nodebb-theme-lavender": "3.0.14", - "nodebb-theme-persona": "4.1.51", + "nodebb-theme-persona": "4.1.52", "nodebb-theme-vanilla": "5.1.34", "nodebb-widget-essentials": "2.0.11", "nodemailer": "2.0.0", From 5c70e503aa35d12b496f0ea2a50eb3e43e8f209f Mon Sep 17 00:00:00 2001 From: barisusakli Date: Wed, 28 Sep 2016 18:29:38 +0300 Subject: [PATCH 15/43] closes #5022 --- public/src/modules/chat.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/public/src/modules/chat.js b/public/src/modules/chat.js index 7b87b6e376..8f50ec82b0 100644 --- a/public/src/modules/chat.js +++ b/public/src/modules/chat.js @@ -26,8 +26,11 @@ define('chat', [ module.loadChatsDropdown(chatsListEl); }); - chatsListEl.on('click', '[data-roomid]', function() { - var roomId = this.getAttribute('data-roomid'); + chatsListEl.on('click', '[data-roomid]', function(ev) { + if ($(ev.target).parents('.user-link').length) { + return; + } + var roomId = $(this).attr('data-roomid'); if (!ajaxify.currentPage.match(/^chats\//)) { app.openChat(roomId); } else { @@ -339,7 +342,7 @@ define('chat', [ }); }; - module.disableMobileBehaviour = function(modalEl) { + module.disableMobileBehaviour = function() { app.toggleNavbar(true); }; @@ -347,7 +350,6 @@ define('chat', [ var totalHeight = modalEl.find('.modal-content').outerHeight() - modalEl.find('.modal-header').outerHeight(); var padding = parseInt(modalEl.find('.modal-body').css('padding-top'), 10) + parseInt(modalEl.find('.modal-body').css('padding-bottom'), 10); var contentMargin = parseInt(modalEl.find('.chat-content').css('margin-top'), 10) + parseInt(modalEl.find('.chat-content').css('margin-bottom'), 10); - var sinceHeight = modalEl.find('.since-bar').outerHeight(true); var inputGroupHeight = modalEl.find('.input-group').outerHeight(); return totalHeight - padding - contentMargin - inputGroupHeight; From c19ff46a77bb5c7f386619d481efc19ac115b26c Mon Sep 17 00:00:00 2001 From: barisusakli Date: Wed, 28 Sep 2016 18:31:56 +0300 Subject: [PATCH 16/43] update themes --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 80d8ba223d..d00fd4f004 100644 --- a/package.json +++ b/package.json @@ -61,8 +61,8 @@ "nodebb-plugin-spam-be-gone": "0.4.10", "nodebb-rewards-essentials": "0.0.9", "nodebb-theme-lavender": "3.0.14", - "nodebb-theme-persona": "4.1.52", - "nodebb-theme-vanilla": "5.1.34", + "nodebb-theme-persona": "4.1.53", + "nodebb-theme-vanilla": "5.1.35", "nodebb-widget-essentials": "2.0.11", "nodemailer": "2.0.0", "nodemailer-sendmail-transport": "1.0.0", From c8e5f52d9fa5cefd1cbe3613904ffa24b4aeb803 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Wed, 28 Sep 2016 19:03:32 +0300 Subject: [PATCH 17/43] fix chat route on mobile --- public/src/client/chats.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/public/src/client/chats.js b/public/src/client/chats.js index 754018d96b..aaa5c37b2e 100644 --- a/public/src/client/chats.js +++ b/public/src/client/chats.js @@ -298,7 +298,12 @@ define('forum/chats', [ }; Chats.switchChat = function(roomid) { - ajaxify.go('user/' + ajaxify.data.userslug + '/chats/' + roomid); + var env = utils.findBootstrapEnvironment(); + if (env === 'xs' || env === 'sm') { + app.openChat(roomid); + } else { + ajaxify.go('user/' + ajaxify.data.userslug + '/chats/' + roomid); + } }; Chats.loadChatSince = function(roomId, chatContentEl, since) { From 053906b76dc6e68bea82728ac7a451dd307d2e06 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Wed, 28 Sep 2016 19:59:36 +0300 Subject: [PATCH 18/43] revert chat fix --- public/src/client/chats.js | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/public/src/client/chats.js b/public/src/client/chats.js index aaa5c37b2e..754018d96b 100644 --- a/public/src/client/chats.js +++ b/public/src/client/chats.js @@ -298,12 +298,7 @@ define('forum/chats', [ }; Chats.switchChat = function(roomid) { - var env = utils.findBootstrapEnvironment(); - if (env === 'xs' || env === 'sm') { - app.openChat(roomid); - } else { - ajaxify.go('user/' + ajaxify.data.userslug + '/chats/' + roomid); - } + ajaxify.go('user/' + ajaxify.data.userslug + '/chats/' + roomid); }; Chats.loadChatSince = function(roomId, chatContentEl, since) { From 13a380cfba486958ab91c97cb1fb71b4a7c4d21f Mon Sep 17 00:00:00 2001 From: barisusakli Date: Wed, 28 Sep 2016 20:02:00 +0300 Subject: [PATCH 19/43] update persona --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d00fd4f004..e5b9112f4c 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "nodebb-plugin-spam-be-gone": "0.4.10", "nodebb-rewards-essentials": "0.0.9", "nodebb-theme-lavender": "3.0.14", - "nodebb-theme-persona": "4.1.53", + "nodebb-theme-persona": "4.1.54", "nodebb-theme-vanilla": "5.1.35", "nodebb-widget-essentials": "2.0.11", "nodemailer": "2.0.0", From 922f1587e7feac70eb6d5c0861ca421050855475 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Wed, 28 Sep 2016 20:06:16 +0300 Subject: [PATCH 20/43] closes #5067 --- public/language/en_GB/pages.json | 1 + src/controllers/index.js | 1 + 2 files changed, 2 insertions(+) diff --git a/public/language/en_GB/pages.json b/public/language/en_GB/pages.json index 52339d7830..c9b2014d79 100644 --- a/public/language/en_GB/pages.json +++ b/public/language/en_GB/pages.json @@ -20,6 +20,7 @@ "tags": "Tags", "tag": "Topics tagged under \"%1\"", "register": "Register an account", + "registration-complete": "Registration complete", "login": "Login to your account", "reset": "Reset your account password", "categories": "Categories", diff --git a/src/controllers/index.js b/src/controllers/index.js index 6142c48240..103dbf70f3 100644 --- a/src/controllers/index.js +++ b/src/controllers/index.js @@ -221,6 +221,7 @@ Controllers.registerInterstitial = function(req, res, next) { } res.render('registerComplete', { + title: '[[pages:registration-complete]]', errors: errors, sections: sections }); From 67f137149d06f6552ceac1a4a4408b73b13cdb60 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Wed, 28 Sep 2016 20:07:55 +0300 Subject: [PATCH 21/43] fix validator --- src/controllers/admin/flags.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controllers/admin/flags.js b/src/controllers/admin/flags.js index bed5c57767..b5edc7b5be 100644 --- a/src/controllers/admin/flags.js +++ b/src/controllers/admin/flags.js @@ -56,7 +56,7 @@ flagsController.get = function(req, res, next) { assignees: results.assignees, analytics: results.analytics, categories: results.categories, - byUsername: validator(String(byUsername)), + byUsername: validator.escape(String(byUsername)), sortByCount: sortBy === 'count', sortByTime: sortBy === 'time', pagination: pagination.create(page, pageCount, req.query), From 2931af18d403b6bc433e2ff7c96b97f8439dc20f Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Wed, 28 Sep 2016 15:46:10 -0400 Subject: [PATCH 22/43] define two client-side hooks for logout --- public/src/app.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/public/src/app.js b/public/src/app.js index b714a441cd..54e7c5fdb1 100644 --- a/public/src/app.js +++ b/public/src/app.js @@ -85,13 +85,19 @@ app.cacheBuster = null; }; app.logout = function() { + $(window).trigger('action:app.logout'); $.ajax(config.relative_path + '/logout', { type: 'POST', headers: { 'x-csrf-token': config.csrf_token }, success: function() { - window.location.href = config.relative_path + '/'; + var payload = { + next: config.relative_path + '/' + }; + + $(window).trigger('action:app.loggedOut', payload); + window.location.href = payload.next; } }); }; From be07772a913f166bc27db9065477b0ec8b150f2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Wed, 28 Sep 2016 23:19:01 +0300 Subject: [PATCH 23/43] check for e11000 --- src/database/mongo/sorted.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/database/mongo/sorted.js b/src/database/mongo/sorted.js index eb6505aa47..0b7ce568be 100644 --- a/src/database/mongo/sorted.js +++ b/src/database/mongo/sorted.js @@ -18,6 +18,9 @@ module.exports = function(db, module) { value = helpers.valueToString(value); db.collection('objects').update({_key: key, value: value}, {$set: {score: parseInt(score, 10)}}, {upsert:true, w: 1}, function(err) { + if (err && err.message.startsWith('E11000 duplicate key error')) { + return module.sortedSetAdd(key, score, value, callback); + } callback(err); }); }; From 37206a8b132332ca086e4c2510cd5aba7ecee233 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Wed, 28 Sep 2016 23:59:42 +0300 Subject: [PATCH 24/43] #5066 --- .travis.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 82838ced67..1a00ca309a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,12 +6,15 @@ before_install: - "sudo apt-get update" - "sudo apt-get install mongodb-org-server" - npm i --production - - node app --setup="{\"url\":\"http://127.0.0.1:4567/\",\"secret\":\"abcdef\",\"database\":\"mongo\",\"mongo:host\":\"127.0.0.1\",\"mongo:port\":27017,\"mongo:username\":\"\",\"mongo:password\":\"\",\"mongo:database\":0,\"redis:host\":\"127.0.0.1\",\"redis:port\":6379,\"redis:password\":\"\",\"redis:database\":0,\"admin:username\":\"admin\",\"admin:email\":\"test@example.org\",\"admin:password\":\"abcdef\",\"admin:password:confirm\":\"abcdef\"}" --ci="{\"host\":\"127.0.0.1\",\"port\":27017,\"database\":0}" + - sh -c "if [ '$DB' = 'mongodb' ]; then node app --setup="{\"url\":\"http://127.0.0.1:4567/\",\"secret\":\"abcdef\",\"database\":\"mongo\",\"mongo:host\":\"127.0.0.1\",\"mongo:port\":27017,\"mongo:username\":\"\",\"mongo:password\":\"\",\"mongo:database\":0,\"redis:host\":\"127.0.0.1\",\"redis:port\":6379,\"redis:password\":\"\",\"redis:database\":0,\"admin:username\":\"admin\",\"admin:email\":\"test@example.org\",\"admin:password\":\"abcdef\",\"admin:password:confirm\":\"abcdef\"}" --ci="{\"host\":\"127.0.0.1\",\"port\":27017,\"database\":0}" fi" + - sh -c "if [ '$DB' = 'redis' ]; then node app --setup="{\"url\":\"http://127.0.0.1:4567/\",\"secret\":\"abcdef\",\"database\":\"redis\",\"mongo:host\":\"127.0.0.1\",\"mongo:port\":27017,\"mongo:username\":\"\",\"mongo:password\":\"\",\"mongo:database\":0,\"redis:host\":\"127.0.0.1\",\"redis:port\":6379,\"redis:password\":\"\",\"redis:database\":0,\"admin:username\":\"admin\",\"admin:email\":\"test@example.org\",\"admin:password\":\"abcdef\",\"admin:password:confirm\":\"abcdef\"}" --ci="{\"host\":\"127.0.0.1\",\"port\":6379,\"database\":0}" fi" before_script: - "until nc -z localhost 27017; do echo Waiting for MongoDB; sleep 1; done" language: node_js env: - CXX=g++-4.8 + - DB=mongodb + - DB=redis addons: apt: sources: From 22625757608d3674174066ec48f7baa3c72712c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Thu, 29 Sep 2016 00:07:47 +0300 Subject: [PATCH 25/43] escape " --- .travis.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1a00ca309a..6e842d0a84 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,10 +5,10 @@ before_install: - "echo 'deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen' | sudo tee /etc/apt/sources.list.d/mongodb.list" - "sudo apt-get update" - "sudo apt-get install mongodb-org-server" - - npm i --production - - sh -c "if [ '$DB' = 'mongodb' ]; then node app --setup="{\"url\":\"http://127.0.0.1:4567/\",\"secret\":\"abcdef\",\"database\":\"mongo\",\"mongo:host\":\"127.0.0.1\",\"mongo:port\":27017,\"mongo:username\":\"\",\"mongo:password\":\"\",\"mongo:database\":0,\"redis:host\":\"127.0.0.1\",\"redis:port\":6379,\"redis:password\":\"\",\"redis:database\":0,\"admin:username\":\"admin\",\"admin:email\":\"test@example.org\",\"admin:password\":\"abcdef\",\"admin:password:confirm\":\"abcdef\"}" --ci="{\"host\":\"127.0.0.1\",\"port\":27017,\"database\":0}" fi" - - sh -c "if [ '$DB' = 'redis' ]; then node app --setup="{\"url\":\"http://127.0.0.1:4567/\",\"secret\":\"abcdef\",\"database\":\"redis\",\"mongo:host\":\"127.0.0.1\",\"mongo:port\":27017,\"mongo:username\":\"\",\"mongo:password\":\"\",\"mongo:database\":0,\"redis:host\":\"127.0.0.1\",\"redis:port\":6379,\"redis:password\":\"\",\"redis:database\":0,\"admin:username\":\"admin\",\"admin:email\":\"test@example.org\",\"admin:password\":\"abcdef\",\"admin:password:confirm\":\"abcdef\"}" --ci="{\"host\":\"127.0.0.1\",\"port\":6379,\"database\":0}" fi" -before_script: + - "npm i --production" + - "sh -c \"if [ '$DB' = 'mongodb' ]; then node app --setup=\"{\\\"url\\\":\\\"http://127.0.0.1:4567/\\\",\\\"secret\\\":\\\"abcdef\\\",\\\"database\\\":\\\"mongo\\\",\\\"mongo:host\\\":\\\"127.0.0.1\\\",\\\"mongo:port\\\":27017,\\\"mongo:username\\\":\\\"\\\",\\\"mongo:password\\\":\\\"\\\",\\\"mongo:database\\\":0,\\\"redis:host\\\":\\\"127.0.0.1\\\",\\\"redis:port\\\":6379,\\\"redis:password\\\":\\\"\\\",\\\"redis:database\\\":0,\\\"admin:username\\\":\\\"admin\\\",\\\"admin:email\\\":\\\"test@example.org\\\",\\\"admin:password\\\":\\\"abcdef\\\",\\\"admin:password:confirm\\\":\\\"abcdef\\\"}\" --ci=\"{\\\"host\\\":\\\"127.0.0.1\\\",\\\"port\\\":27017,\\\"database\\\":0}\" fi\"" + - "sh -c \"if [ '$DB' = 'redis' ]; then node app --setup=\"{\\\"url\\\":\\\"http://127.0.0.1:4567/\\\",\\\"secret\\\":\\\"abcdef\\\",\\\"database\\\":\\\"redis\\\",\\\"mongo:host\\\":\\\"127.0.0.1\\\",\\\"mongo:port\\\":27017,\\\"mongo:username\\\":\\\"\\\",\\\"mongo:password\\\":\\\"\\\",\\\"mongo:database\\\":0,\\\"redis:host\\\":\\\"127.0.0.1\\\",\\\"redis:port\\\":6379,\\\"redis:password\\\":\\\"\\\",\\\"redis:database\\\":0,\\\"admin:username\\\":\\\"admin\\\",\\\"admin:email\\\":\\\"test@example.org\\\",\\\"admin:password\\\":\\\"abcdef\\\",\\\"admin:password:confirm\\\":\\\"abcdef\\\"}\" --ci=\"{\\\"host\\\":\\\"127.0.0.1\\\",\\\"port\\\":6379,\\\"database\\\":0}\" fi\"" +before_script: - "until nc -z localhost 27017; do echo Waiting for MongoDB; sleep 1; done" language: node_js env: From c9edf1af423fdbddfbbdd957d51992139523602b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Thu, 29 Sep 2016 00:21:45 +0300 Subject: [PATCH 26/43] escape test --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6e842d0a84..b9a324c0ff 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,8 +6,8 @@ before_install: - "sudo apt-get update" - "sudo apt-get install mongodb-org-server" - "npm i --production" - - "sh -c \"if [ '$DB' = 'mongodb' ]; then node app --setup=\"{\\\"url\\\":\\\"http://127.0.0.1:4567/\\\",\\\"secret\\\":\\\"abcdef\\\",\\\"database\\\":\\\"mongo\\\",\\\"mongo:host\\\":\\\"127.0.0.1\\\",\\\"mongo:port\\\":27017,\\\"mongo:username\\\":\\\"\\\",\\\"mongo:password\\\":\\\"\\\",\\\"mongo:database\\\":0,\\\"redis:host\\\":\\\"127.0.0.1\\\",\\\"redis:port\\\":6379,\\\"redis:password\\\":\\\"\\\",\\\"redis:database\\\":0,\\\"admin:username\\\":\\\"admin\\\",\\\"admin:email\\\":\\\"test@example.org\\\",\\\"admin:password\\\":\\\"abcdef\\\",\\\"admin:password:confirm\\\":\\\"abcdef\\\"}\" --ci=\"{\\\"host\\\":\\\"127.0.0.1\\\",\\\"port\\\":27017,\\\"database\\\":0}\" fi\"" - - "sh -c \"if [ '$DB' = 'redis' ]; then node app --setup=\"{\\\"url\\\":\\\"http://127.0.0.1:4567/\\\",\\\"secret\\\":\\\"abcdef\\\",\\\"database\\\":\\\"redis\\\",\\\"mongo:host\\\":\\\"127.0.0.1\\\",\\\"mongo:port\\\":27017,\\\"mongo:username\\\":\\\"\\\",\\\"mongo:password\\\":\\\"\\\",\\\"mongo:database\\\":0,\\\"redis:host\\\":\\\"127.0.0.1\\\",\\\"redis:port\\\":6379,\\\"redis:password\\\":\\\"\\\",\\\"redis:database\\\":0,\\\"admin:username\\\":\\\"admin\\\",\\\"admin:email\\\":\\\"test@example.org\\\",\\\"admin:password\\\":\\\"abcdef\\\",\\\"admin:password:confirm\\\":\\\"abcdef\\\"}\" --ci=\"{\\\"host\\\":\\\"127.0.0.1\\\",\\\"port\\\":6379,\\\"database\\\":0}\" fi\"" + - sh -c "if [ '$DB' = 'mongodb' ]; then node app --setup=\"{\\\"url\\\":\\\"http://127.0.0.1:4567/\\\",\\\"secret\\\":\\\"abcdef\\\",\\\"database\\\":\\\"mongo\\\",\\\"mongo:host\\\":\\\"127.0.0.1\\\",\\\"mongo:port\\\":27017,\\\"mongo:username\\\":\\\"\\\",\\\"mongo:password\\\":\\\"\\\",\\\"mongo:database\\\":0,\\\"redis:host\\\":\\\"127.0.0.1\\\",\\\"redis:port\\\":6379,\\\"redis:password\\\":\\\"\\\",\\\"redis:database\\\":0,\\\"admin:username\\\":\\\"admin\\\",\\\"admin:email\\\":\\\"test@example.org\\\",\\\"admin:password\\\":\\\"abcdef\\\",\\\"admin:password:confirm\\\":\\\"abcdef\\\"}\" --ci=\"{\\\"host\\\":\\\"127.0.0.1\\\",\\\"port\\\":27017,\\\"database\\\":0}\" fi" + - sh -c "if [ '$DB' = 'redis' ]; then node app --setup=\"{\\\"url\\\":\\\"http://127.0.0.1:4567/\\\",\\\"secret\\\":\\\"abcdef\\\",\\\"database\\\":\\\"redis\\\",\\\"mongo:host\\\":\\\"127.0.0.1\\\",\\\"mongo:port\\\":27017,\\\"mongo:username\\\":\\\"\\\",\\\"mongo:password\\\":\\\"\\\",\\\"mongo:database\\\":0,\\\"redis:host\\\":\\\"127.0.0.1\\\",\\\"redis:port\\\":6379,\\\"redis:password\\\":\\\"\\\",\\\"redis:database\\\":0,\\\"admin:username\\\":\\\"admin\\\",\\\"admin:email\\\":\\\"test@example.org\\\",\\\"admin:password\\\":\\\"abcdef\\\",\\\"admin:password:confirm\\\":\\\"abcdef\\\"}\" --ci=\"{\\\"host\\\":\\\"127.0.0.1\\\",\\\"port\\\":6379,\\\"database\\\":0}\" fi" before_script: - "until nc -z localhost 27017; do echo Waiting for MongoDB; sleep 1; done" language: node_js From ae8a75a09644f2c4d78303e0a3ba5c732e3909b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Thu, 29 Sep 2016 00:36:41 +0300 Subject: [PATCH 27/43] add semicolon --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index b9a324c0ff..50badc2115 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,8 +6,8 @@ before_install: - "sudo apt-get update" - "sudo apt-get install mongodb-org-server" - "npm i --production" - - sh -c "if [ '$DB' = 'mongodb' ]; then node app --setup=\"{\\\"url\\\":\\\"http://127.0.0.1:4567/\\\",\\\"secret\\\":\\\"abcdef\\\",\\\"database\\\":\\\"mongo\\\",\\\"mongo:host\\\":\\\"127.0.0.1\\\",\\\"mongo:port\\\":27017,\\\"mongo:username\\\":\\\"\\\",\\\"mongo:password\\\":\\\"\\\",\\\"mongo:database\\\":0,\\\"redis:host\\\":\\\"127.0.0.1\\\",\\\"redis:port\\\":6379,\\\"redis:password\\\":\\\"\\\",\\\"redis:database\\\":0,\\\"admin:username\\\":\\\"admin\\\",\\\"admin:email\\\":\\\"test@example.org\\\",\\\"admin:password\\\":\\\"abcdef\\\",\\\"admin:password:confirm\\\":\\\"abcdef\\\"}\" --ci=\"{\\\"host\\\":\\\"127.0.0.1\\\",\\\"port\\\":27017,\\\"database\\\":0}\" fi" - - sh -c "if [ '$DB' = 'redis' ]; then node app --setup=\"{\\\"url\\\":\\\"http://127.0.0.1:4567/\\\",\\\"secret\\\":\\\"abcdef\\\",\\\"database\\\":\\\"redis\\\",\\\"mongo:host\\\":\\\"127.0.0.1\\\",\\\"mongo:port\\\":27017,\\\"mongo:username\\\":\\\"\\\",\\\"mongo:password\\\":\\\"\\\",\\\"mongo:database\\\":0,\\\"redis:host\\\":\\\"127.0.0.1\\\",\\\"redis:port\\\":6379,\\\"redis:password\\\":\\\"\\\",\\\"redis:database\\\":0,\\\"admin:username\\\":\\\"admin\\\",\\\"admin:email\\\":\\\"test@example.org\\\",\\\"admin:password\\\":\\\"abcdef\\\",\\\"admin:password:confirm\\\":\\\"abcdef\\\"}\" --ci=\"{\\\"host\\\":\\\"127.0.0.1\\\",\\\"port\\\":6379,\\\"database\\\":0}\" fi" + - sh -c "if [ '$DB' = 'mongodb' ]; then node app --setup=\"{\\\"url\\\":\\\"http://127.0.0.1:4567/\\\",\\\"secret\\\":\\\"abcdef\\\",\\\"database\\\":\\\"mongo\\\",\\\"mongo:host\\\":\\\"127.0.0.1\\\",\\\"mongo:port\\\":27017,\\\"mongo:username\\\":\\\"\\\",\\\"mongo:password\\\":\\\"\\\",\\\"mongo:database\\\":0,\\\"redis:host\\\":\\\"127.0.0.1\\\",\\\"redis:port\\\":6379,\\\"redis:password\\\":\\\"\\\",\\\"redis:database\\\":0,\\\"admin:username\\\":\\\"admin\\\",\\\"admin:email\\\":\\\"test@example.org\\\",\\\"admin:password\\\":\\\"abcdef\\\",\\\"admin:password:confirm\\\":\\\"abcdef\\\"}\" --ci=\"{\\\"host\\\":\\\"127.0.0.1\\\",\\\"port\\\":27017,\\\"database\\\":0}\"; fi" + - sh -c "if [ '$DB' = 'redis' ]; then node app --setup=\"{\\\"url\\\":\\\"http://127.0.0.1:4567/\\\",\\\"secret\\\":\\\"abcdef\\\",\\\"database\\\":\\\"redis\\\",\\\"mongo:host\\\":\\\"127.0.0.1\\\",\\\"mongo:port\\\":27017,\\\"mongo:username\\\":\\\"\\\",\\\"mongo:password\\\":\\\"\\\",\\\"mongo:database\\\":0,\\\"redis:host\\\":\\\"127.0.0.1\\\",\\\"redis:port\\\":6379,\\\"redis:password\\\":\\\"\\\",\\\"redis:database\\\":0,\\\"admin:username\\\":\\\"admin\\\",\\\"admin:email\\\":\\\"test@example.org\\\",\\\"admin:password\\\":\\\"abcdef\\\",\\\"admin:password:confirm\\\":\\\"abcdef\\\"}\" --ci=\"{\\\"host\\\":\\\"127.0.0.1\\\",\\\"port\\\":6379,\\\"database\\\":0}\"; fi" before_script: - "until nc -z localhost 27017; do echo Waiting for MongoDB; sleep 1; done" language: node_js From d859163dea125588216ebbaf699f449dc689c025 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Thu, 29 Sep 2016 00:44:48 +0300 Subject: [PATCH 28/43] configure env matrix --- .travis.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 50badc2115..e89064595e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,9 +12,8 @@ before_script: - "until nc -z localhost 27017; do echo Waiting for MongoDB; sleep 1; done" language: node_js env: - - CXX=g++-4.8 - - DB=mongodb - - DB=redis + - CXX=g++-4.8 DB=mongodb + - CXX=g++-4.8 DB=redis addons: apt: sources: From 4eb8015017e49561e390381f580a10baaab87287 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Thu, 29 Sep 2016 14:31:24 +0300 Subject: [PATCH 29/43] closes #5069 --- package.json | 2 +- src/database/redis.js | 13 ++++++++----- src/socket.io/index.js | 3 +-- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index e5b9112f4c..fb8b6be978 100644 --- a/package.json +++ b/package.json @@ -81,7 +81,7 @@ "sitemap": "^1.4.0", "socket.io": "^1.4.8", "socket.io-client": "^1.4.0", - "socket.io-redis": "^1.0.0", + "socket.io-redis": "1.1.1", "socketio-wildcard": "~0.3.0", "string": "^3.0.0", "templates.js": "0.3.4", diff --git a/src/database/redis.js b/src/database/redis.js index 8af568b5d9..214c9ef4a1 100644 --- a/src/database/redis.js +++ b/src/database/redis.js @@ -65,15 +65,18 @@ }; module.connect = function(options) { - var redis_socket_or_host = nconf.get('redis:host'), - cxn, dbIdx; - - options = options || {}; + var redis_socket_or_host = nconf.get('redis:host'); + var cxn; if (!redis) { redis = require('redis'); } + options = options || {}; + if (nconf.get('redis:password')) { + options.auth_pass = nconf.get('redis:password'); + } + if (redis_socket_or_host && redis_socket_or_host.indexOf('/') >= 0) { /* If redis.host contains a path name character, use the unix dom sock connection. ie, /tmp/redis.sock */ cxn = redis.createClient(nconf.get('redis:host'), options); @@ -91,7 +94,7 @@ cxn.auth(nconf.get('redis:password')); } - dbIdx = parseInt(nconf.get('redis:database'), 10); + var dbIdx = parseInt(nconf.get('redis:database'), 10); if (dbIdx) { cxn.select(dbIdx, function(error) { if(error) { diff --git a/src/socket.io/index.js b/src/socket.io/index.js index 5ee6050571..d3393ea2d2 100644 --- a/src/socket.io/index.js +++ b/src/socket.io/index.js @@ -177,9 +177,8 @@ var ratelimit = require('../middleware/ratelimit'); if (nconf.get('redis')) { var redisAdapter = require('socket.io-redis'); var redis = require('../database/redis'); - var pub = redis.connect({return_buffers: true}); + var pub = redis.connect(); var sub = redis.connect({return_buffers: true}); - io.adapter(redisAdapter({pubClient: pub, subClient: sub})); } else if (nconf.get('isCluster') === 'true') { winston.warn('[socket.io] Clustering detected, you are advised to configure Redis as a websocket store.'); From a325a85a840878bffa6220455c86467ff81652bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Thu, 29 Sep 2016 21:58:18 +0300 Subject: [PATCH 30/43] fix mass group invite --- src/socket.io/groups.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/socket.io/groups.js b/src/socket.io/groups.js index 41de928b51..a8eb6b7ae9 100644 --- a/src/socket.io/groups.js +++ b/src/socket.io/groups.js @@ -152,7 +152,7 @@ SocketGroups.issueMassInvite = isOwner(function(socket, data, callback) { }); async.eachSeries(uids, function(uid, next) { - groups.invite(data.groupName, uid, callback); + groups.invite(data.groupName, uid, next); }, callback); }); }); From abd99760e56044cb4cb6d629465bbee5c86efe17 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Fri, 30 Sep 2016 13:18:29 +0300 Subject: [PATCH 31/43] closes #5070 --- src/controllers/accounts/chats.js | 1 + src/messaging.js | 2 +- src/messaging/rooms.js | 36 ++++++++++++++++++++++--------- src/socket.io/modules.js | 1 + 4 files changed, 29 insertions(+), 11 deletions(-) diff --git a/src/controllers/accounts/chats.js b/src/controllers/accounts/chats.js index 7ff867134c..b1d23ebeb3 100644 --- a/src/controllers/accounts/chats.js +++ b/src/controllers/accounts/chats.js @@ -74,6 +74,7 @@ chatsController.get = function(req, res, callback) { return user && parseInt(user.uid, 10) && parseInt(user.uid, 10) !== req.uid; }); + room.groupChat = room.hasOwnProperty('groupChat') ? room.groupChat : room.users.length > 2; room.rooms = recentChats.rooms; room.uid = uid; room.userslug = req.params.userslug; diff --git a/src/messaging.js b/src/messaging.js index 2fe69e50fe..e2be899b46 100644 --- a/src/messaging.js +++ b/src/messaging.js @@ -265,7 +265,7 @@ var async = require('async'), }, users: function(next) { async.map(roomIds, function(roomId, next) { - db.getSortedSetRevRange('chat:room:' + roomId + ':uids', 0, 3, function(err, uids) { + db.getSortedSetRevRange('chat:room:' + roomId + ':uids', 0, 9, function(err, uids) { if (err) { return next(err); } diff --git a/src/messaging/rooms.js b/src/messaging/rooms.js index 54423a2673..7433da44c6 100644 --- a/src/messaging/rooms.js +++ b/src/messaging/rooms.js @@ -13,10 +13,7 @@ module.exports = function(Messaging) { if (err || !data) { return callback(err || new Error('[[error:no-chat-room]]')); } - data.roomName = data.roomName || '[[modules:chat.roomname, ' + roomId + ']]'; - if (data.roomName) { - data.roomName = validator.escape(String(data.roomName)); - } + modifyRoomData([data]); callback(null, data); }); }; @@ -29,16 +26,23 @@ module.exports = function(Messaging) { if (err) { return callback(err); } - roomData.forEach(function(data) { - if (data) { - data.roomName = data.roomName || '[[modules:chat.roomname, ' + data.roomId + ']]'; - data.roomName = validator.escape(String(data.roomName)); - } - }); + modifyRoomData(roomData); callback(null, roomData); }); }; + function modifyRoomData(rooms) { + rooms.forEach(function(data) { + if (data) { + data.roomName = data.roomName || '[[modules:chat.roomname, ' + data.roomId + ']]'; + data.roomName = validator.escape(String(data.roomName)); + if (data.hasOwnProperty('groupChat')) { + data.groupChat = parseInt(data.groupChat, 10) === 1; + } + } + }); + } + Messaging.newRoom = function(uid, toUids, callback) { var roomId; var now = Date.now(); @@ -105,6 +109,18 @@ module.exports = function(Messaging) { return now; }); db.sortedSetAdd('chat:room:' + roomId + ':uids', timestamps, uids, next); + }, + function(next) { + async.parallel({ + userCount: async.apply(db.sortedSetCard, 'chat:room:' + roomId + ':uids'), + roomData: async.apply(db.getObject, 'chat:room:' + roomId) + }, next); + }, + function(results, next) { + if (!results.roomData.hasOwnProperty('groupChat') && results.userCount > 2) { + return db.setObjectField('chat:room:' + roomId, 'groupChat', 1, next); + } + next(); } ], callback); }; diff --git a/src/socket.io/modules.js b/src/socket.io/modules.js index 3a1e711b45..8825ee4bcb 100644 --- a/src/socket.io/modules.js +++ b/src/socket.io/modules.js @@ -133,6 +133,7 @@ SocketModules.chats.loadRoom = function(socket, data, callback) { }, function (results, next) { results.roomData.users = results.users; + results.roomData.groupChat = results.roomData.hasOwnProperty('groupChat') ? results.roomData.groupChat : results.users.length > 2; results.roomData.isOwner = parseInt(results.roomData.owner, 10) === socket.uid; results.roomData.maximumUsersInChatRoom = parseInt(meta.config.maximumUsersInChatRoom, 10) || 0; results.roomData.showUserInput = !results.roomData.maximumUsersInChatRoom || results.roomData.maximumUsersInChatRoom > 2; From 1b5287803c972863e3c59be47e399a4ec07bc787 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Fri, 30 Sep 2016 14:00:49 +0300 Subject: [PATCH 32/43] closes #5071 --- src/messaging.js | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/messaging.js b/src/messaging.js index e2be899b46..2bad43ce79 100644 --- a/src/messaging.js +++ b/src/messaging.js @@ -312,6 +312,7 @@ var async = require('async'), }; Messaging.getTeaser = function (uid, roomId, callback) { + var teaser; async.waterfall([ function (next) { db.getSortedSetRevRange('uid:' + uid + ':chat:room:' + roomId + ':mids', 0, 0, next); @@ -320,14 +321,22 @@ var async = require('async'), if (!mids || !mids.length) { return next(null, null); } - Messaging.getMessageFields(mids[0], ['content', 'timestamp'], next); + Messaging.getMessageFields(mids[0], ['fromuid', 'content', 'timestamp'], next); }, - function (teaser, next) { - if (teaser && teaser.content) { - teaser.content = S(teaser.content).stripTags().decodeHTMLEntities().s; - teaser.timestampISO = utils.toISOString(teaser.timestamp); - } - + function (_teaser, next) { + teaser = _teaser; + if (!teaser) { + return callback(); + } + if (teaser.content) { + teaser.content = S(teaser.content).stripTags().decodeHTMLEntities().s; + } + + teaser.timestampISO = utils.toISOString(teaser.timestamp); + user.getUserFields(teaser.fromuid, ['uid', 'username', 'userslug', 'picture', 'status', 'lastonline'] , next); + }, + function(user, next) { + teaser.user = user; next(null, teaser); } ], callback); From ce0fd957413eb515b7120a0adf989f45b438bb55 Mon Sep 17 00:00:00 2001 From: NodeBB Misty Date: Fri, 30 Sep 2016 09:02:20 -0400 Subject: [PATCH 33/43] Latest translations and fallbacks --- public/language/ko/category.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/language/ko/category.json b/public/language/ko/category.json index 5fe7e96cde..0c5f877d53 100644 --- a/public/language/ko/category.json +++ b/public/language/ko/category.json @@ -12,8 +12,8 @@ "ignore": "관심 해제", "watching": "Watching", "ignoring": "Ignoring", - "watching.description": "Show topics in unread", - "ignoring.description": "Do not show topics in unread", + "watching.description": "읽지 않은 주제를 표시합니다", + "ignoring.description": "읽지 않은 주제를 표시하지 않습니다", "watch.message": "이 카테고리에 올라오는 글을 주시하고 있습니다.", "ignore.message": "이 카테고리에 올라오는 글을 무시합니다.", "watched-categories": "관심 카테고리" From 15409f92cd13a7668eac1dc1731401b474f45158 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Fri, 30 Sep 2016 18:42:19 +0300 Subject: [PATCH 34/43] escape history data, hide moderation note in api --- src/controllers/accounts/helpers.js | 5 +++++ src/controllers/accounts/info.js | 4 ++-- src/middleware/header.js | 2 +- src/user/info.js | 23 +++++++---------------- 4 files changed, 15 insertions(+), 19 deletions(-) diff --git a/src/controllers/accounts/helpers.js b/src/controllers/accounts/helpers.js index 3d9b2a9a1e..7af9cfa3e4 100644 --- a/src/controllers/accounts/helpers.js +++ b/src/controllers/accounts/helpers.js @@ -87,6 +87,10 @@ helpers.getUserDataByUserSlug = function(userslug, callerUID, callback) { userData.ips = results.ips; } + if (!isAdmin && !isGlobalModerator) { + userData.moderationNote = undefined; + } + userData.uid = userData.uid; userData.yourid = callerUID; userData.theirid = userData.uid; @@ -120,6 +124,7 @@ helpers.getUserDataByUserSlug = function(userslug, callerUID, callback) { userData.signature = validator.escape(String(userData.signature || '')); userData.aboutme = validator.escape(String(userData.aboutme || '')); userData.birthday = validator.escape(String(userData.birthday || '')); + userData.moderationNote = validator.escape(String(userData.moderationNote || '')); userData['cover:url'] = userData['cover:url'] || require('../../coverPhoto').getDefaultProfileCover(userData.uid); userData['cover:position'] = userData['cover:position'] || '50% 50%'; diff --git a/src/controllers/accounts/info.js b/src/controllers/accounts/info.js index fad9cd4c24..63dea030ec 100644 --- a/src/controllers/accounts/info.js +++ b/src/controllers/accounts/info.js @@ -22,8 +22,8 @@ infoController.get = function(req, res, callback) { async.parallel({ history: async.apply(user.getModerationHistory, userData.uid), sessions: async.apply(user.auth.getSessions, userData.uid, req.sessionID), - usernames: async.apply(user.getUsernameHistory, userData.uid), - emails: async.apply(user.getEmailHistory, userData.uid) + usernames: async.apply(user.getHistory, 'user:' + userData.uid + ':usernames'), + emails: async.apply(user.getHistory, 'user:' + userData.uid + ':emails') }, next); } ], function(err, data) { diff --git a/src/middleware/header.js b/src/middleware/header.js index 26e9795019..57c532f83e 100644 --- a/src/middleware/header.js +++ b/src/middleware/header.js @@ -120,7 +120,7 @@ module.exports = function(middleware) { results.user.isAdmin = results.isAdmin; results.user.isGlobalMod = results.isGlobalMod; results.user.uid = parseInt(results.user.uid, 10); - results.user.email = String(results.user.email).replace(/\\/g, '\\\\'); + results.user.email = String(results.user.email).replace(/\\/g, '\\\\').replace(/"/g, '\\"'); results.user['email:confirmed'] = parseInt(results.user['email:confirmed'], 10) === 1; results.user.isEmailConfirmSent = !!results.isEmailConfirmSent; diff --git a/src/user/info.js b/src/user/info.js index 49d03ed90c..8f2e4d3a83 100644 --- a/src/user/info.js +++ b/src/user/info.js @@ -61,24 +61,15 @@ module.exports = function(User) { }); }; - User.getEmailHistory = function(uid, callback) { - db.getSortedSetRevRangeWithScores('user:' + uid + ':emails', 0, -1, function(err, data) { - callback(err, data.map(function(set) { + User.getHistory = function(set, callback) { + db.getSortedSetRevRangeWithScores(set, 0, -1, function(err, data) { + if (err) { + return callback(err); + } + callback(null, data.map(function(set) { set.timestamp = set.score; set.timestampISO = new Date(set.score).toISOString(); - set.value = set.value.split(':')[0]; - delete set.score; - return set; - })); - }); - }; - - User.getUsernameHistory = function(uid, callback) { - db.getSortedSetRevRangeWithScores('user:' + uid + ':usernames', 0, -1, function(err, data) { - callback(err, data.map(function(set) { - set.timestamp = set.score; - set.timestampISO = new Date(set.score).toISOString(); - set.value = set.value.split(':')[0]; + set.value = validator.escape(String(set.value.split(':')[0])); delete set.score; return set; })); From 6aec61d7227b73b49f30ea912dcab5f299f240f9 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Fri, 30 Sep 2016 19:39:08 +0300 Subject: [PATCH 35/43] groupChat on recentChats --- src/messaging.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/messaging.js b/src/messaging.js index 2bad43ce79..d3809c9676 100644 --- a/src/messaging.js +++ b/src/messaging.js @@ -288,6 +288,7 @@ var async = require('async'), results.roomData.forEach(function(room, index) { room.users = results.users[index]; + room.groupChat = room.hasOwnProperty('groupChat') ? room.groupChat : room.users.length > 2; room.unread = results.unread[index]; room.teaser = results.teasers[index]; @@ -329,9 +330,9 @@ var async = require('async'), return callback(); } if (teaser.content) { - teaser.content = S(teaser.content).stripTags().decodeHTMLEntities().s; + teaser.content = S(teaser.content).stripTags().decodeHTMLEntities().s; } - + teaser.timestampISO = utils.toISOString(teaser.timestamp); user.getUserFields(teaser.fromuid, ['uid', 'username', 'userslug', 'picture', 'status', 'lastonline'] , next); }, From 4875a13421fe43b8ff5dffccceb29315342f207b Mon Sep 17 00:00:00 2001 From: NodeBB Misty Date: Fri, 30 Sep 2016 14:18:18 -0400 Subject: [PATCH 36/43] Incremented version number --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index fb8b6be978..84128c76f8 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "nodebb", "license": "GPL-3.0", "description": "NodeBB Forum", - "version": "1.1.2", + "version": "1.2.0", "homepage": "http://www.nodebb.org", "repository": { "type": "git", @@ -123,4 +123,4 @@ "url": "https://github.com/barisusakli" } ] -} +} \ No newline at end of file From a93ee979267285182a2352e4a6b58345a52a277d Mon Sep 17 00:00:00 2001 From: barisusakli Date: Sun, 2 Oct 2016 15:17:22 +0300 Subject: [PATCH 37/43] closes #5073 --- public/src/app.js | 3 ++- public/src/client/chats.js | 18 ++++++++-------- public/src/modules/chat.js | 7 ++++--- src/messaging.js | 2 +- src/socket.io/modules.js | 42 +++++++++++++++++++------------------- 5 files changed, 37 insertions(+), 35 deletions(-) diff --git a/public/src/app.js b/public/src/app.js index 54e7c5fdb1..7fd5bba563 100644 --- a/public/src/app.js +++ b/public/src/app.js @@ -266,7 +266,7 @@ app.cacheBuster = null; } }; - app.openChat = function (roomId) { + app.openChat = function (roomId, uid) { if (!app.user.uid) { return app.alertError('[[error:not-logged-in]]'); } @@ -288,6 +288,7 @@ app.cacheBuster = null; roomData.users = roomData.users.filter(function(user) { return user && parseInt(user.uid, 10) !== parseInt(app.user.uid, 10); }); + roomData.uid = uid || app.user.uid; chat.createModal(roomData, loadAndCenter); }); } diff --git a/public/src/client/chats.js b/public/src/client/chats.js index 754018d96b..b7ef28bc32 100644 --- a/public/src/client/chats.js +++ b/public/src/client/chats.js @@ -63,11 +63,11 @@ define('forum/chats', [ if (app.previousUrl && app.previousUrl.match(/chats/)) { ajaxify.go('user/' + ajaxify.data.userslug + '/chats', function() { - app.openChat(roomId); + app.openChat(roomId, ajaxify.data.uid); }, true); } else { window.history.go(-1); - app.openChat(roomId); + app.openChat(roomId, ajaxify.data.uid); } $(window).one('action:chat.loaded', function() { @@ -79,7 +79,7 @@ define('forum/chats', [ recentChats.init(); - Chats.addSinceHandler(ajaxify.data.roomId, $('.expanded-chat .chat-content'), $('.expanded-chat [data-since]')); + Chats.addSinceHandler(ajaxify.data.roomId, ajaxify.data.uid, $('.expanded-chat .chat-content'), $('.expanded-chat [data-since]')); Chats.addRenameHandler(ajaxify.data.roomId, $('[component="chat/room/name"]')); Chats.addScrollHandler(ajaxify.data.roomId, ajaxify.data.uid, $('.chat-content')); }; @@ -96,8 +96,8 @@ define('forum/chats', [ return; } loading = true; - - socket.emit('modules.chats.getMessages', {roomId: roomId, uid: uid, start: $('.chat-content').children('[data-index]').first().attr('data-index')}, function(err, data) { + var start = parseInt($('.chat-content').children('[data-index]').first().attr('data-index'), 10) + 1; + socket.emit('modules.chats.getMessages', {roomId: roomId, uid: uid, start: start}, function(err, data) { if (err) { return app.alertError(err.message); } @@ -156,12 +156,12 @@ define('forum/chats', [ }); }; - Chats.addSinceHandler = function(roomId, chatContentEl, sinceEl) { + Chats.addSinceHandler = function(roomId, uid, chatContentEl, sinceEl) { sinceEl.on('click', function() { var since = $(this).attr('data-since'); sinceEl.removeClass('selected'); $(this).addClass('selected'); - Chats.loadChatSince(roomId, chatContentEl, since); + Chats.loadChatSince(roomId, uid, chatContentEl, since); return false; }); }; @@ -301,11 +301,11 @@ define('forum/chats', [ ajaxify.go('user/' + ajaxify.data.userslug + '/chats/' + roomid); }; - Chats.loadChatSince = function(roomId, chatContentEl, since) { + Chats.loadChatSince = function(roomId, uid, chatContentEl, since) { if (!roomId) { return; } - socket.emit('modules.chats.get', {roomId: roomId, since: since}, function(err, messageData) { + socket.emit('modules.chats.getMessages', {roomId: roomId, uid: uid, since: since, markRead: true}, function(err, messageData) { if (err) { return app.alertError(err.message); } diff --git a/public/src/modules/chat.js b/public/src/modules/chat.js index 8f50ec82b0..e3e2bf0a0e 100644 --- a/public/src/modules/chat.js +++ b/public/src/modules/chat.js @@ -83,6 +83,7 @@ define('chat', [ return user && parseInt(user.uid, 10) !== parseInt(app.user.uid, 10); }); roomData.silent = true; + roomData.uid = app.user.uid; module.createModal(roomData, function(modal) { module.toggleNew(modal.attr('UUID'), !isSelf, true); if (!isSelf) { @@ -254,7 +255,7 @@ define('chat', [ messagesEl.css('height', module.calculateChatListHeight(chatModal)); }); - Chats.addSinceHandler(chatModal.attr('roomId'), chatModal.find('.chat-content'), chatModal.find('[data-since]')); + Chats.addSinceHandler(chatModal.attr('roomId'), data.uid, chatModal.find('.chat-content'), chatModal.find('[data-since]')); Chats.addRenameHandler(chatModal.attr('roomId'), chatModal.find('[component="chat/room/name"]')); Chats.addSendHandlers(chatModal.attr('roomId'), chatModal.find('#chat-message-input'), chatModal.find('#chat-message-send-btn')); @@ -262,9 +263,9 @@ define('chat', [ Chats.createTagsInput(chatModal.find('.users-tag-input'), data); Chats.createAutoComplete(chatModal.find('[component="chat/input"]')); - Chats.loadChatSince(chatModal.attr('roomId'), chatModal.find('.chat-content'), 'recent'); + Chats.loadChatSince(chatModal.attr('roomId'), data.uid, chatModal.find('.chat-content'), 'recent'); - Chats.addScrollHandler(chatModal.attr('roomId'), app.user.uid, chatModal.find('.chat-content')); + Chats.addScrollHandler(chatModal.attr('roomId'), data.uid, chatModal.find('.chat-content')); checkStatus(chatModal); diff --git a/src/messaging.js b/src/messaging.js index d3809c9676..b185e43964 100644 --- a/src/messaging.js +++ b/src/messaging.js @@ -52,7 +52,7 @@ var async = require('async'), var uid = params.uid; var roomId = params.roomId; var since = params.since; - var isNew = params.isNew; + var isNew = params.isNew || false; var start = params.hasOwnProperty('start') ? params.start : 0; var count = params.count || 250; var markRead = params.markRead || true; diff --git a/src/socket.io/modules.js b/src/socket.io/modules.js index 8825ee4bcb..ee60c76a9b 100644 --- a/src/socket.io/modules.js +++ b/src/socket.io/modules.js @@ -12,26 +12,13 @@ var server = require('./'); var user = require('../user'); var SocketModules = { - chats: {}, - sounds: {}, - settings: {} - }; + chats: {}, + sounds: {}, + settings: {} +}; /* Chat */ -SocketModules.chats.get = function(socket, data, callback) { - if(!data || !data.roomId) { - return callback(new Error('[[error:invalid-data]]')); - } - - Messaging.getMessages({ - uid: socket.uid, - roomId: data.roomId, - since: data.since, - isNew: false - }, callback); -}; - SocketModules.chats.getRaw = function(socket, data, callback) { if (!data || !data.hasOwnProperty('mid')) { return callback(new Error('[[error:invalid-data]]')); @@ -119,10 +106,13 @@ SocketModules.chats.loadRoom = function(socket, data, callback) { async.waterfall([ function (next) { - Messaging.isUserInRoom(socket.uid, data.roomId, next); + async.parallel({ + inRoom: async.apply(Messaging.isUserInRoom, socket.uid, data.roomId), + isAdminOrGlobalMod: async.apply(user.isAdminOrGlobalMod, socket.uid) + }, next); }, - function (inRoom, next) { - if (!inRoom) { + function (results, next) { + if (!results.isAdminOrGlobalMod && !results.inRoom) { return next(new Error('[[error:not-allowed]]')); } @@ -321,13 +311,23 @@ SocketModules.chats.getMessages = function(socket, data, callback) { if (!socket.uid || !data.uid || !data.roomId) { return callback(new Error('[[error:invalid-data]]')); } + var params = { uid: data.uid, roomId: data.roomId, - start: parseInt(data.start, 10) + 1, + start: parseInt(data.start, 10) || 0, count: 50, markRead: false }; + + if (data.hasOwnProperty('since')) { + params.since = data.since; + } + + if (data.hasOwnProperty('markRead')) { + params.markRead = data.markRead; + } + if (socket.uid === parseInt(data.uid, 10)) { return Messaging.getMessages(params, callback); } From 128ef884bf9a3aca85e42649aff1293dc2b0ee6a Mon Sep 17 00:00:00 2001 From: barisusakli Date: Mon, 3 Oct 2016 18:56:39 +0300 Subject: [PATCH 38/43] #5077 --- src/topics.js | 41 +++++++++-------------------------------- 1 file changed, 9 insertions(+), 32 deletions(-) diff --git a/src/topics.js b/src/topics.js index 3248d8f567..9fb8f827a8 100644 --- a/src/topics.js +++ b/src/topics.js @@ -345,7 +345,7 @@ var social = require('./social'); } }; - Topics.getTopicBookmarks = function( tid, callback ){ + Topics.getTopicBookmarks = function(tid, callback) { db.getSortedSetRangeWithScores(['tid:' + tid + ':bookmarks'], 0, -1, callback); }; @@ -372,49 +372,26 @@ var social = require('./social'); }; }); - async.map(uidData, function(data, mapCallback) { - posts.getPostIndices(forkedPosts, data.uid, function(err, indices) { + async.eachLimit(uidData, 50, function(data, next) { + posts.getPostIndices(forkedPosts, data.uid, function(err, postIndices) { if (err) { - return callback(err); + return next(err); } - data.postIndices = indices; - mapCallback(null, data); - }); - }, function(err, results) { - if (err) { - return callback(err); - } - async.map(results, function(data, mapCallback) { - var uid = data.uid; + var bookmark = data.bookmark; bookmark = bookmark < maxIndex ? bookmark : maxIndex; - var postIndices = data.postIndices; - for (var i = 0; i < postIndices.length && postIndices[i] < data.bookmark; ++i ){ + for (var i = 0; i < postIndices.length && postIndices[i] < data.bookmark; ++i) { --bookmark; } if (parseInt(bookmark, 10) !== parseInt(data.bookmark, 10)) { - mapCallback( null, { uid: uid, bookmark: bookmark } ); + Topics.setUserBookmark(tid, data.uid, bookmark, next); } else { - mapCallback( null, null ); + next(); } - }, function(err, results) { - if (err) { - return callback(err); - } - - async.map(results, function(ui, cb) { - if( ui && ui.bookmark) { - Topics.setUserBookmark(tid, ui.uid, ui.bookmark, cb); - } else { - return cb(null, null); - } - }, function(err) { - next(err); - }); }); - }); + }, next); } ], function(err){ callback(err); From fe50c8d124ca1fa09e70355f8e55991e6185a377 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Mon, 3 Oct 2016 20:35:36 +0300 Subject: [PATCH 39/43] closes #5078 --- public/src/client/chats.js | 8 +- src/controllers/accounts/chats.js | 8 +- src/messaging.js | 174 +++++++++++++++++------------- src/messaging/rooms.js | 13 ++- src/routes/accounts.js | 2 +- src/socket.io/modules.js | 38 ++----- 6 files changed, 136 insertions(+), 107 deletions(-) diff --git a/public/src/client/chats.js b/public/src/client/chats.js index b7ef28bc32..94625a5779 100644 --- a/public/src/client/chats.js +++ b/public/src/client/chats.js @@ -101,7 +101,9 @@ define('forum/chats', [ if (err) { return app.alertError(err.message); } - + if (!data) { + return; + } messages.parseMessage(data, function(html) { var currentScrollTop = el.scrollTop(); var previousHeight = el[0].scrollHeight; @@ -309,7 +311,9 @@ define('forum/chats', [ if (err) { return app.alertError(err.message); } - + if (!messageData) { + return; + } chatContentEl.find('[component="chat/message"]').remove(); messages.appendChatMessage(chatContentEl, messageData); diff --git a/src/controllers/accounts/chats.js b/src/controllers/accounts/chats.js index b1d23ebeb3..12ea675e8d 100644 --- a/src/controllers/accounts/chats.js +++ b/src/controllers/accounts/chats.js @@ -30,10 +30,13 @@ chatsController.get = function(req, res, callback) { if (!uid) { return callback(); } - messaging.getRecentChats(uid, 0, 19, next); + messaging.getRecentChats(req.uid, uid, 0, 19, next); }, function(_recentChats, next) { recentChats = _recentChats; + if (!recentChats) { + return callback(); + } if (!req.params.roomid) { return res.render('chats', { rooms: recentChats.rooms, @@ -48,12 +51,13 @@ chatsController.get = function(req, res, callback) { messaging.isUserInRoom(req.uid, req.params.roomid, next); }, function(inRoom, next) { - if (!inRoom && parseInt(req.uid, 10) === parseInt(uid, 10)) { + if (!inRoom) { return callback(); } async.parallel({ users: async.apply(messaging.getUsersInRoom, req.params.roomid, 0, -1), messages: async.apply(messaging.getMessages, { + callerUid: req.uid, uid: uid, roomId: req.params.roomid, since: 'recent', diff --git a/src/messaging.js b/src/messaging.js index b185e43964..532b375b41 100644 --- a/src/messaging.js +++ b/src/messaging.js @@ -1,18 +1,17 @@ 'use strict'; -var async = require('async'), - winston = require('winston'), - S = require('string'), +var async = require('async'); +var winston = require('winston'); +var S = require('string'); - - db = require('./database'), - user = require('./user'), - plugins = require('./plugins'), - meta = require('./meta'), - utils = require('../public/src/utils'), - notifications = require('./notifications'), - userNotifications = require('./user/notifications'); +var db = require('./database'); +var user = require('./user'); +var plugins = require('./plugins'); +var meta = require('./meta'); +var utils = require('../public/src/utils'); +var notifications = require('./notifications'); +var userNotifications = require('./user/notifications'); (function(Messaging) { @@ -63,34 +62,37 @@ var async = require('async'), count = 50; min = 0; } - - db.getSortedSetRevRangeByScore('uid:' + uid + ':chat:room:' + roomId + ':mids', start, count, '+inf', min, function(err, mids) { - if (err) { - return callback(err); - } - - if (!Array.isArray(mids) || !mids.length) { - return callback(null, []); - } - var indices = {}; - mids.forEach(function(mid, index) { - indices[mid] = start + index; - }); - - mids.reverse(); - - Messaging.getMessagesData(mids, uid, roomId, isNew, function(err, messageData) { - if (err) { - return callback(err); + var indices = {}; + async.waterfall([ + function(next) { + canGetMessages(params.callerUid, params.uid, next); + }, + function(canGet, next) { + if (!canGet) { + return callback(null, null); + } + db.getSortedSetRevRangeByScore('uid:' + uid + ':chat:room:' + roomId + ':mids', start, count, '+inf', min, next); + }, + function(mids, next) { + if (!Array.isArray(mids) || !mids.length) { + return callback(null, []); } - for(var i=0; i 2; @@ -307,11 +323,21 @@ var async = require('async'), }).join(', '); }); - callback(null, {rooms: results.roomData, nextStart: stop + 1}); - }); - }); + next(null, {rooms: results.roomData, nextStart: stop + 1}); + } + ], callback); }; + function canGetRecentChats(callerUid, uid, callback) { + plugins.fireHook('filter:messaging.canGetRecentChats', { + callerUid: callerUid, + uid: uid, + canGet: parseInt(callerUid, 10) === parseInt(uid, 10) + }, function(err, data) { + callback(err, data ? data.canGet : false); + }); + } + Messaging.getTeaser = function (uid, roomId, callback) { var teaser; async.waterfall([ diff --git a/src/messaging/rooms.js b/src/messaging/rooms.js index 7433da44c6..92a5815df6 100644 --- a/src/messaging/rooms.js +++ b/src/messaging/rooms.js @@ -5,6 +5,7 @@ var validator = require('validator'); var db = require('../database'); var user = require('../user'); +var plugins = require('../plugins'); module.exports = function(Messaging) { @@ -74,7 +75,17 @@ module.exports = function(Messaging) { }; Messaging.isUserInRoom = function(uid, roomId, callback) { - db.isSortedSetMember('chat:room:' + roomId + ':uids', uid, callback); + async.waterfall([ + function(next) { + db.isSortedSetMember('chat:room:' + roomId + ':uids', uid, next); + }, + function(inRoom, next) { + plugins.fireHook('filter:messaging.isUserInRoom', {uid: uid, roomId: roomId, inRoom: inRoom}, next); + }, + function(data, next) { + next(null, data.inRoom); + } + ], callback); }; Messaging.roomExists = function(roomId, callback) { diff --git a/src/routes/accounts.js b/src/routes/accounts.js index 9d17b8f86a..27db7a308a 100644 --- a/src/routes/accounts.js +++ b/src/routes/accounts.js @@ -31,6 +31,6 @@ module.exports = function (app, middleware, controllers) { app.delete('/api/user/:userslug/session/:uuid', [middleware.requireUser], controllers.accounts.session.revoke); setupPageRoute(app, '/notifications', middleware, [middleware.authenticate], controllers.accounts.notifications.get); - setupPageRoute(app, '/user/:userslug/chats/:roomid?', middleware, accountMiddlewares, controllers.accounts.chats.get); + setupPageRoute(app, '/user/:userslug/chats/:roomid?', middleware, middlewares, controllers.accounts.chats.get); setupPageRoute(app, '/chats/:roomid?', middleware, [], controllers.accounts.chats.redirectToChat); }; diff --git a/src/socket.io/modules.js b/src/socket.io/modules.js index ee60c76a9b..4f8e0ab130 100644 --- a/src/socket.io/modules.js +++ b/src/socket.io/modules.js @@ -55,7 +55,7 @@ SocketModules.chats.newRoom = function(socket, data, callback) { }; SocketModules.chats.send = function(socket, data, callback) { - if (!data || !data.roomId) { + if (!data || !data.roomId || !socket.uid) { return callback(new Error('[[error:invalid-data]]')); } @@ -106,13 +106,10 @@ SocketModules.chats.loadRoom = function(socket, data, callback) { async.waterfall([ function (next) { - async.parallel({ - inRoom: async.apply(Messaging.isUserInRoom, socket.uid, data.roomId), - isAdminOrGlobalMod: async.apply(user.isAdminOrGlobalMod, socket.uid) - }, next); + Messaging.isUserInRoom(socket.uid, data.roomId, next); }, - function (results, next) { - if (!results.isAdminOrGlobalMod && !results.inRoom) { + function (inRoom, next) { + if (!inRoom) { return next(new Error('[[error:not-allowed]]')); } @@ -222,6 +219,9 @@ SocketModules.chats.canMessage = function(socket, roomId, callback) { }; SocketModules.chats.markRead = function(socket, roomId, callback) { + if (!socket.uid) { + return callback(new Error('[[error:invalid-data]]')); + } async.parallel({ usersInRoom: async.apply(Messaging.getUidsInRoom, roomId, 0, -1), markRead: async.apply(Messaging.markRead, socket.uid, roomId) @@ -283,21 +283,12 @@ SocketModules.chats.renameRoom = function(socket, data, callback) { }; SocketModules.chats.getRecentChats = function(socket, data, callback) { - if (!data || !utils.isNumber(data.after)) { + if (!data || !utils.isNumber(data.after) || !utils.isNumber(data.uid)) { return callback(new Error('[[error:invalid-data]]')); } var start = parseInt(data.after, 10); var stop = start + 9; - if (socket.uid === parseInt(data.uid, 10)) { - return Messaging.getRecentChats(socket.uid, start, stop, callback); - } - - user.isAdminOrGlobalMod(socket.uid, function(err, isAdminOrGlobalMod) { - if (err || !isAdminOrGlobalMod) { - return callback(err || new Error('[[error:no-privileges]]')); - } - Messaging.getRecentChats(data.uid, start, stop, callback); - }); + Messaging.getRecentChats(socket.uid, data.uid, start, stop, callback); }; SocketModules.chats.hasPrivateChat = function(socket, uid, callback) { @@ -313,6 +304,7 @@ SocketModules.chats.getMessages = function(socket, data, callback) { } var params = { + callerUid: socket.uid, uid: data.uid, roomId: data.roomId, start: parseInt(data.start, 10) || 0, @@ -328,15 +320,7 @@ SocketModules.chats.getMessages = function(socket, data, callback) { params.markRead = data.markRead; } - if (socket.uid === parseInt(data.uid, 10)) { - return Messaging.getMessages(params, callback); - } - user.isAdminOrGlobalMod(socket.uid, function(err, isAdminOrGlobalMod) { - if (err || !isAdminOrGlobalMod) { - return callback(err || new Error('[[error:no-privileges]]')); - } - Messaging.getMessages(params, callback); - }); + Messaging.getMessages(params, callback); }; /* Sounds */ From 0da9bf2698c33267852108773234f78902af681d Mon Sep 17 00:00:00 2001 From: barisusakli Date: Mon, 3 Oct 2016 21:02:07 +0300 Subject: [PATCH 40/43] remove since in chat --- public/src/client/chats.js | 28 ---------------------------- public/src/modules/chat.js | 3 --- 2 files changed, 31 deletions(-) diff --git a/public/src/client/chats.js b/public/src/client/chats.js index 94625a5779..d6fc4ddb2d 100644 --- a/public/src/client/chats.js +++ b/public/src/client/chats.js @@ -79,7 +79,6 @@ define('forum/chats', [ recentChats.init(); - Chats.addSinceHandler(ajaxify.data.roomId, ajaxify.data.uid, $('.expanded-chat .chat-content'), $('.expanded-chat [data-since]')); Chats.addRenameHandler(ajaxify.data.roomId, $('[component="chat/room/name"]')); Chats.addScrollHandler(ajaxify.data.roomId, ajaxify.data.uid, $('.chat-content')); }; @@ -158,16 +157,6 @@ define('forum/chats', [ }); }; - Chats.addSinceHandler = function(roomId, uid, chatContentEl, sinceEl) { - sinceEl.on('click', function() { - var since = $(this).attr('data-since'); - sinceEl.removeClass('selected'); - $(this).addClass('selected'); - Chats.loadChatSince(roomId, uid, chatContentEl, since); - return false; - }); - }; - Chats.addRenameHandler = function(roomId, inputEl) { var oldName = inputEl.val(); inputEl.on('blur keypress', function(ev) { @@ -303,23 +292,6 @@ define('forum/chats', [ ajaxify.go('user/' + ajaxify.data.userslug + '/chats/' + roomid); }; - Chats.loadChatSince = function(roomId, uid, chatContentEl, since) { - if (!roomId) { - return; - } - socket.emit('modules.chats.getMessages', {roomId: roomId, uid: uid, since: since, markRead: true}, function(err, messageData) { - if (err) { - return app.alertError(err.message); - } - if (!messageData) { - return; - } - chatContentEl.find('[component="chat/message"]').remove(); - - messages.appendChatMessage(chatContentEl, messageData); - }); - }; - Chats.addGlobalEventListeners = function() { $(window).on('resize', Chats.resizeMainWindow); $(window).on('mousemove keypress click', function() { diff --git a/public/src/modules/chat.js b/public/src/modules/chat.js index e3e2bf0a0e..80e3b8fe74 100644 --- a/public/src/modules/chat.js +++ b/public/src/modules/chat.js @@ -255,7 +255,6 @@ define('chat', [ messagesEl.css('height', module.calculateChatListHeight(chatModal)); }); - Chats.addSinceHandler(chatModal.attr('roomId'), data.uid, chatModal.find('.chat-content'), chatModal.find('[data-since]')); Chats.addRenameHandler(chatModal.attr('roomId'), chatModal.find('[component="chat/room/name"]')); Chats.addSendHandlers(chatModal.attr('roomId'), chatModal.find('#chat-message-input'), chatModal.find('#chat-message-send-btn')); @@ -263,8 +262,6 @@ define('chat', [ Chats.createTagsInput(chatModal.find('.users-tag-input'), data); Chats.createAutoComplete(chatModal.find('[component="chat/input"]')); - Chats.loadChatSince(chatModal.attr('roomId'), data.uid, chatModal.find('.chat-content'), 'recent'); - Chats.addScrollHandler(chatModal.attr('roomId'), data.uid, chatModal.find('.chat-content')); checkStatus(chatModal); From a254222911d83201f52c25248ed64674fbefda28 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Mon, 3 Oct 2016 21:15:32 +0300 Subject: [PATCH 41/43] if user is already part of group skip instead of error --- src/groups/membership.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/groups/membership.js b/src/groups/membership.js index 17e70a12dc..14f34f0084 100644 --- a/src/groups/membership.js +++ b/src/groups/membership.js @@ -189,9 +189,9 @@ module.exports = function(Groups) { if (!checks.exists) { return next(new Error('[[error:no-group]]')); } else if (checks.isMember) { - return next(new Error('[[error:group-already-member]]')); + return callback(); } else if (type === 'invite' && checks.isInvited) { - return next(new Error('[[error:group-already-invited]]')); + return callback(); } else if (type === 'request' && checks.isPending) { return next(new Error('[[error:group-already-requested]]')); } From a9cb582c702e9536292cf2a5bfb405dc1aff2676 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Mon, 3 Oct 2016 21:18:29 +0300 Subject: [PATCH 42/43] up themes --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 84128c76f8..616c14ce15 100644 --- a/package.json +++ b/package.json @@ -61,8 +61,8 @@ "nodebb-plugin-spam-be-gone": "0.4.10", "nodebb-rewards-essentials": "0.0.9", "nodebb-theme-lavender": "3.0.14", - "nodebb-theme-persona": "4.1.54", - "nodebb-theme-vanilla": "5.1.35", + "nodebb-theme-persona": "4.1.55", + "nodebb-theme-vanilla": "5.1.36", "nodebb-widget-essentials": "2.0.11", "nodemailer": "2.0.0", "nodemailer-sendmail-transport": "1.0.0", From aca0a893e7ab52003e016eec382ea3f0d3610ba7 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Mon, 3 Oct 2016 22:18:47 +0300 Subject: [PATCH 43/43] remove since properly --- package.json | 4 +- public/src/app.js | 2 +- public/src/modules/chat.js | 222 ++++++++++++++---------------- src/controllers/accounts/chats.js | 1 - src/messaging.js | 18 +-- src/socket.io/modules.js | 13 +- 6 files changed, 117 insertions(+), 143 deletions(-) diff --git a/package.json b/package.json index 616c14ce15..cb83742b5b 100644 --- a/package.json +++ b/package.json @@ -61,8 +61,8 @@ "nodebb-plugin-spam-be-gone": "0.4.10", "nodebb-rewards-essentials": "0.0.9", "nodebb-theme-lavender": "3.0.14", - "nodebb-theme-persona": "4.1.55", - "nodebb-theme-vanilla": "5.1.36", + "nodebb-theme-persona": "4.1.56", + "nodebb-theme-vanilla": "5.1.37", "nodebb-widget-essentials": "2.0.11", "nodemailer": "2.0.0", "nodemailer-sendmail-transport": "1.0.0", diff --git a/public/src/app.js b/public/src/app.js index 7fd5bba563..46f0419709 100644 --- a/public/src/app.js +++ b/public/src/app.js @@ -281,7 +281,7 @@ app.cacheBuster = null; if (chat.modalExists(roomId)) { loadAndCenter(chat.getModal(roomId)); } else { - socket.emit('modules.chats.loadRoom', {roomId: roomId}, function(err, roomData) { + socket.emit('modules.chats.loadRoom', {roomId: roomId, uid: uid || app.user.uid}, function(err, roomData) { if (err) { return app.alertError(err.message); } diff --git a/public/src/modules/chat.js b/public/src/modules/chat.js index 80e3b8fe74..6034eacfb0 100644 --- a/public/src/modules/chat.js +++ b/public/src/modules/chat.js @@ -154,131 +154,117 @@ define('chat', [ return $('#chat-modal-' + roomId).length !== 0; }; - function checkStatus(chatModal) { - socket.emit('user.checkStatus', chatModal.attr('touid'), function(err, status) { - if (err) { - return app.alertError(err.message); + module.createModal = function(data, callback) { + app.parseAndTranslate('chat', data, function(chatModal) { + + var uuid = utils.generateUUID(); + var dragged = false; + + chatModal.attr('id', 'chat-modal-' + data.roomId); + chatModal.attr('roomId', data.roomId); + chatModal.attr('intervalId', 0); + chatModal.attr('UUID', uuid); + chatModal.css('position', 'fixed'); + chatModal.css('zIndex', 100); + chatModal.appendTo($('body')); + chatModal.find('.timeago').timeago(); + module.center(chatModal); + + app.loadJQueryUI(function() { + chatModal.find('.modal-content').resizable({ + handles: 'n, e, s, w, se', + minHeight: 250, + minWidth: 400 + }); + + chatModal.find('.modal-content').on('resize', function(event, ui) { + if (ui.originalSize.height === ui.size.height) { + return; + } + + chatModal.find('.chat-content').css('height', module.calculateChatListHeight(chatModal)); + }); + + chatModal.draggable({ + start:function() { + module.bringModalToTop(chatModal); + }, + stop:function() { + chatModal.find('#chat-message-input').focus(); + }, + distance: 10, + handle: '.modal-header' + }); + }); + + chatModal.find('#chat-close-btn').on('click', function() { + module.close(chatModal); + }); + + function gotoChats() { + var text = components.get('chat/input').val(); + $(window).one('action:ajaxify.end', function() { + components.get('chat/input').val(text); + }); + + ajaxify.go('user/' + app.user.userslug + '/chats/' + chatModal.attr('roomId')); + module.close(chatModal); } - app.updateUserStatus(chatModal.find('[component="user/status"]'), status); - }); - } + chatModal.find('.modal-header').on('dblclick', gotoChats); + chatModal.find('button[data-action="maximize"]').on('click', gotoChats); - module.createModal = function(data, callback) { - templates.parse('chat', data, function(chatTpl) { - translator.translate(chatTpl, function (chatTpl) { + chatModal.on('click', function() { + module.bringModalToTop(chatModal); - var chatModal = $(chatTpl), - uuid = utils.generateUUID(), + if (dragged) { dragged = false; - - chatModal.attr('id', 'chat-modal-' + data.roomId); - chatModal.attr('roomId', data.roomId); - chatModal.attr('intervalId', 0); - chatModal.attr('UUID', uuid); - chatModal.css('position', 'fixed'); - chatModal.css('zIndex', 100); - chatModal.appendTo($('body')); - module.center(chatModal); - - app.loadJQueryUI(function() { - chatModal.find('.modal-content').resizable({ - handles: 'n, e, s, w, se', - minHeight: 250, - minWidth: 400 - }); - - chatModal.find('.modal-content').on('resize', function(event, ui) { - if (ui.originalSize.height === ui.size.height) { - return; - } - - chatModal.find('.chat-content').css('height', module.calculateChatListHeight(chatModal)); - }); - - chatModal.draggable({ - start:function() { - module.bringModalToTop(chatModal); - }, - stop:function() { - chatModal.find('#chat-message-input').focus(); - }, - distance: 10, - handle: '.modal-header' - }); - }); - - chatModal.find('#chat-close-btn').on('click', function() { - module.close(chatModal); - }); - - function gotoChats() { - var text = components.get('chat/input').val(); - $(window).one('action:ajaxify.end', function() { - components.get('chat/input').val(text); - }); - - ajaxify.go('user/' + app.user.userslug + '/chats/' + chatModal.attr('roomId')); - module.close(chatModal); - } - - chatModal.find('.modal-header').on('dblclick', gotoChats); - chatModal.find('button[data-action="maximize"]').on('click', gotoChats); - - chatModal.on('click', function() { - module.bringModalToTop(chatModal); - - if (dragged) { - dragged = false; - } - }); - - chatModal.on('mousemove', function(e) { - if (e.which === 1) { - dragged = true; - } - }); - - chatModal.on('mousemove keypress click', function() { - if (newMessage) { - socket.emit('modules.chats.markRead', data.roomId); - newMessage = false; - } - }); - - Chats.addEditDeleteHandler(chatModal.find('[component="chat/messages"]'), data.roomId); - - chatModal.find('[component="chat/controlsToggle"]').on('click', function() { - var messagesEl = chatModal.find('[component="chat/messages"]'); - - chatModal.find('[component="chat/controls"]').toggle(); - messagesEl.css('height', module.calculateChatListHeight(chatModal)); - }); - - Chats.addRenameHandler(chatModal.attr('roomId'), chatModal.find('[component="chat/room/name"]')); - - Chats.addSendHandlers(chatModal.attr('roomId'), chatModal.find('#chat-message-input'), chatModal.find('#chat-message-send-btn')); - - Chats.createTagsInput(chatModal.find('.users-tag-input'), data); - Chats.createAutoComplete(chatModal.find('[component="chat/input"]')); - - Chats.addScrollHandler(chatModal.attr('roomId'), data.uid, chatModal.find('.chat-content')); - - checkStatus(chatModal); - - taskbar.push('chat', chatModal.attr('UUID'), { - title: data.users.length ? data.users[0].username : '', - roomId: data.roomId, - icon: 'fa-comment', - state: '' - }); - - $(window).trigger('action:chat.loaded', chatModal); - - if (typeof callback === 'function') { - callback(chatModal); } }); + + chatModal.on('mousemove', function(e) { + if (e.which === 1) { + dragged = true; + } + }); + + chatModal.on('mousemove keypress click', function() { + if (newMessage) { + socket.emit('modules.chats.markRead', data.roomId); + newMessage = false; + } + }); + + Chats.addEditDeleteHandler(chatModal.find('[component="chat/messages"]'), data.roomId); + + chatModal.find('[component="chat/controlsToggle"]').on('click', function() { + var messagesEl = chatModal.find('[component="chat/messages"]'); + + chatModal.find('[component="chat/controls"]').toggle(); + messagesEl.css('height', module.calculateChatListHeight(chatModal)); + }); + + Chats.addRenameHandler(chatModal.attr('roomId'), chatModal.find('[component="chat/room/name"]')); + + Chats.addSendHandlers(chatModal.attr('roomId'), chatModal.find('#chat-message-input'), chatModal.find('#chat-message-send-btn')); + + Chats.createTagsInput(chatModal.find('.users-tag-input'), data); + Chats.createAutoComplete(chatModal.find('[component="chat/input"]')); + + Chats.addScrollHandler(chatModal.attr('roomId'), data.uid, chatModal.find('.chat-content')); + + taskbar.push('chat', chatModal.attr('UUID'), { + title: data.users.length ? data.users[0].username : '', + roomId: data.roomId, + icon: 'fa-comment', + state: '' + }); + + $(window).trigger('action:chat.loaded', chatModal); + + if (typeof callback === 'function') { + callback(chatModal); + } }); }; diff --git a/src/controllers/accounts/chats.js b/src/controllers/accounts/chats.js index 12ea675e8d..ddde8efb5e 100644 --- a/src/controllers/accounts/chats.js +++ b/src/controllers/accounts/chats.js @@ -60,7 +60,6 @@ chatsController.get = function(req, res, callback) { callerUid: req.uid, uid: uid, roomId: req.params.roomid, - since: 'recent', isNew: false }), room: async.apply(messaging.getRoomData, req.params.roomid) diff --git a/src/messaging.js b/src/messaging.js index 532b375b41..ae554f7359 100644 --- a/src/messaging.js +++ b/src/messaging.js @@ -22,13 +22,6 @@ var userNotifications = require('./user/notifications'); require('./messaging/unread')(Messaging); require('./messaging/notifications')(Messaging); - var terms = { - day: 86400000, - week: 604800000, - month: 2592000000, - threemonths: 7776000000 - }; - Messaging.getMessageField = function(mid, field, callback) { Messaging.getMessageFields(mid, [field], function(err, fields) { callback(err, fields ? fields[field] : null); @@ -50,18 +43,11 @@ var userNotifications = require('./user/notifications'); Messaging.getMessages = function(params, callback) { var uid = params.uid; var roomId = params.roomId; - var since = params.since; var isNew = params.isNew || false; var start = params.hasOwnProperty('start') ? params.start : 0; - var count = params.count || 250; + var stop = parseInt(start, 10) + ((params.count || 50) - 1); var markRead = params.markRead || true; - var min = params.count ? 0 : Date.now() - (terms[since] || terms.day); - - if (since === 'recent') { - count = 50; - min = 0; - } var indices = {}; async.waterfall([ function(next) { @@ -71,7 +57,7 @@ var userNotifications = require('./user/notifications'); if (!canGet) { return callback(null, null); } - db.getSortedSetRevRangeByScore('uid:' + uid + ':chat:room:' + roomId + ':mids', start, count, '+inf', min, next); + db.getSortedSetRevRange('uid:' + uid + ':chat:room:' + roomId + ':mids', start, stop, next); }, function(mids, next) { if (!Array.isArray(mids) || !mids.length) { diff --git a/src/socket.io/modules.js b/src/socket.io/modules.js index 4f8e0ab130..d2097ff800 100644 --- a/src/socket.io/modules.js +++ b/src/socket.io/modules.js @@ -115,11 +115,18 @@ SocketModules.chats.loadRoom = function(socket, data, callback) { async.parallel({ roomData: async.apply(Messaging.getRoomData, data.roomId), - users: async.apply(Messaging.getUsersInRoom, data.roomId, 0, -1) + users: async.apply(Messaging.getUsersInRoom, data.roomId, 0, -1), + messages: async.apply(Messaging.getMessages, { + callerUid: socket.uid, + uid: data.uid || socket.uid, + roomId: data.roomId, + isNew: false + }), }, next); }, function (results, next) { results.roomData.users = results.users; + results.roomData.messages = results.messages; results.roomData.groupChat = results.roomData.hasOwnProperty('groupChat') ? results.roomData.groupChat : results.users.length > 2; results.roomData.isOwner = parseInt(results.roomData.owner, 10) === socket.uid; results.roomData.maximumUsersInChatRoom = parseInt(meta.config.maximumUsersInChatRoom, 10) || 0; @@ -312,10 +319,6 @@ SocketModules.chats.getMessages = function(socket, data, callback) { markRead: false }; - if (data.hasOwnProperty('since')) { - params.since = data.since; - } - if (data.hasOwnProperty('markRead')) { params.markRead = data.markRead; }