From 9f2e5e9c4b1bf804dc1074a2caecbbfd912e30ca Mon Sep 17 00:00:00 2001 From: psychobunny Date: Wed, 8 Mar 2017 11:31:58 -0500 Subject: [PATCH 01/25] closes #4685 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5ba13271b9..82606a8e35 100644 --- a/package.json +++ b/package.json @@ -87,7 +87,7 @@ "socket.io-redis": "3.1.0", "socketio-wildcard": "~0.3.0", "string": "^3.0.0", - "templates.js": "0.3.6", + "templates.js": "0.3.10", "toobusy-js": "^0.5.1", "uglify-js": "^2.6.0", "underscore": "^1.8.3", From 57691d9ad8cadabc96ee00121fe5341f1b5a9c8b Mon Sep 17 00:00:00 2001 From: barisusakli Date: Thu, 9 Mar 2017 17:18:30 +0300 Subject: [PATCH 02/25] test for system group rename --- src/groups/update.js | 118 ++++++++++++++++++++++++------------------- test/groups.js | 9 ++++ 2 files changed, 75 insertions(+), 52 deletions(-) diff --git a/src/groups/update.js b/src/groups/update.js index 99e8dcc65a..95ec22753c 100644 --- a/src/groups/update.js +++ b/src/groups/update.js @@ -91,16 +91,18 @@ module.exports = function (Groups) { async.apply(db.sortedSetRemove, 'groups:visible:name', groupName.toLowerCase() + ':' + groupName), ], callback); } else { - db.getObjectFields('group:' + groupName, ['createtime', 'memberCount'], function (err, groupData) { - if (err) { - return callback(err); - } - async.parallel([ - async.apply(db.sortedSetAdd, 'groups:visible:createtime', groupData.createtime, groupName), - async.apply(db.sortedSetAdd, 'groups:visible:memberCount', groupData.memberCount, groupName), - async.apply(db.sortedSetAdd, 'groups:visible:name', 0, groupName.toLowerCase() + ':' + groupName), - ], callback); - }); + async.waterfall([ + function (next) { + db.getObjectFields('group:' + groupName, ['createtime', 'memberCount'], next); + }, + function (groupData, next) { + async.parallel([ + async.apply(db.sortedSetAdd, 'groups:visible:createtime', groupData.createtime, groupName), + async.apply(db.sortedSetAdd, 'groups:visible:memberCount', groupData.memberCount, groupName), + async.apply(db.sortedSetAdd, 'groups:visible:name', 0, groupName.toLowerCase() + ':' + groupName), + ], next); + }, + ], callback); } } @@ -155,40 +157,48 @@ module.exports = function (Groups) { function checkNameChange(currentName, newName, callback) { if (currentName === newName) { - return callback(); + return setImmediate(callback); } var currentSlug = utils.slugify(currentName); var newSlug = utils.slugify(newName); if (currentSlug === newSlug) { - return callback(); + return setImmediate(callback); } - Groups.existsBySlug(newSlug, function (err, exists) { - if (err || exists) { - return callback(err || new Error('[[error:group-already-exists]]')); - } - callback(); - }); + async.waterfall([ + function (next) { + Groups.existsBySlug(newSlug, next); + }, + function (exists, next) { + next(!exists ? new Error('[[error:group-already-exists]]') : null); + }, + ], callback); } function renameGroup(oldName, newName, callback) { if (oldName === newName || !newName || newName.length === 0) { - return callback(); + return setImmediate(callback); } - - db.getObject('group:' + oldName, function (err, group) { - if (err || !group) { - return callback(err); - } - - if (parseInt(group.system, 10) === 1) { - return callback(); - } - - Groups.exists(newName, function (err, exists) { - if (err || exists) { - return callback(err || new Error('[[error:group-already-exists]]')); + var group; + async.waterfall([ + function (next) { + db.getObject('group:' + oldName, next); + }, + function (_group, next) { + group = _group; + if (!group) { + return callback(); } + if (parseInt(group.system, 10) === 1) { + return callback(new Error('[[error:not-allowed-to-rename-system-group]]')); + } + + Groups.exists(newName, next); + }, + function (exists, next) { + if (exists) { + return callback(new Error('[[error:group-already-exists]]')); + } async.series([ async.apply(db.setObjectField, 'group:' + oldName, 'name', newName), async.apply(db.setObjectField, 'group:' + oldName, 'slug', utils.slugify(newName)), @@ -222,29 +232,33 @@ module.exports = function (Groups) { next(); }, - ], callback); - }); + ], next); + }, + ], function (err) { + callback(err); }); } function renameGroupMember(group, oldName, newName, callback) { - db.isSortedSetMember(group, oldName, function (err, isMember) { - if (err || !isMember) { - return callback(err); - } - var score; - async.waterfall([ - function (next) { - db.sortedSetScore(group, oldName, next); - }, - function (_score, next) { - score = _score; - db.sortedSetRemove(group, oldName, next); - }, - function (next) { - db.sortedSetAdd(group, score, newName, next); - }, - ], callback); - }); + var score; + async.waterfall([ + function (next) { + db.isSortedSetMember(group, oldName, next); + }, + function (isMember, next) { + if (!isMember) { + return callback(); + } + + db.sortedSetScore(group, oldName, next); + }, + function (_score, next) { + score = _score; + db.sortedSetRemove(group, oldName, next); + }, + function (next) { + db.sortedSetAdd(group, score, newName, next); + }, + ], callback); } }; diff --git a/test/groups.js b/test/groups.js index 4d587b3aad..6b52787efa 100644 --- a/test/groups.js +++ b/test/groups.js @@ -315,6 +315,15 @@ describe('Groups', function () { }); }); }); + + it('should fail if system groups is being renamed', function (done) { + Groups.update('administrators', { + name: 'administrators_fail', + }, function (err) { + assert.equal(err.message, '[[error:not-allowed-to-rename-system-group]]'); + done(); + }); + }); }); describe('.destroy()', function () { From c619b850ce53083ddeb9dbd932580c9e1912508f Mon Sep 17 00:00:00 2001 From: barisusakli Date: Thu, 9 Mar 2017 17:28:19 +0300 Subject: [PATCH 03/25] fix tests --- src/groups/update.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/groups/update.js b/src/groups/update.js index 95ec22753c..9bf53886e5 100644 --- a/src/groups/update.js +++ b/src/groups/update.js @@ -169,7 +169,7 @@ module.exports = function (Groups) { Groups.existsBySlug(newSlug, next); }, function (exists, next) { - next(!exists ? new Error('[[error:group-already-exists]]') : null); + next(exists ? new Error('[[error:group-already-exists]]') : null); }, ], callback); } From 8d493bf3b0c72faaed5ff7f70bc3282113767eaf Mon Sep 17 00:00:00 2001 From: barisusakli Date: Thu, 9 Mar 2017 19:52:48 +0300 Subject: [PATCH 04/25] post parse test --- src/posts/parse.js | 35 +++++++++++++++-------------------- test/posts.js | 44 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 58 insertions(+), 21 deletions(-) diff --git a/src/posts/parse.js b/src/posts/parse.js index 946c589056..8ac2028bbd 100644 --- a/src/posts/parse.js +++ b/src/posts/parse.js @@ -1,5 +1,6 @@ 'use strict'; +var async = require('async'); var nconf = require('nconf'); var url = require('url'); var winston = require('winston'); @@ -14,31 +15,26 @@ var urlRegex = /href="([^"]+)"/g; module.exports = function (Posts) { Posts.parsePost = function (postData, callback) { - postData.content = postData.content || ''; + postData.content = String(postData.content || ''); if (postData.pid && cache.has(String(postData.pid))) { postData.content = cache.get(String(postData.pid)); return callback(null, postData); } - // Casting post content into a string, just in case - if (typeof postData.content !== 'string') { - postData.content = postData.content.toString(); - } + async.waterfall([ + function (next) { + plugins.fireHook('filter:parse.post', { postData: postData }, next); + }, + function (data, next) { + data.postData.content = translator.escape(data.postData.content); - plugins.fireHook('filter:parse.post', { postData: postData }, function (err, data) { - if (err) { - return callback(err); - } - - data.postData.content = translator.escape(data.postData.content); - - if (global.env === 'production' && data.postData.pid) { - cache.set(String(data.postData.pid), data.postData.content); - } - - callback(null, data.postData); - }); + if (global.env === 'production' && data.postData.pid) { + cache.set(String(data.postData.pid), data.postData.content); + } + next(null, data.postData); + }, + ], callback); }; Posts.parseSignature = function (userData, uid, callback) { @@ -51,7 +47,6 @@ module.exports = function (Posts) { var parsed; var current = urlRegex.exec(content); var absolute; - while (current !== null) { if (current[1]) { try { @@ -78,7 +73,7 @@ module.exports = function (Posts) { }; function sanitizeSignature(signature) { - var string = S(signature); + var string = S(signature); var tagsToStrip = []; if (parseInt(meta.config['signatures:disableLinks'], 10) === 1) { diff --git a/test/posts.js b/test/posts.js index 55d13e1ea4..1a79200e12 100644 --- a/test/posts.js +++ b/test/posts.js @@ -743,6 +743,48 @@ describe('Post\'s', function () { }); }); + describe('parse', function () { + it('should store post content in cache', function (done) { + var oldValue = global.env; + global.env = 'production'; + var postData = { + pid: 9999, + content: 'some post content', + }; + posts.parsePost(postData, function (err) { + assert.ifError(err); + posts.parsePost(postData, function (err) { + assert.ifError(err); + global.env = oldValue; + done(); + }); + }); + }); + + it('should parse signature and remove links and images', function (done) { + var meta = require('../src/meta'); + meta.config['signatures:disableLinks'] = 1; + meta.config['signatures:disableImages'] = 1; + var userData = { + signature: 'test derp', + }; + + posts.parseSignature(userData, 1, function (err, data) { + assert.ifError(err); + assert.equal(data.userData.signature, 'test derp'); + done(); + }); + }); + + it('should turn relative links in post body to absolute urls', function (done) { + var nconf = require('nconf'); + var content = 'test youtube'; + var parsedContent = posts.relativeToAbsolute(content); + assert.equal(parsedContent, 'test youtube'); + done(); + }); + }); + describe('socket methods', function () { var pid; before(function (done) { @@ -809,7 +851,7 @@ describe('Post\'s', function () { }); it('shold error with invalid data', function (done) { - socketPosts.loadMoreBookmarks({ uid: voterUid }, { uid: voterUid, after: null }, function (err, postData) { + socketPosts.loadMoreBookmarks({ uid: voterUid }, { uid: voterUid, after: null }, function (err) { assert.equal(err.message, '[[error:invalid-data]]'); done(); }); From 3d719eec992078c35f36e9bc486633fa2d2544f2 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Thu, 9 Mar 2017 20:18:30 +0300 Subject: [PATCH 05/25] enable sigs after test --- test/posts.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/posts.js b/test/posts.js index 1a79200e12..49a4783872 100644 --- a/test/posts.js +++ b/test/posts.js @@ -772,6 +772,8 @@ describe('Post\'s', function () { posts.parseSignature(userData, 1, function (err, data) { assert.ifError(err); assert.equal(data.userData.signature, 'test derp'); + meta.config['signatures:disableLinks'] = 0; + meta.config['signatures:disableImages'] = 0; done(); }); }); From 74d2835a1f0d35070c2303a2e2456a3b3ca99dd9 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Thu, 9 Mar 2017 20:18:42 +0300 Subject: [PATCH 06/25] escape body class parts --- src/middleware/render.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/middleware/render.js b/src/middleware/render.js index 48d4a0b526..88e9879887 100644 --- a/src/middleware/render.js +++ b/src/middleware/render.js @@ -123,7 +123,7 @@ module.exports = function (middleware) { winston.error(err.message); p = ''; } - + p = validator.escape(String(p)); parts[index] = index ? parts[0] + '-' + p : 'page-' + (p || 'home'); }); return parts.join(' '); From 1c1d97dd547316290d227b53f46126a846cf2153 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Thu, 9 Mar 2017 21:32:43 +0300 Subject: [PATCH 07/25] up spam be gone --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 82606a8e35..ee0cc57714 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "nodebb-plugin-markdown": "7.1.1", "nodebb-plugin-mentions": "1.1.3", "nodebb-plugin-soundpack-default": "1.0.0", - "nodebb-plugin-spam-be-gone": "0.4.10", + "nodebb-plugin-spam-be-gone": "0.4.13", "nodebb-rewards-essentials": "0.0.9", "nodebb-theme-lavender": "3.0.15", "nodebb-theme-persona": "4.2.4", From 0c8058ba9dbb51f23ddf6ae70bdde7df02cc4492 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Thu, 9 Mar 2017 22:36:28 +0300 Subject: [PATCH 08/25] closes #5516 --- src/topics/unread.js | 4 ++-- test/topics.js | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/topics/unread.js b/src/topics/unread.js index cc3101ee05..b2f5b199d1 100644 --- a/src/topics/unread.js +++ b/src/topics/unread.js @@ -206,7 +206,7 @@ module.exports = function (Topics) { Topics.markAsRead = function (tids, uid, callback) { callback = callback || function () {}; if (!Array.isArray(tids) || !tids.length) { - return callback(); + return setImmediate(callback, null, false); } tids = tids.filter(function (tid, index, array) { @@ -214,7 +214,7 @@ module.exports = function (Topics) { }); if (!tids.length) { - return callback(null, false); + return setImmediate(callback, null, false); } async.waterfall([ diff --git a/test/topics.js b/test/topics.js index 5a65cf8ec8..2222395833 100644 --- a/test/topics.js +++ b/test/topics.js @@ -1181,6 +1181,14 @@ describe('Topic\'s', function () { }); }); }); + + it('should not do anything if tids is empty array', function (done) { + socketTopics.markAsRead({ uid: adminUid }, [], function (err, markedRead) { + assert.ifError(err); + assert(!markedRead); + done(); + }); + }); }); describe('tags', function () { From 92fa9fecb6fc552b4c632fae729b392fbba3680f Mon Sep 17 00:00:00 2001 From: barisusakli Date: Fri, 10 Mar 2017 00:31:50 +0300 Subject: [PATCH 09/25] add mongodb connection options #3670 increase reconnect tries add keepAlive setting set autoReconnect to true, should be on by default --- src/database/mongo.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/database/mongo.js b/src/database/mongo.js index 9bc321703b..6e3af3ac64 100644 --- a/src/database/mongo.js +++ b/src/database/mongo.js @@ -84,6 +84,9 @@ var connOptions = { server: { poolSize: parseInt(nconf.get('mongo:poolSize'), 10) || 10, + socketOptions: { autoReconnect: true, keepAlive: nconf.get('mongo:keepAlive') || 0 }, + reconnectTries : 3600, + reconnectInterval : 1000, }, }; From 0c7dee05efeb910e79d9e4129784d4aa0e43b9cd Mon Sep 17 00:00:00 2001 From: barisusakli Date: Fri, 10 Mar 2017 00:38:34 +0300 Subject: [PATCH 10/25] fix lint --- src/database/mongo.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/database/mongo.js b/src/database/mongo.js index 6e3af3ac64..bb3d9f05c2 100644 --- a/src/database/mongo.js +++ b/src/database/mongo.js @@ -85,8 +85,8 @@ server: { poolSize: parseInt(nconf.get('mongo:poolSize'), 10) || 10, socketOptions: { autoReconnect: true, keepAlive: nconf.get('mongo:keepAlive') || 0 }, - reconnectTries : 3600, - reconnectInterval : 1000, + reconnectTries: 3600, + reconnectInterval: 1000, }, }; From fd8e647ef5308c73c4626e93dba6a43efa8c40d9 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Thu, 9 Mar 2017 16:47:07 -0500 Subject: [PATCH 11/25] closes #5506 --- public/language/en-GB/groups.json | 1 + public/src/client/groups/details.js | 26 +++++++++++++++++--------- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/public/language/en-GB/groups.json b/public/language/en-GB/groups.json index a55cc8603f..08c8d4d1f5 100644 --- a/public/language/en-GB/groups.json +++ b/public/language/en-GB/groups.json @@ -32,6 +32,7 @@ "details.disableJoinRequests": "Disable join requests", "details.grant": "Grant/Rescind Ownership", "details.kick": "Kick", + "details.kick_confirm": "Are you sure you want to remove this member from the group?", "details.owner_options": "Group Administration", "details.group_name": "Group Name", diff --git a/public/src/client/groups/details.js b/public/src/client/groups/details.js index 4f7a11a892..e7225bb16c 100644 --- a/public/src/client/groups/details.js +++ b/public/src/client/groups/details.js @@ -75,15 +75,23 @@ define('forum/groups/details', [ break; case 'kick': - socket.emit('groups.kick', { - uid: uid, - groupName: groupName, - }, function (err) { - if (!err) { - userRow.slideUp().remove(); - } else { - app.alertError(err.message); - } + translator.translate('[[groups:details.kick_confirm]]', function (translated) { + bootbox.confirm(translated, function (confirm) { + if (!confirm) { + return; + } + + socket.emit('groups.kick', { + uid: uid, + groupName: groupName, + }, function (err) { + if (!err) { + userRow.slideUp().remove(); + } else { + app.alertError(err.message); + } + }); + }); }); break; From 8da8e4d8c33f0e9501aeeb00c33320be3fb94bcf Mon Sep 17 00:00:00 2001 From: psychobunny Date: Thu, 9 Mar 2017 16:50:26 -0500 Subject: [PATCH 12/25] closes #5469 --- public/language/en-GB/admin/manage/flags.json | 2 +- src/views/admin/manage/flags.tpl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/public/language/en-GB/admin/manage/flags.json b/public/language/en-GB/admin/manage/flags.json index bfc488a409..8286861d01 100644 --- a/public/language/en-GB/admin/manage/flags.json +++ b/public/language/en-GB/admin/manage/flags.json @@ -9,7 +9,7 @@ "search": "Search", "dismiss-all": "Dismiss All", "none-flagged": "No flagged posts!", - "posted-in": "Posted in %1", + "posted-in": "Posted in", "read-more": "Read More", "flagged-x-times": "This post has been flagged %1 time(s):", "dismiss": "Dismiss this Flag", diff --git a/src/views/admin/manage/flags.tpl b/src/views/admin/manage/flags.tpl index 995dd13a8f..a6351009d8 100644 --- a/src/views/admin/manage/flags.tpl +++ b/src/views/admin/manage/flags.tpl @@ -105,7 +105,7 @@ - [[posted-in, {posts.category.name}]], + [[admin/manage/flags:posted-in]] {posts.category.name} [[admin/manage/flags:read-more]] From 5e0de4b8fbed018877657fb71ea4c03bed382f88 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Fri, 10 Mar 2017 12:21:59 +0300 Subject: [PATCH 13/25] closes #5517 --- src/database/mongo.js | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/src/database/mongo.js b/src/database/mongo.js index bb3d9f05c2..8e6494ffd7 100644 --- a/src/database/mongo.js +++ b/src/database/mongo.js @@ -47,13 +47,8 @@ module.init = function (callback) { callback = callback || function () { }; - var mongoClient; - try { - mongoClient = require('mongodb').MongoClient; - } catch (err) { - winston.error('Unable to initialize MongoDB! Is MongoDB installed? Error :' + err.message); - return callback(err); - } + + var mongoClient = require('mongodb').MongoClient; var usernamePassword = ''; if (nconf.get('mongo:username') && nconf.get('mongo:password')) { @@ -90,7 +85,7 @@ }, }; - connOptions = _.deepExtend((nconf.get('mongo:options') || {}), connOptions); + connOptions = _.deepExtend(connOptions, nconf.get('mongo:options') || {}); mongoClient.connect(connString, connOptions, function (err, _db) { if (err) { @@ -110,10 +105,7 @@ if (nconf.get('mongo:password') && nconf.get('mongo:username')) { db.authenticate(nconf.get('mongo:username'), nconf.get('mongo:password'), function (err) { - if (err) { - return callback(err); - } - callback(); + callback(err); }); } else { winston.warn('You have no mongo password setup!'); From dc4d394cd5157fd4edd19ef229981372ab678b59 Mon Sep 17 00:00:00 2001 From: "Misty (Bot)" Date: Fri, 10 Mar 2017 09:22:18 +0000 Subject: [PATCH 14/25] Latest translations and fallbacks --- public/language/pl/admin/settings/group.json | 2 +- public/language/pl/admin/settings/tags.json | 2 +- public/language/pl/admin/settings/uploads.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/public/language/pl/admin/settings/group.json b/public/language/pl/admin/settings/group.json index 6db8cb32b4..c5900c2a39 100644 --- a/public/language/pl/admin/settings/group.json +++ b/public/language/pl/admin/settings/group.json @@ -1,5 +1,5 @@ { - "general": "General", + "general": "Ogólne", "private-groups": "Prywatne Grupy", "private-groups.help": "If enabled, joining of groups requires the approval of the group owner (Default: enabled)", "private-groups.warning": "Beware! If this option is disabled and you have private groups, they automatically become public.", diff --git a/public/language/pl/admin/settings/tags.json b/public/language/pl/admin/settings/tags.json index d67523c8e6..ef8efabbcd 100644 --- a/public/language/pl/admin/settings/tags.json +++ b/public/language/pl/admin/settings/tags.json @@ -1,6 +1,6 @@ { "tag": "Ustawienia Tagów", - "min-per-topic": "Minimum Tags per Topic", + "min-per-topic": "Minimalna ilość Tagów na Temat", "max-per-topic": "Maximum Tags per Topic", "min-length": "Minimum Tag Length", "max-length": "Maximum Tag Length", diff --git a/public/language/pl/admin/settings/uploads.json b/public/language/pl/admin/settings/uploads.json index 9a610fb576..05edbff41a 100644 --- a/public/language/pl/admin/settings/uploads.json +++ b/public/language/pl/admin/settings/uploads.json @@ -1,6 +1,6 @@ { "posts": "Posty", - "allow-files": "Allow users to upload regular files", + "allow-files": "Pozwolić użytkownikom wgrywać pliki", "private": "Make uploaded files private", "max-image-width": "Resize images down to specified width (in pixels)", "max-image-width-help": "(in pixels, default: 760 pixels, set to 0 to disable)", From b3f8428691e08f70db0543904f79cb7a5d5340e2 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Fri, 10 Mar 2017 13:36:24 -0500 Subject: [PATCH 15/25] closes #5510 --- src/controllers/topics.js | 18 ++++++++++++++++++ src/topics/data.js | 4 ++++ src/topics/delete.js | 9 ++++++++- 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/controllers/topics.js b/src/controllers/topics.js index 1d813868ae..5202f3ac2b 100644 --- a/src/controllers/topics.js +++ b/src/controllers/topics.js @@ -146,6 +146,24 @@ topicsController.get = function (req, res, callback) { next(null, data.topicData); }); }, + function (topicData, next) { + if (!topicData.deleterUid) { + return next(null, topicData); + } + + user.getUserFields(topicData.deleterUid, ['username', 'userslug'], function(err, deleter) { + if (err) { + return next(err); + } + + topicData.deleter = deleter; + topicData.deleter.timestampISO = topicData.deletedTimestampISO + delete topicData.deleterUid; + delete topicData.deletedTimestampISO; + + next(null, topicData); + }); + }, function (topicData, next) { function findPost(index) { for (var i = 0; i < topicData.posts.length; i += 1) { diff --git a/src/topics/data.js b/src/topics/data.js index cf1df2787c..17e060f679 100644 --- a/src/topics/data.js +++ b/src/topics/data.js @@ -86,4 +86,8 @@ module.exports = function (Topics) { Topics.deleteTopicField = function (tid, field, callback) { db.deleteObjectField('topic:' + tid, field, callback); }; + + Topics.deleteTopicFields = function (tid, fields, callback) { + db.deleteObjectFields('topic:' + tid, fields, callback); + }; }; diff --git a/src/topics/delete.js b/src/topics/delete.js index 7fdd0bc1a7..b23cfbd513 100644 --- a/src/topics/delete.js +++ b/src/topics/delete.js @@ -18,7 +18,11 @@ module.exports = function (Topics) { async.parallel([ function (next) { - Topics.setTopicField(tid, 'deleted', 1, next); + Topics.setTopicFields(tid, { + deleted: 1, + deleterUid: uid, + deletedTimestampISO: (new Date()).toISOString() + }, next); }, function (next) { db.sortedSetsRemove(['topics:recent', 'topics:posts', 'topics:views'], tid, next); @@ -47,6 +51,9 @@ module.exports = function (Topics) { function (next) { Topics.setTopicField(tid, 'deleted', 0, next); }, + function (next) { + Topics.deleteTopicFields(tid, ['deleterUid', 'deletedTimestampISO'], next); + }, function (next) { Topics.updateRecent(tid, topicData.lastposttime, next); }, From 5aa45e9181a00856fbf6c2e6bcfb8745fd787ceb Mon Sep 17 00:00:00 2001 From: psychobunny Date: Fri, 10 Mar 2017 13:37:02 -0500 Subject: [PATCH 16/25] up persona --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ee0cc57714..09e1bfa9dc 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,7 @@ "nodebb-plugin-spam-be-gone": "0.4.13", "nodebb-rewards-essentials": "0.0.9", "nodebb-theme-lavender": "3.0.15", - "nodebb-theme-persona": "4.2.4", + "nodebb-theme-persona": "4.2.5", "nodebb-theme-vanilla": "5.2.0", "nodebb-widget-essentials": "2.0.13", "nodemailer": "2.6.4", From f2eb4b808386d61c53b7bdb5cad8925b5fe9414b Mon Sep 17 00:00:00 2001 From: psychobunny Date: Fri, 10 Mar 2017 14:03:07 -0500 Subject: [PATCH 17/25] closes #5439 --- public/language/en-GB/admin/settings/general.json | 3 ++- public/src/ajaxify.js | 9 +++++++-- src/controllers/api.js | 4 ++++ src/views/admin/settings/general.tpl | 5 +++++ 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/public/language/en-GB/admin/settings/general.json b/public/language/en-GB/admin/settings/general.json index c26740ee4f..8db88bb958 100644 --- a/public/language/en-GB/admin/settings/general.json +++ b/public/language/en-GB/admin/settings/general.json @@ -26,5 +26,6 @@ "touch-icon.upload": "Upload", "touch-icon.help": "Recommended size and format: 192x192, PNG format only. If no touch icon is specified, NodeBB will fall back to using the favicon.", "outgoing-links": "Outgoing Links", - "outgoing-links.warning-page": "Use Outgoing Links Warning Page" + "outgoing-links.warning-page": "Use Outgoing Links Warning Page", + "outgoing-links.whitelist": "Domains to whitelist for bypassing the warning page" } \ No newline at end of file diff --git a/public/src/ajaxify.js b/public/src/ajaxify.js index 913dbb6fd6..539de6c47b 100644 --- a/public/src/ajaxify.js +++ b/public/src/ajaxify.js @@ -366,8 +366,13 @@ $(document).ready(function () { window.open(this.href, '_blank'); e.preventDefault(); } else if (config.useOutgoingLinksPage) { - ajaxify.go('outgoing?url=' + encodeURIComponent(this.href)); - e.preventDefault(); + var safeUrls = config.outgoingLinksWhitelist.trim().split(/[\s,]+/g); + var href = this.href; + + if (!safeUrls.some(function(url) { return href.indexOf(url) !== -1; } )) { + ajaxify.go('outgoing?url=' + encodeURIComponent(href)); + e.preventDefault(); + } } } } diff --git a/src/controllers/api.js b/src/controllers/api.js index 5ddbd0731b..f7158481e7 100644 --- a/src/controllers/api.js +++ b/src/controllers/api.js @@ -64,6 +64,10 @@ apiController.getConfig = function (req, res, next) { config.bootswatchSkin = meta.config.bootswatchSkin || 'noskin'; config.defaultBootswatchSkin = meta.config.bootswatchSkin || 'noskin'; + if (config.useOutgoingLinksPage) { + config.outgoingLinksWhitelist = meta.config['outgoingLinks:whitelist']; + } + var timeagoCutoff = meta.config.timeagoCutoff === undefined ? 30 : meta.config.timeagoCutoff; config.timeagoCutoff = timeagoCutoff !== '' ? Math.max(0, parseInt(timeagoCutoff, 10)) : timeagoCutoff; diff --git a/src/views/admin/settings/general.tpl b/src/views/admin/settings/general.tpl index 990509e41f..c78691037e 100644 --- a/src/views/admin/settings/general.tpl +++ b/src/views/admin/settings/general.tpl @@ -123,6 +123,11 @@ [[admin/settings/general:outgoing-links.warning-page]] + +
+ + +
From 447b7b02ca625ee0c179b2d12dc5ae792fc33911 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Fri, 10 Mar 2017 14:12:17 -0500 Subject: [PATCH 18/25] use tagsinput for #5439 instead --- public/src/admin/settings/general.js | 5 +++++ src/views/admin/settings/general.tpl | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/public/src/admin/settings/general.js b/public/src/admin/settings/general.js index af66449e02..0f01aa6371 100644 --- a/public/src/admin/settings/general.js +++ b/public/src/admin/settings/general.js @@ -17,6 +17,11 @@ define('admin/settings/general', ['admin/settings'], function () { $('button[data-action="removeOgImage"]').on('click', function () { $('input[data-field="removeOgImage"]').val(''); }); + + $('[data-field-type="tagsinput"]').tagsinput({ + confirmKeys: [13, 44], + trimValue: true, + }); }; return Module; diff --git a/src/views/admin/settings/general.tpl b/src/views/admin/settings/general.tpl index c78691037e..2afbd532b9 100644 --- a/src/views/admin/settings/general.tpl +++ b/src/views/admin/settings/general.tpl @@ -125,8 +125,8 @@
- - +
+
From 3b41c40b938d9558e6f235631fd614e77df5ac05 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Fri, 10 Mar 2017 22:22:08 +0300 Subject: [PATCH 19/25] refactor deleter code to use unixtimestamp --- src/controllers/topics.js | 18 ------------------ src/topics.js | 10 ++++++++++ src/topics/delete.js | 4 ++-- 3 files changed, 12 insertions(+), 20 deletions(-) diff --git a/src/controllers/topics.js b/src/controllers/topics.js index 5202f3ac2b..1d813868ae 100644 --- a/src/controllers/topics.js +++ b/src/controllers/topics.js @@ -146,24 +146,6 @@ topicsController.get = function (req, res, callback) { next(null, data.topicData); }); }, - function (topicData, next) { - if (!topicData.deleterUid) { - return next(null, topicData); - } - - user.getUserFields(topicData.deleterUid, ['username', 'userslug'], function(err, deleter) { - if (err) { - return next(err); - } - - topicData.deleter = deleter; - topicData.deleter.timestampISO = topicData.deletedTimestampISO - delete topicData.deleterUid; - delete topicData.deletedTimestampISO; - - next(null, topicData); - }); - }, function (topicData, next) { function findPost(index) { for (var i = 0; i < topicData.posts.length; i += 1) { diff --git a/src/topics.js b/src/topics.js index 77cea4ec98..164200016d 100644 --- a/src/topics.js +++ b/src/topics.js @@ -180,6 +180,7 @@ var social = require('./social'); isIgnoring: async.apply(Topics.isIgnoring, [topicData.tid], uid), bookmark: async.apply(Topics.getUserBookmark, topicData.tid, uid), postSharing: async.apply(social.getActivePostSharing), + deleter: async.apply(getDeleter, topicData), related: function (next) { async.waterfall([ function (next) { @@ -202,6 +203,8 @@ var social = require('./social'); topicData.isIgnoring = results.isIgnoring[0]; topicData.bookmark = results.bookmark; topicData.postSharing = results.postSharing; + topicData.deleter = results.deleter; + topicData.deletedTimestampISO = utils.toISOString(topicData.deletedTimestamp); topicData.related = results.related || []; topicData.unreplied = parseInt(topicData.postcount, 10) === 1; @@ -258,6 +261,13 @@ var social = require('./social'); ], callback); } + function getDeleter(topicData, callback) { + if (!topicData.deleterUid) { + return setImmediate(callback, null, null); + } + user.getUserFields(topicData.deleterUid, ['username', 'userslug', 'picture'], callback); + } + Topics.getMainPost = function (tid, uid, callback) { Topics.getMainPosts([tid], uid, function (err, mainPosts) { callback(err, Array.isArray(mainPosts) && mainPosts.length ? mainPosts[0] : null); diff --git a/src/topics/delete.js b/src/topics/delete.js index b23cfbd513..30992dd94c 100644 --- a/src/topics/delete.js +++ b/src/topics/delete.js @@ -21,7 +21,7 @@ module.exports = function (Topics) { Topics.setTopicFields(tid, { deleted: 1, deleterUid: uid, - deletedTimestampISO: (new Date()).toISOString() + deletedTimestamp: Date.now(), }, next); }, function (next) { @@ -52,7 +52,7 @@ module.exports = function (Topics) { Topics.setTopicField(tid, 'deleted', 0, next); }, function (next) { - Topics.deleteTopicFields(tid, ['deleterUid', 'deletedTimestampISO'], next); + Topics.deleteTopicFields(tid, ['deleterUid', 'deletedTimestamp'], next); }, function (next) { Topics.updateRecent(tid, topicData.lastposttime, next); From debe34b96c15708caef08c4b319ad2beac155675 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Fri, 10 Mar 2017 14:25:31 -0500 Subject: [PATCH 20/25] better styling for tagsinput in ACP and added it to general -> keywords --- public/less/admin/settings.less | 16 ++++++++++++++++ src/views/admin/settings/general.tpl | 4 ++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/public/less/admin/settings.less b/public/less/admin/settings.less index 84572def68..decfc8b7ed 100644 --- a/public/less/admin/settings.less +++ b/public/less/admin/settings.less @@ -16,4 +16,20 @@ [data-action="upload"][type="text"] { width: 95%; } + + .bootstrap-tagsinput { + width: 100%; + border: 0; + box-shadow: none; + padding-left: 0; + + input { + width: 100%; + margin-left: 1px; + margin-top: 9px; + border-bottom: 1px dotted #ccc !important; + padding-bottom: 5px; + padding-left: 0; + } + } } \ No newline at end of file diff --git a/src/views/admin/settings/general.tpl b/src/views/admin/settings/general.tpl index 2afbd532b9..9a96706394 100644 --- a/src/views/admin/settings/general.tpl +++ b/src/views/admin/settings/general.tpl @@ -31,8 +31,8 @@
- -
+
+
From bb146e049c9e54eacd69a16469b89aab837707d2 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Fri, 10 Mar 2017 22:36:04 +0300 Subject: [PATCH 21/25] fix lint --- 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 539de6c47b..93eb4791b0 100644 --- a/public/src/ajaxify.js +++ b/public/src/ajaxify.js @@ -369,7 +369,7 @@ $(document).ready(function () { var safeUrls = config.outgoingLinksWhitelist.trim().split(/[\s,]+/g); var href = this.href; - if (!safeUrls.some(function(url) { return href.indexOf(url) !== -1; } )) { + if (!safeUrls.some(function (url) { return href.indexOf(url) !== -1; })) { ajaxify.go('outgoing?url=' + encodeURIComponent(href)); e.preventDefault(); } From 62f445ad7f95b3bf76e8dc2a8bc0a2d6b23d775b Mon Sep 17 00:00:00 2001 From: psychobunny Date: Fri, 10 Mar 2017 14:33:47 -0500 Subject: [PATCH 22/25] ACP: added tagsinput to other fields that are "comma separated" --- public/src/admin/settings.js | 8 ++++++++ public/src/admin/settings/general.js | 5 ----- src/views/admin/settings/group.tpl | 2 +- src/views/admin/settings/uploads.tpl | 4 ++-- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/public/src/admin/settings.js b/public/src/admin/settings.js index 041de4a40f..3c2575734b 100644 --- a/public/src/admin/settings.js +++ b/public/src/admin/settings.js @@ -102,6 +102,7 @@ define('admin/settings', ['uploader'], function (uploader) { }); handleUploads(); + setupTagsInput(); $('#clear-sitemap-cache').off('click').on('click', function () { socket.emit('admin.settings.clearSitemapCache', function () { @@ -142,6 +143,13 @@ define('admin/settings', ['uploader'], function (uploader) { }); } + function setupTagsInput() { + $('[data-field-type="tagsinput"]').tagsinput({ + confirmKeys: [13, 44], + trimValue: true, + }); + } + Settings.remove = function (key) { socket.emit('admin.config.remove', key); }; diff --git a/public/src/admin/settings/general.js b/public/src/admin/settings/general.js index 0f01aa6371..af66449e02 100644 --- a/public/src/admin/settings/general.js +++ b/public/src/admin/settings/general.js @@ -17,11 +17,6 @@ define('admin/settings/general', ['admin/settings'], function () { $('button[data-action="removeOgImage"]').on('click', function () { $('input[data-field="removeOgImage"]').val(''); }); - - $('[data-field-type="tagsinput"]').tagsinput({ - confirmKeys: [13, 44], - trimValue: true, - }); }; return Module; diff --git a/src/views/admin/settings/group.tpl b/src/views/admin/settings/group.tpl index 1c0b660361..fd696cb5ad 100644 --- a/src/views/admin/settings/group.tpl +++ b/src/views/admin/settings/group.tpl @@ -43,7 +43,7 @@

[[admin/settings/group:default-cover-help]]

-
+
diff --git a/src/views/admin/settings/uploads.tpl b/src/views/admin/settings/uploads.tpl index 6c9b59db80..feff2dbff3 100644 --- a/src/views/admin/settings/uploads.tpl +++ b/src/views/admin/settings/uploads.tpl @@ -50,7 +50,7 @@
- +

[[admin/settings/uploads:allowed-file-extensions-help]]

@@ -131,7 +131,7 @@

[[admin/settings/uploads:default-covers-help]]

- +
From 5ca9e5e14cb0d29c1bf69934d2492c040ba33373 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Fri, 10 Mar 2017 14:36:30 -0500 Subject: [PATCH 23/25] ACP: distinguish from regular text --- public/less/admin/admin.less | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/public/less/admin/admin.less b/public/less/admin/admin.less index 23f3bead8c..bcf6ddca58 100644 --- a/public/less/admin/admin.less +++ b/public/less/admin/admin.less @@ -272,4 +272,8 @@ body { border: 1px dashed @brand-success; background: lighten(@brand-success, 10%); opacity: 0.5; +} + +form small { + color: @gray-light; } \ No newline at end of file From 286d0ab203d07f2faab8ed97eaf4f6e28143cd9a Mon Sep 17 00:00:00 2001 From: psychobunny Date: Fri, 10 Mar 2017 14:40:10 -0500 Subject: [PATCH 24/25] prevent tagsinput initialization from flagging as unsaved --- public/src/admin/settings.js | 1 + 1 file changed, 1 insertion(+) diff --git a/public/src/admin/settings.js b/public/src/admin/settings.js index 3c2575734b..5495e3b71b 100644 --- a/public/src/admin/settings.js +++ b/public/src/admin/settings.js @@ -148,6 +148,7 @@ define('admin/settings', ['uploader'], function (uploader) { confirmKeys: [13, 44], trimValue: true, }); + app.flags._unsaved = false; } Settings.remove = function (key) { From 9dc54f801ebbf42733808d02eed1e52f414c126a Mon Sep 17 00:00:00 2001 From: psychobunny Date: Fri, 10 Mar 2017 14:55:52 -0500 Subject: [PATCH 25/25] up persona --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 09e1bfa9dc..395b439cfb 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,7 @@ "nodebb-plugin-spam-be-gone": "0.4.13", "nodebb-rewards-essentials": "0.0.9", "nodebb-theme-lavender": "3.0.15", - "nodebb-theme-persona": "4.2.5", + "nodebb-theme-persona": "4.2.6", "nodebb-theme-vanilla": "5.2.0", "nodebb-widget-essentials": "2.0.13", "nodemailer": "2.6.4",