From 2c2a28c5b6d4bd2f1585543a96951b6360a55438 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Fri, 8 Sep 2017 11:37:51 -0400 Subject: [PATCH 01/20] closes #5919 --- src/meta/blacklist.js | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/meta/blacklist.js b/src/meta/blacklist.js index 4a1eeeb71f..6d408d538b 100644 --- a/src/meta/blacklist.js +++ b/src/meta/blacklist.js @@ -20,7 +20,7 @@ Blacklist.load = function (callback) { Blacklist.get, Blacklist.validate, function (rules, next) { - winston.verbose('[meta/blacklist] Loading ' + rules.valid.length + ' blacklist rules'); + winston.verbose('[meta/blacklist] Loading ' + rules.valid.length + ' blacklist rule(s)' + (rules.duplicateCount > 0 ? ', ignored ' + rules.duplicateCount + ' duplicate(s)' : '')); if (rules.invalid.length) { winston.warn('[meta/blacklist] ' + rules.invalid.length + ' invalid blacklist rule(s) were ignored.'); } @@ -44,8 +44,8 @@ Blacklist.save = function (rules, callback) { db.set('ip-blacklist-rules', rules, next); }, function (next) { - Blacklist.load(next); pubsub.publish('blacklist:reload'); + setImmediate(next); }, ], callback); }; @@ -101,6 +101,7 @@ Blacklist.validate = function (rules, callback) { var ipv6 = []; var cidr = []; var invalid = []; + var duplicateCount = 0; var inlineCommentMatch = /#.*$/; var whitelist = ['127.0.0.1', '::1', '::ffff:0:127.0.0.1']; @@ -112,6 +113,16 @@ Blacklist.validate = function (rules, callback) { return rule.length && !rule.startsWith('#') ? rule : null; }).filter(Boolean); + // Filter out duplicates + rules = rules.filter(function (rule, index) { + const pass = rules.indexOf(rule) === index; + if (!pass) { + duplicateCount += 1; + } + + return pass; + }); + // Filter out invalid rules rules = rules.filter(function (rule) { var addr; @@ -157,6 +168,7 @@ Blacklist.validate = function (rules, callback) { cidr: cidr, valid: rules, invalid: invalid, + duplicateCount: duplicateCount, }); }; From a6b993ef6cd73b2cb903caeb15190f2ae47f6c70 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Fri, 8 Sep 2017 11:55:37 -0400 Subject: [PATCH 02/20] updating 500-embed to load after page is fully loaded, #5733 --- src/views/500-embed.tpl | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/views/500-embed.tpl b/src/views/500-embed.tpl index b1045d431f..474e99a973 100644 --- a/src/views/500-embed.tpl +++ b/src/views/500-embed.tpl @@ -1,12 +1,14 @@ \ No newline at end of file From b56d6f8b5008f3b516c680525d3261aecab7d794 Mon Sep 17 00:00:00 2001 From: Baris Usakli Date: Fri, 8 Sep 2017 14:39:50 -0400 Subject: [PATCH 03/20] make call to db in /ping and /sping --- src/webserver.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/webserver.js b/src/webserver.js index 26f4820c15..7b5198378f 100644 --- a/src/webserver.js +++ b/src/webserver.js @@ -180,8 +180,15 @@ function setupExpressApp(app, callback) { setupAutoLocale(app, callback); } -function ping(req, res) { - res.status(200).send(req.path === '/sping' ? 'healthy' : '200'); +function ping(req, res, next) { + async.waterfall([ + function (next) { + db.getObject('config', next); + }, + function () { + res.status(200).send(req.path === '/sping' ? 'healthy' : '200'); + }, + ], next); } function setupFavicon(app) { From 9f4e92fa13a55fd89686282fa5da387a5c8578ce Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Tue, 12 Sep 2017 13:46:51 -0400 Subject: [PATCH 04/20] closes #5925 --- src/controllers/errors.js | 65 ++++++++++++++++++++++++++------------- 1 file changed, 43 insertions(+), 22 deletions(-) diff --git a/src/controllers/errors.js b/src/controllers/errors.js index 177bcaa769..a0d8faad21 100644 --- a/src/controllers/errors.js +++ b/src/controllers/errors.js @@ -3,6 +3,7 @@ var nconf = require('nconf'); var winston = require('winston'); var validator = require('validator'); +var plugins = require('../plugins'); exports.handleURIErrors = function (err, req, res, next) { // Handle cases where malformed URIs are passed in @@ -35,30 +36,50 @@ exports.handleURIErrors = function (err, req, res, next) { // this needs to have four arguments or express treats it as `(req, res, next)` // don't remove `next`! exports.handleErrors = function (err, req, res, next) { // eslint-disable-line no-unused-vars - switch (err.code) { - case 'EBADCSRFTOKEN': - winston.error(req.path + '\n', err.message); - return res.sendStatus(403); - case 'blacklisted-ip': - return res.status(403).type('text/plain').send(err.message); - } + var cases = { + EBADCSRFTOKEN: function () { + winston.error(req.path + '\n', err.message); + res.sendStatus(403); + }, + 'blacklisted-ip': function () { + res.status(403).type('text/plain').send(err.message); + }, + }; + var defaultHandler = function () { + // Display NodeBB error page + var status = parseInt(err.status, 10); + if ((status === 302 || status === 308) && err.path) { + return res.locals.isAPI ? res.set('X-Redirect', err.path).status(200).json(err.path) : res.redirect(err.path); + } - var status = parseInt(err.status, 10); - if ((status === 302 || status === 308) && err.path) { - return res.locals.isAPI ? res.set('X-Redirect', err.path).status(200).json(err.path) : res.redirect(err.path); - } + winston.error(req.path + '\n', err.stack); - winston.error(req.path + '\n', err.stack); + res.status(status || 500); - res.status(status || 500); + var path = String(req.path || ''); + if (res.locals.isAPI) { + res.json({ path: validator.escape(path), error: err.message }); + } else { + var middleware = require('../middleware'); + middleware.buildHeader(req, res, function () { + res.render('500', { path: validator.escape(path), error: validator.escape(String(err.message)) }); + }); + } + }; - var path = String(req.path || ''); - if (res.locals.isAPI) { - res.json({ path: validator.escape(path), error: err.message }); - } else { - var middleware = require('../middleware'); - middleware.buildHeader(req, res, function () { - res.render('500', { path: validator.escape(path), error: validator.escape(String(err.message)) }); - }); - } + plugins.fireHook('filter:error.handle', { + cases: cases, + }, function (_err, data) { + if (_err) { + // Assume defaults + winston.warn('[errors/handle] Unable to retrieve plugin handlers for errors: ' + _err.message); + data.cases = cases; + } + + if (data.cases.hasOwnProperty(err.code)) { + data.cases[err.code](err, res, res, defaultHandler); + } else { + defaultHandler(); + } + }); }; From 8b0e6611d954ffac554577b0ebe2021a8badcaba Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Tue, 12 Sep 2017 18:55:47 -0400 Subject: [PATCH 05/20] fixed incorrect parameter passed into hook --- src/controllers/errors.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controllers/errors.js b/src/controllers/errors.js index a0d8faad21..96bfda203c 100644 --- a/src/controllers/errors.js +++ b/src/controllers/errors.js @@ -77,7 +77,7 @@ exports.handleErrors = function (err, req, res, next) { // eslint-disable-line n } if (data.cases.hasOwnProperty(err.code)) { - data.cases[err.code](err, res, res, defaultHandler); + data.cases[err.code](err, req, res, defaultHandler); } else { defaultHandler(); } From 211482bbc0f5218d0d96657b9da3a1a42e8676b1 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Wed, 13 Sep 2017 12:09:31 -0400 Subject: [PATCH 06/20] fixes #5927 --- public/src/app.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/public/src/app.js b/public/src/app.js index 913360c615..d6acad4554 100644 --- a/public/src/app.js +++ b/public/src/app.js @@ -439,6 +439,9 @@ app.cacheBuster = null; .replace('{pageTitle}', function () { return title; }) .replace('{browserTitle}', function () { return config.browserTitle; }); + // Allow translation strings in title on ajaxify (#5927) + title = title.replace(/[/g, '[').replace(/]/g, ']'); + translator.translate(title, function (translated) { titleObj.titles[0] = translated; app.alternatingTitle(''); From 514317ab20c625bb703dc26fab05e1d372e6697f Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Wed, 13 Sep 2017 17:06:00 -0400 Subject: [PATCH 07/20] using translator.unescape instead of replaces --- public/src/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/src/app.js b/public/src/app.js index d6acad4554..421cf71943 100644 --- a/public/src/app.js +++ b/public/src/app.js @@ -440,7 +440,7 @@ app.cacheBuster = null; .replace('{browserTitle}', function () { return config.browserTitle; }); // Allow translation strings in title on ajaxify (#5927) - title = title.replace(/[/g, '[').replace(/]/g, ']'); + title = translator.unescape(title); translator.translate(title, function (translated) { titleObj.titles[0] = translated; From dea372a5c56f8dadfd79b4ef7c28768feb1a5586 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Thu, 14 Sep 2017 10:15:05 -0400 Subject: [PATCH 08/20] fixes #5932 --- src/middleware/index.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/middleware/index.js b/src/middleware/index.js index 511ae1ddd4..d7f1ce1a73 100644 --- a/src/middleware/index.js +++ b/src/middleware/index.js @@ -9,6 +9,7 @@ var nconf = require('nconf'); var ensureLoggedIn = require('connect-ensure-login'); var toobusy = require('toobusy-js'); var Benchpress = require('benchpressjs'); +var LRU = require('lru-cache'); var plugins = require('../plugins'); var meta = require('../meta'); @@ -23,6 +24,10 @@ var controllers = { helpers: require('../controllers/helpers'), }; +var delayCache = LRU({ + maxAge: 1000 * 60, +}); + var middleware = module.exports; middleware.applyCSRF = csrf(); @@ -186,6 +191,14 @@ middleware.processTimeagoLocales = function (req, res, next) { middleware.delayLoading = function (req, res, next) { // Introduces an artificial delay during load so that brute force attacks are effectively mitigated + + // Add IP to cache so if too many requests are made, subsequent requests are blocked for a minute + var timesSeen = delayCache.get(req.ip) || 0; + if (timesSeen > 10) { + return res.sendStatus(429); + } + delayCache.set(req.ip, timesSeen += 1); + setTimeout(next, 1000); }; From 1f5d14dda442f9113daa1efe0fc1edcd72b32134 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ch=E1=BA=BF=20Ti=E1=BB=87p=20Ch=C3=A2n=20Khoa?= Date: Fri, 29 Sep 2017 20:27:41 +0700 Subject: [PATCH 09/20] place some code under the right loop (#5945) --- public/src/widgets.js | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/public/src/widgets.js b/public/src/widgets.js index 082b291624..badc55c892 100644 --- a/public/src/widgets.js +++ b/public/src/widgets.js @@ -23,21 +23,21 @@ widgetsAtLocation.forEach(function (widget) { html += widget.html; + }); - if (location === 'footer' && !$('#content [widget-area="footer"]').length) { - $('#content').append($('
')); - } else if (location === 'sidebar' && !$('#content [widget-area="sidebar"]').length) { - if ($('[component="account/cover"]').length) { - $('[component="account/cover"]').nextAll().wrapAll($('
')); - } else if ($('[component="groups/cover"]').length) { - $('[component="groups/cover"]').nextAll().wrapAll($('
')); - } else { - $('#content > *').wrapAll($('
')); - } - } else if (location === 'header' && !$('#content [widget-area="header"]').length) { - $('#content').prepend($('
')); + if (location === 'footer' && !$('#content [widget-area="footer"]').length) { + $('#content').append($('
')); + } else if (location === 'sidebar' && !$('#content [widget-area="sidebar"]').length) { + if ($('[component="account/cover"]').length) { + $('[component="account/cover"]').nextAll().wrapAll($('
')); + } else if ($('[component="groups/cover"]').length) { + $('[component="groups/cover"]').nextAll().wrapAll($('
')); + } else { + $('#content > *').wrapAll($('
')); } - }); + } else if (location === 'header' && !$('#content [widget-area="header"]').length) { + $('#content').prepend($('
')); + } area = $('#content [widget-area="' + location + '"]'); if (html && area.length) { From 47bbe846cbd6eb7a96ace23aef9cbb23fba1411e Mon Sep 17 00:00:00 2001 From: "Misty (Bot)" Date: Mon, 2 Oct 2017 09:24:20 +0000 Subject: [PATCH 10/20] Latest translations and fallbacks --- public/language/th/admin/general/social.json | 6 +- public/language/th/admin/manage/users.json | 160 +++++++++--------- .../th/admin/settings/notifications.json | 6 +- 3 files changed, 86 insertions(+), 86 deletions(-) diff --git a/public/language/th/admin/general/social.json b/public/language/th/admin/general/social.json index 23aedfcfaa..7d6a9a8c83 100644 --- a/public/language/th/admin/general/social.json +++ b/public/language/th/admin/general/social.json @@ -1,5 +1,5 @@ { - "post-sharing": "Post Sharing", - "info-plugins-additional": "Plugins can add additional networks for sharing posts.", - "save-success": "Successfully saved Post Sharing Networks!" + "post-sharing": "การแชร์กระทู้", + "info-plugins-additional": "ส่วนเสริมสามารถเพิ่มการเชือมต่อโซเชียลมิเดียเพื่อแชร์กระทู้", + "save-success": "การบันทึกการโพสแชร์เนื้อหาเสร็จสมบูรณ์!" } \ No newline at end of file diff --git a/public/language/th/admin/manage/users.json b/public/language/th/admin/manage/users.json index f1651a814b..599f817de9 100644 --- a/public/language/th/admin/manage/users.json +++ b/public/language/th/admin/manage/users.json @@ -1,91 +1,91 @@ { - "users": "Users", - "edit": "Edit", - "make-admin": "Make Admin", - "remove-admin": "Remove Admin", - "validate-email": "Validate Email", - "send-validation-email": "Send Validation Email", - "password-reset-email": "Send Password Reset Email", - "ban": "Ban User(s)", - "temp-ban": "Ban User(s) Temporarily", - "unban": "Unban User(s)", - "reset-lockout": "Reset Lockout", - "reset-flags": "Reset Flags", - "delete": "Delete User(s)", - "purge": "Delete User(s) and Content", - "download-csv": "Download CSV", - "invite": "Invite", - "new": "New User", + "users": "ผู้ใช้", + "edit": "แก้ไข", + "make-admin": "ทำให้เป็นแอดมิน", + "remove-admin": "ยกเลิกการเป็นแอดมิน", + "validate-email": "ยืนยันอีเมล", + "send-validation-email": "ส่งอีเมลยืนยัน", + "password-reset-email": "ส่งการล้างค่ารหัสผ่านทางอีเมล", + "ban": "ผู้ใช้งานที่โดนแบน", + "temp-ban": "ผู้ใช้งานที่โดนแบนชั่วคราว", + "unban": "ยกเลิกการแบนผู้ใช้งาน", + "reset-lockout": "ยกเลิกการกักกัน", + "reset-flags": "ยกเลิกการการเฝ้าระวัง", + "delete": "ลบผู้ใช้งาน", + "purge": "ลบผู้ใช้งานและเนื้อหา", + "download-csv": "ดาวน์โหลด CSV", + "invite": "เชิญ", + "new": "ผู้ใช้งานใหม่", - "pills.latest": "Latest Users", - "pills.unvalidated": "Not Validated", - "pills.no-posts": "No Posts", - "pills.top-posters": "Top Posters", - "pills.top-rep": "Most Reputation", - "pills.inactive": "Inactive", - "pills.flagged": "Most Flagged", - "pills.banned": "Banned", - "pills.search": "User Search", + "pills.latest": "ผู้ใช้งานคนล่าสุด", + "pills.unvalidated": "ยังไม่ได้ยืนยัน", + "pills.no-posts": "ไม่มีกระทู้", + "pills.top-posters": "ผู้ที่โพสกระทู้มากที่สุด", + "pills.top-rep": "ชื่อเสียงมากที่สุด", + "pills.inactive": "ไม่มีการใช้งาน", + "pills.flagged": "ได้รับการติดตาม", + "pills.banned": "แบน", + "pills.search": "ค้นหาผู้ใช้งาน", - "search.username": "By User Name", - "search.username-placeholder": "Enter a username to search", - "search.email": "By Email", - "search.email-placeholder": "Enter a email to search", - "search.ip": "By IP Address", - "search.ip-placeholder": "Enter an IP Address to search", - "search.not-found": "User not found!", + "search.username": "โดยชื่อผู้ใช้งาน", + "search.username-placeholder": "ใส่ชื่อผู้ใช้งานเพื่อทำการค้นหา", + "search.email": "โดยอีเมล", + "search.email-placeholder": "ใส่อีเมลเพื่อทำการค้นหา", + "search.ip": "โดย IP แอดเดรส", + "search.ip-placeholder": "ใส่ IP แอดเดรสเพื่อทำการค้นหา", + "search.not-found": "ไม่พบผู้ใช้งาน!", - "inactive.3-months": "3 months", - "inactive.6-months": "6 months", - "inactive.12-months": "12 months", + "inactive.3-months": "สามเดือน", + "inactive.6-months": "หกเดือน", + "inactive.12-months": "สิบสองเดือน", "users.uid": "uid", - "users.username": "username", - "users.email": "email", - "users.postcount": "postcount", - "users.reputation": "reputation", - "users.flags": "flags", - "users.joined": "joined", - "users.last-online": "last online", - "users.banned": "banned", + "users.username": "ชื่อผู้ใช้", + "users.email": "อีเมล", + "users.postcount": "จำนวนกระทู้", + "users.reputation": "ชื่อเสียง", + "users.flags": "ติดตาม", + "users.joined": "เข้าร่วม", + "users.last-online": "ออนไลน์ครั้งสุดท้าย", + "users.banned": "แบน", - "create.username": "User Name", - "create.email": "Email", - "create.email-placeholder": "Email of this user", - "create.password": "Password", - "create.password-confirm": "Confirm Password", + "create.username": "ชื่อผู้ใช้งาน", + "create.email": "อีเมล", + "create.email-placeholder": "อีเมลของผู้ใช้", + "create.password": "รหัสผ่าน", + "create.password-confirm": "ยืนยันรหัสผ่าน", - "temp-ban.length": "Ban Length", - "temp-ban.reason": "Reason (Optional)", - "temp-ban.hours": "Hours", - "temp-ban.days": "Days", - "temp-ban.explanation": "Enter the length of time for the ban. Note that a time of 0 will be a considered a permanent ban.", + "temp-ban.length": "ระยะเวลาการแบน", + "temp-ban.reason": "เหตุผล (ตัวเลือก)", + "temp-ban.hours": "ชั่วโมง", + "temp-ban.days": "วัน", + "temp-ban.explanation": "ระบุระยะเวลาของการแบน ถ้าระยะเวลาเป็น \"0\" คือการแบนถาวร", - "alerts.confirm-ban": "Do you really want to ban this user permanently?", - "alerts.confirm-ban-multi": "Do you really want to ban these users permanently?", - "alerts.ban-success": "User(s) banned!", - "alerts.button-ban-x": "Ban %1 user(s)", - "alerts.unban-success": "User(s) unbanned!", - "alerts.lockout-reset-success": "Lockout(s) reset!", - "alerts.flag-reset-success": "Flags(s) reset!", - "alerts.no-remove-yourself-admin": "You can't remove yourself as Administrator!", - "alerts.make-admin-success": "User(s) are now administrators.", - "alerts.confirm-remove-admin": "Do you really want to remove admins?", - "alerts.remove-admin-success": "User(s) are no longer administrators.", - "alerts.confirm-validate-email": "Do you want to validate email(s) of these user(s)?", - "alerts.validate-email-success": "Emails validated", - "alerts.password-reset-confirm": "Do you want to send password reset email(s) to these user(s)?", - "alerts.confirm-delete": "Warning!
Do you really want to delete user(s)?
This action is not reversable! Only the user account will be deleted, their posts and topics will remain.", - "alerts.delete-success": "User(s) Deleted!", - "alerts.confirm-purge": "Warning!
Do you really want to delete user(s) and their content?
This action is not reversable! All user data and content will be erased!", - "alerts.create": "Create User", - "alerts.button-create": "Create", - "alerts.button-cancel": "Cancel", - "alerts.error-passwords-different": "Passwords must match!", - "alerts.error-x": "Error

%1

", - "alerts.create-success": "User created!", + "alerts.confirm-ban": "คุณต้องการที่จะแบนผู้ใช้คนนี้ ถาวร ?", + "alerts.confirm-ban-multi": "คุณต้องการที่จะแบนผู้ใช้กลุ่มนี้ ถาวร ?", + "alerts.ban-success": "ผู้ใช้งานที่โดนแบน", + "alerts.button-ban-x": "แบน %1 ผู้ใช้งาน", + "alerts.unban-success": "ยกเลิกการแบนผู้ใช้งาน", + "alerts.lockout-reset-success": "ยกเลิกการกักกัน", + "alerts.flag-reset-success": "ยกเลิกการติดตาม", + "alerts.no-remove-yourself-admin": "คุณไม่สามารถที่จะยกเลิกตัวเองจากการเป็นผู้ดูแลระบบ", + "alerts.make-admin-success": "ผู้ใช้งานได้เป็นแอดมิน", + "alerts.confirm-remove-admin": "คุณต้องการที่จะยกเลิกแอดมินเหล่านี้?", + "alerts.remove-admin-success": "ผู้ใช้งานที่ไม่ได้เป็นแอดมิน", + "alerts.confirm-validate-email": "คุณต้องการที่ยืนยันอีเมลของผู้ใช้เหล่านี้หรือไม่?", + "alerts.validate-email-success": "อีเมลที่ได้รับการยืนยัน", + "alerts.password-reset-confirm": "คุณต้องการที่จะส่งอีเมลการล้างค่ารหัสผ่านให้กับผู้ใช้เหล่านี้หรือไม่?", + "alerts.confirm-delete": "ระวัง!
คุณต้องการที่จะลบผู้ใช้งานเหล่านี้หรือไม่?
การกระทำนี้ไม่สามารถย้อนกลับได้! มีเพียงแค่บัญชีที่จะโดนลบ แต่ว่ากระทู้และคอมเมนท์จะยังคงอยู่", + "alerts.delete-success": "ผู้ใช้งานโดนลบ!", + "alerts.confirm-purge": "ระวัง!
คุณต้องการที่จะลบผู้ใช้งานเหล่านี้และเนื้อหาของเขาหรือไม่?
การกระทำนี้ไม่สามรถย้อนกลับได้! บัญชีและเนื้อหาของผู้ใช้เหล่านี้จะโดนลบ!", + "alerts.create": "สร้างผู้ใช้งาน", + "alerts.button-create": "สร้าง", + "alerts.button-cancel": "ยกเลิก", + "alerts.error-passwords-different": "รหัสผ่านจะต้องเหมือนกัน! ", + "alerts.error-x": "ผิดพลาด

%1

", + "alerts.create-success": "ผู้ใช้งานถูกสร้าง!", - "alerts.prompt-email": "Email: ", - "alerts.email-sent-to": "An invitation email has been sent to %1", - "alerts.x-users-found": "%1 user(s) found! Search took %2 ms." + "alerts.prompt-email": "อีเมล: ", + "alerts.email-sent-to": "อีเมลคำเชิญถูกส่งไปที่ %1", + "alerts.x-users-found": "%1 ผู้ใช้งานถูกพบ! การค้นหาใช้เวลา %2 ms." } \ No newline at end of file diff --git a/public/language/th/admin/settings/notifications.json b/public/language/th/admin/settings/notifications.json index 4eff7f341a..e5193fc159 100644 --- a/public/language/th/admin/settings/notifications.json +++ b/public/language/th/admin/settings/notifications.json @@ -1,5 +1,5 @@ { - "notifications": "Notifications", - "welcome-notification": "Welcome Notification", - "welcome-notification-link": "Welcome Notification Link" + "notifications": "การแจ้งเตือน", + "welcome-notification": "การยินดีต้อนรับแจ้งเตือน", + "welcome-notification-link": "ลิงค์การยินดีต้อนรับแจ้งเตือน" } \ No newline at end of file From da9da8190f1ca345b3da89b2ac5d4a9f1db403bb Mon Sep 17 00:00:00 2001 From: Peter Jaszkowiak Date: Sun, 1 Oct 2017 16:19:10 -0600 Subject: [PATCH 11/20] Bump dependencies Bumping eslint & configs meant making some linting fixes For future reference, the `xmlhttprequest-ssl` library must be of equal versioning to the one in `engine.io-client`, otherwise it won't be deduped which causes the socket.io tests to fail --- .eslintrc | 4 ++ package.json | 62 +++++++++++++-------------- public/src/admin/appearance/skins.js | 10 ++--- public/src/admin/appearance/themes.js | 12 +++--- public/src/admin/extend/widgets.js | 3 +- public/src/admin/general/dashboard.js | 3 +- public/src/admin/modules/search.js | 2 +- public/src/client/account/header.js | 3 +- public/src/client/chats/messages.js | 4 +- public/src/client/chats/search.js | 4 +- public/src/client/groups/details.js | 3 +- src/controllers/admin/uploads.js | 2 +- src/file.js | 4 +- src/flags.js | 4 +- src/groups/cover.js | 2 +- src/image.js | 2 +- src/meta/minifier.js | 4 +- src/plugins/hooks.js | 5 +-- src/topics/thumb.js | 2 +- src/user/picture.js | 2 +- test/build.js | 2 +- test/search-admin.js | 44 +++++++++---------- test/socket.io.js | 3 +- test/topics.js | 7 +-- 24 files changed, 96 insertions(+), 97 deletions(-) diff --git a/.eslintrc b/.eslintrc index 4f7d4e2413..ef9f48dedc 100644 --- a/.eslintrc +++ b/.eslintrc @@ -32,6 +32,9 @@ "no-prototype-builtins": "off", "new-cap": "off", "no-plusplus": ["error", { "allowForLoopAfterthoughts": true }], + "object-curly-newline": "off", + "no-restricted-globals": "off", + "function-paren-newline": "off", "import/no-unresolved": "error", // ES6 @@ -42,6 +45,7 @@ "no-var": "off", "object-shorthand": "off", "vars-on-top": "off", + "prefer-destructuring": "off", // TODO "import/no-extraneous-dependencies": "off", diff --git a/package.json b/package.json index 1ffc42720e..0707481f2e 100644 --- a/package.json +++ b/package.json @@ -19,27 +19,27 @@ "dependencies": { "ace-builds": "^1.2.8", "async": "2.5.0", - "autoprefixer": "7.1.3", + "autoprefixer": "7.1.4", "bcryptjs": "2.4.3", - "benchpressjs": "^1.0.3", - "body-parser": "^1.17.2", + "benchpressjs": "^1.1.0", + "body-parser": "^1.18.2", "bootstrap": "^3.3.7", "chart.js": "^2.6.0", "colors": "^1.1.2", - "compression": "^1.7.0", + "compression": "^1.7.1", "connect-ensure-login": "^0.1.1", "connect-flash": "^0.1.1", "connect-mongo": "1.3.2", "connect-multiparty": "^2.0.0", - "connect-redis": "3.3.0", + "connect-redis": "3.3.2", "cookie-parser": "^1.4.3", "cron": "^1.2.1", - "cropperjs": "^0.8.1", + "cropperjs": "^1.0.0", "csurf": "^1.9.0", "daemon": "^1.1.0", - "express": "^4.15.4", - "express-session": "^1.15.5", - "express-useragent": "1.0.7", + "express": "^4.16.1", + "express-session": "^1.15.6", + "express-useragent": "1.0.8", "html-to-text": "3.3.0", "ipaddr.js": "^1.5.2", "jimp": "0.2.28", @@ -49,13 +49,13 @@ "lodash": "^4.17.4", "logrotate-stream": "^0.2.5", "lru-cache": "4.1.1", - "mime": "^1.4.0", + "mime": "^2.0.3", "minimist": "^1.2.0", "mkdirp": "^0.5.1", "mongodb": "2.2.31", - "morgan": "^1.8.2", + "morgan": "^1.9.0", "mousetrap": "^1.6.1", - "nconf": "^0.8.4", + "nconf": "^0.8.5", "nodebb-plugin-composer-default": "6.0.0", "nodebb-plugin-dbsearch": "2.0.6", "nodebb-plugin-emoji-extended": "1.1.1", @@ -70,20 +70,20 @@ "nodebb-theme-slick": "1.1.1", "nodebb-theme-vanilla": "7.0.1", "nodebb-widget-essentials": "3.0.5", - "nodemailer": "4.1.0", - "passport": "^0.3.0", + "nodemailer": "4.1.1", + "passport": "^0.4.0", "passport-local": "1.0.0", - "postcss": "6.0.10", - "postcss-clean": "1.0.3", + "postcss": "6.0.12", + "postcss-clean": "1.1.0", "promise-polyfill": "^6.0.2", "prompt": "^1.0.0", "redis": "2.8.0", - "request": "2.81.0", - "rimraf": "2.6.1", + "request": "2.83.0", + "rimraf": "2.6.2", "rss": "^1.2.2", - "sanitize-html": "^1.14.0", + "sanitize-html": "^1.14.1", "semver": "^5.4.1", - "serve-favicon": "^2.4.3", + "serve-favicon": "^2.4.5", "sitemap": "^1.13.0", "socket.io": "2.0.3", "socket.io-client": "2.0.3", @@ -92,24 +92,24 @@ "spdx-license-list": "^3.0.1", "string": "^3.3.3", "toobusy-js": "^0.5.1", - "uglify-js": "^3.0.28", - "validator": "8.1.0", + "uglify-js": "^3.1.3", + "validator": "9.0.0", "winston": "^2.3.1", "xml": "^1.0.1", "xregexp": "3.2.0", "zxcvbn": "^4.4.2" }, "devDependencies": { - "coveralls": "^2.11.14", - "eslint": "^3.12.0", - "eslint-config-airbnb-base": "^11.1.0", - "eslint-plugin-import": "^2.2.0", + "coveralls": "^3.0.0", + "eslint": "^4.8.0", + "eslint-config-airbnb-base": "^12.0.1", + "eslint-plugin-import": "^2.7.0", "grunt": "^1.0.1", "grunt-contrib-watch": "^1.0.0", - "istanbul": "^0.4.2", - "jsdom": "^11.2.0", - "mocha": "^3.5.0", - "mocha-lcov-reporter": "^1.2.0", + "istanbul": "^0.4.5", + "jsdom": "^11.3.0", + "mocha": "^3.5.3", + "mocha-lcov-reporter": "^1.3.0", "xmlhttprequest": "1.8.0", "xmlhttprequest-ssl": "1.5.3" }, @@ -136,4 +136,4 @@ "url": "https://github.com/barisusakli" } ] -} \ No newline at end of file +} diff --git a/public/src/admin/appearance/skins.js b/public/src/admin/appearance/skins.js index 7ec56349f7..b42f3991a3 100644 --- a/public/src/admin/appearance/skins.js +++ b/public/src/admin/appearance/skins.js @@ -72,8 +72,8 @@ define('admin/appearance/skins', ['translator', 'benchpress'], function (transla if (config['theme:src']) { var skin = config['theme:src'] - .match(/latest\/(\S+)\/bootstrap.min.css/)[1] - .replace(/(^|\s)([a-z])/g, function (m, p1, p2) { return p1 + p2.toUpperCase(); }); + .match(/latest\/(\S+)\/bootstrap.min.css/)[1] + .replace(/(^|\s)([a-z])/g, function (m, p1, p2) { return p1 + p2.toUpperCase(); }); highlightSelectedTheme(skin); } @@ -105,9 +105,9 @@ define('admin/appearance/skins', ['translator', 'benchpress'], function (transla $('[data-theme="' + themeId + '"]') .addClass('selected') .find('[data-action="use"]') - .html(current) - .removeClass('btn-primary') - .addClass('btn-success'); + .html(current) + .removeClass('btn-primary') + .addClass('btn-success'); }); } diff --git a/public/src/admin/appearance/themes.js b/public/src/admin/appearance/themes.js index 64d7a202fd..c0a96831bb 100644 --- a/public/src/admin/appearance/themes.js +++ b/public/src/admin/appearance/themes.js @@ -94,16 +94,16 @@ define('admin/appearance/themes', ['translator', 'benchpress'], function (transl $('[data-theme]') .removeClass('selected') .find('[data-action="use"]') - .html(select) - .removeClass('btn-success') - .addClass('btn-primary'); + .html(select) + .removeClass('btn-success') + .addClass('btn-primary'); $('[data-theme="' + themeId + '"]') .addClass('selected') .find('[data-action="use"]') - .html(current) - .removeClass('btn-primary') - .addClass('btn-success'); + .html(current) + .removeClass('btn-primary') + .addClass('btn-success'); }); } diff --git a/public/src/admin/extend/widgets.js b/public/src/admin/extend/widgets.js index be7bf72e83..f6d02ab420 100644 --- a/public/src/admin/extend/widgets.js +++ b/public/src/admin/extend/widgets.js @@ -148,8 +148,7 @@ define('admin/extend/widgets', ['jqueryui'], function () { .addClass(btn.attr('data-class')); container.attr('data-container-html', container.attr('data-container-html') - .replace(/class="[a-zA-Z0-9-\s]+"/, 'class="' + container[0].className.replace(' pointer ui-draggable', '') + '"') - ); + .replace(/class="[a-zA-Z0-9-\s]+"/, 'class="' + container[0].className.replace(' pointer ui-draggable', '') + '"')); }); } diff --git a/public/src/admin/general/dashboard.js b/public/src/admin/general/dashboard.js index e0c17ef25e..3b448a4de8 100644 --- a/public/src/admin/general/dashboard.js +++ b/public/src/admin/general/dashboard.js @@ -472,8 +472,7 @@ define('admin/general/dashboard', ['semver', 'Chart', 'translator', 'benchpress' var topic = topics[tids[i]]; var label = topic.value === '0' ? topic.title : ' ' + topic.title + ''; - legend.append( - '
  • ' + + legend.append('
  • ' + '
    ' + '' + label + '' + '
  • '); diff --git a/public/src/admin/modules/search.js b/public/src/admin/modules/search.js index 0df7b7b385..2a5798c18a 100644 --- a/public/src/admin/modules/search.js +++ b/public/src/admin/modules/search.js @@ -36,7 +36,7 @@ define('admin/modules/search', ['mousetrap'], function (mousetrap) { '' + title + '
    ' + (!results ? '' : - ('' + + ('' + results + '')) + '
    ' + diff --git a/public/src/client/account/header.js b/public/src/client/account/header.js index e88eda06f0..5c16a45a95 100644 --- a/public/src/client/account/header.js +++ b/public/src/client/account/header.js @@ -73,7 +73,8 @@ define('forum/account/header', [ } function setupCoverPhoto() { - coverPhoto.init(components.get('account/cover'), + coverPhoto.init( + components.get('account/cover'), function (imageData, position, callback) { socket.emit('user.updateCover', { uid: ajaxify.data.uid, diff --git a/public/src/client/chats/messages.js b/public/src/client/chats/messages.js index 8f8caa2a1f..fc4a327021 100644 --- a/public/src/client/chats/messages.js +++ b/public/src/client/chats/messages.js @@ -96,9 +96,7 @@ define('forum/chats/messages', ['components', 'sounds', 'translator', 'benchpres messages.scrollToBottom = function (containerEl) { if (containerEl.length) { - containerEl.scrollTop( - containerEl[0].scrollHeight - containerEl.height() - ); + containerEl.scrollTop(containerEl[0].scrollHeight - containerEl.height()); } }; diff --git a/public/src/client/chats/search.js b/public/src/client/chats/search.js index f9504e78a4..1b76d665d8 100644 --- a/public/src/client/chats/search.js +++ b/public/src/client/chats/search.js @@ -63,8 +63,8 @@ define('forum/chats/search', ['components'], function (components) { } var chatEl = $('
  • ') - .attr('data-uid', userObj.uid) - .appendTo(chatsListEl); + .attr('data-uid', userObj.uid) + .appendTo(chatsListEl); chatEl.append(createUserImage()); return chatEl; diff --git a/public/src/client/groups/details.js b/public/src/client/groups/details.js index e7225bb16c..65534df0aa 100644 --- a/public/src/client/groups/details.js +++ b/public/src/client/groups/details.js @@ -21,7 +21,8 @@ define('forum/groups/details', [ if (ajaxify.data.group.isOwner) { Details.prepareSettings(); - coverPhoto.init(components.get('groups/cover'), + coverPhoto.init( + components.get('groups/cover'), function (imageData, position, callback) { socket.emit('groups.cover.update', { groupName: groupName, diff --git a/src/controllers/admin/uploads.js b/src/controllers/admin/uploads.js index 42cade14cc..dc5bd7ce37 100644 --- a/src/controllers/admin/uploads.js +++ b/src/controllers/admin/uploads.js @@ -89,7 +89,7 @@ uploadsController.uploadLogo = function (req, res, next) { uploadsController.uploadSound = function (req, res, next) { var uploadedFile = req.files.files[0]; - var mimeType = mime.lookup(uploadedFile.name); + var mimeType = mime.getType(uploadedFile.name); if (!/^audio\//.test(mimeType)) { return next(Error('[[error:invalid-data]]')); } diff --git a/src/file.js b/src/file.js index 31806d6252..ec86c624b1 100644 --- a/src/file.js +++ b/src/file.js @@ -45,7 +45,7 @@ file.saveFileToLocal = function (filename, folder, tempPath, callback) { }; file.base64ToLocal = function (imageData, uploadPath, callback) { - var buffer = new Buffer(imageData.slice(imageData.indexOf('base64') + 7), 'base64'); + var buffer = Buffer.from(imageData.slice(imageData.indexOf('base64') + 7), 'base64'); uploadPath = path.join(nconf.get('upload_path'), uploadPath); fs.writeFile(uploadPath, buffer, { @@ -141,7 +141,7 @@ file.linkDirs = function linkDirs(sourceDir, destDir, callback) { file.typeToExtension = function (type) { var extension; if (type) { - extension = '.' + mime.extension(type); + extension = '.' + mime.getExtension(type); } return extension; }; diff --git a/src/flags.js b/src/flags.js index 9e3059d2a4..10635ee435 100644 --- a/src/flags.js +++ b/src/flags.js @@ -240,7 +240,7 @@ Flags.validate = function (payload, callback) { } var minimumReputation = utils.isNumber(meta.config['privileges:flag']) ? parseInt(meta.config['privileges:flag'], 10) : 1; - // Check if reporter meets rep threshold (or can edit the target post, in which case threshold does not apply) + // Check if reporter meets rep threshold (or can edit the target post, in which case threshold does not apply) if (!editable.flag && parseInt(data.reporter.reputation, 10) < minimumReputation) { return callback(new Error('[[error:not-enough-reputation-to-flag]]')); } @@ -256,7 +256,7 @@ Flags.validate = function (payload, callback) { } var minimumReputation = utils.isNumber(meta.config['privileges:flag']) ? parseInt(meta.config['privileges:flag'], 10) : 1; - // Check if reporter meets rep threshold (or can edit the target user, in which case threshold does not apply) + // Check if reporter meets rep threshold (or can edit the target user, in which case threshold does not apply) if (!editable && parseInt(data.reporter.reputation, 10) < minimumReputation) { return callback(new Error('[[error:not-enough-reputation-to-flag]]')); } diff --git a/src/groups/cover.js b/src/groups/cover.js index 66cac228bf..289ee16302 100644 --- a/src/groups/cover.js +++ b/src/groups/cover.js @@ -26,7 +26,7 @@ module.exports = function (Groups) { var tempPath = data.file ? data.file : ''; var url; - var type = data.file ? mime.lookup(data.file) : 'image/png'; + var type = data.file ? mime.getType(data.file) : 'image/png'; async.waterfall([ function (next) { diff --git a/src/image.js b/src/image.js index 4d3be47e6f..fc3ddd5e76 100644 --- a/src/image.js +++ b/src/image.js @@ -141,7 +141,7 @@ image.writeImageDataToTempFile = function (imageData, callback) { var filepath = path.join(os.tmpdir(), filename + extension); - var buffer = new Buffer(imageData.slice(imageData.indexOf('base64') + 7), 'base64'); + var buffer = Buffer.from(imageData.slice(imageData.indexOf('base64') + 7), 'base64'); fs.writeFile(filepath, buffer, { encoding: 'base64', diff --git a/src/meta/minifier.js b/src/meta/minifier.js index a3e40d195a..3b26f99ec5 100644 --- a/src/meta/minifier.js +++ b/src/meta/minifier.js @@ -282,9 +282,9 @@ function buildCSS(data, callback) { processImportFrom: ['local'], }), ] : [autoprefixer]).process(lessOutput.css).then(function (result) { - callback(null, { code: result.css }); + process.nextTick(callback, null, { code: result.css }); }, function (err) { - callback(err); + process.nextTick(callback, err); }); }); } diff --git a/src/plugins/hooks.js b/src/plugins/hooks.js index ba52cd5f40..63e3cfaec1 100644 --- a/src/plugins/hooks.js +++ b/src/plugins/hooks.js @@ -39,8 +39,7 @@ module.exports = function (Plugins) { (Plugins.deprecatedHooks[data.hook] ? 'please use `' + Plugins.deprecatedHooks[data.hook] + '` instead.' : 'there is no alternative.' - ) - ); + )); } else { // handle hook's startsWith, i.e. action:homepage.get var parts = data.hook.split(':'); @@ -61,7 +60,7 @@ module.exports = function (Plugins) { if (memo && memo[prop]) { return memo[prop]; } - // Couldn't find method by path, aborting + // Couldn't find method by path, aborting return null; }, Plugins.libraries[data.id]); diff --git a/src/topics/thumb.js b/src/topics/thumb.js index 92963f70df..cfd13f3fb8 100644 --- a/src/topics/thumb.js +++ b/src/topics/thumb.js @@ -35,7 +35,7 @@ module.exports = function (Topics) { var extension = path.extname(data.thumb); if (!extension) { - extension = '.' + mime.extension(type); + extension = '.' + mime.getExtension(type); } filename = Date.now() + '-topic-thumb' + extension; pathToUpload = path.join(nconf.get('upload_path'), 'files', filename); diff --git a/src/user/picture.js b/src/user/picture.js index 817073163b..820d4b12ce 100644 --- a/src/user/picture.js +++ b/src/user/picture.js @@ -28,7 +28,7 @@ module.exports = function (User) { var uploadSize = parseInt(meta.config.maximumProfileImageSize, 10) || 256; var size = res.headers['content-length']; var type = res.headers['content-type']; - var extension = mime.extension(type); + var extension = mime.getExtension(type); if (['png', 'jpeg', 'jpg', 'gif'].indexOf(extension) === -1) { return callback(new Error('[[error:invalid-image-extension]]')); diff --git a/test/build.js b/test/build.js index 1287165a17..1c346ad621 100644 --- a/test/build.js +++ b/test/build.js @@ -114,7 +114,7 @@ describe('minifier', function () { it('.css.bundle() should minify styles', function (done) { minifier.css.bundle(styles, paths, true, false, function (err, bundle) { assert.ifError(err); - assert.strictEqual(bundle.code, '.help{margin:10px;display:block}.yellow{background:#ff0}.help .blue{background:#00f}'); + assert.strictEqual(bundle.code, '.help{margin:10px}.yellow{background:#ff0}.help{display:block}.help .blue{background:#00f}'); done(); }); }); diff --git a/test/search-admin.js b/test/search-admin.js index f885b2bbf9..3c2620dfc1 100644 --- a/test/search-admin.js +++ b/test/search-admin.js @@ -46,20 +46,20 @@ describe('admin search', function () { describe('sanitize', function () { it('should strip out scripts', function (done) { assert.equal( - search.sanitize('Pellentesque tristique senectus' + - ' habitant morbi'), - 'Pellentesque tristique senectus' + - ' habitant morbi' - ); + search.sanitize('Pellentesque tristique senectus' + + ' habitant morbi'), + 'Pellentesque tristique senectus' + + ' habitant morbi' + ); done(); }); it('should remove all tags', function (done) { assert.equal( - search.sanitize('

    Pellentesque habitant morbi tristique senectus' + - 'Aenean vitae est.Mauris eleifend leo.

    '), - 'Pellentesque habitant morbi tristique senectus' + - 'Aenean vitae est.Mauris eleifend leo.' - ); + search.sanitize('

    Pellentesque habitant morbi tristique senectus' + + 'Aenean vitae est.Mauris eleifend leo.

    '), + 'Pellentesque habitant morbi tristique senectus' + + 'Aenean vitae est.Mauris eleifend leo.' + ); done(); }); }); @@ -67,24 +67,20 @@ describe('admin search', function () { describe('simplify', function () { it('should remove all mustaches', function (done) { assert.equal( - search.simplify( - 'Pellentesque tristique {{senectus}}habitant morbi' + - 'liquam tincidunt {mauris.eu}risus' - ), - 'Pellentesque tristique habitant morbi' + - 'liquam tincidunt risus' - ); + search.simplify('Pellentesque tristique {{senectus}}habitant morbi' + + 'liquam tincidunt {mauris.eu}risus'), + 'Pellentesque tristique habitant morbi' + + 'liquam tincidunt risus' + ); done(); }); it('should collapse all whitespace', function (done) { assert.equal( - search.simplify( - 'Pellentesque tristique habitant morbi' + - ' \n\n liquam tincidunt mauris eu risus.' - ), - 'Pellentesque tristique habitant morbi' + - '\nliquam tincidunt mauris eu risus.' - ); + search.simplify('Pellentesque tristique habitant morbi' + + ' \n\n liquam tincidunt mauris eu risus.'), + 'Pellentesque tristique habitant morbi' + + '\nliquam tincidunt mauris eu risus.' + ); done(); }); }); diff --git a/test/socket.io.js b/test/socket.io.js index 76f7ae6a72..eb7489ef8a 100644 --- a/test/socket.io.js +++ b/test/socket.io.js @@ -72,7 +72,8 @@ describe('socket.io', function () { helpers.connectSocketIO(res, function (err, _io) { io = _io; assert.ifError(err); - done(err); + + done(); }); }); }); diff --git a/test/topics.js b/test/topics.js index 0592b9d030..f8c1ee5d16 100644 --- a/test/topics.js +++ b/test/topics.js @@ -654,8 +654,8 @@ describe('Topic\'s', function () { function (next) { topicPids = replies.map(function (reply) { return reply.pid; }); socketTopics.bookmark({ uid: topic.userId }, { tid: newTopic.tid, index: originalBookmark }, next); - }], - done); + }, + ], done); }); it('should fail with invalid data', function (done) { @@ -711,7 +711,8 @@ describe('Topic\'s', function () { 'Fork test, no bookmark update', topicPids.slice(1, 3), newTopic.tid, - next); + next + ); }, function (forkedTopicData, next) { topics.getUserBookmark(newTopic.tid, topic.userId, next); From b70f3285209dc0db2d8cf46604bc9f3c9a92a286 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Mon, 2 Oct 2017 19:27:42 -0400 Subject: [PATCH 12/20] closes #5948 --- src/meta/blacklist.js | 7 +++++-- test/blacklist.js | 5 +++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/meta/blacklist.js b/src/meta/blacklist.js index 20f0e441ff..31af5f9eee 100644 --- a/src/meta/blacklist.js +++ b/src/meta/blacklist.js @@ -71,8 +71,11 @@ Blacklist.test = function (clientIp, callback) { Blacklist._rules.ipv4.indexOf(clientIp) === -1 && // not explicitly specified in ipv4 list Blacklist._rules.ipv6.indexOf(clientIp) === -1 && // not explicitly specified in ipv6 list !Blacklist._rules.cidr.some(function (subnet) { - return addr.match(ipaddr.parseCIDR(subnet)); - // return ip.cidrSubnet(subnet).contains(clientIp); + var cidr = ipaddr.parseCIDR(subnet); + if (addr.kind() !== cidr[0].kind()) { + return false; + } + return addr.match(cidr); }) // not in a blacklisted IPv4 or IPv6 cidr range ) { plugins.fireHook('filter:blacklist.test', { // To return test failure, pass back an error in callback diff --git a/test/blacklist.js b/test/blacklist.js index d003739d8f..763c5364f7 100644 --- a/test/blacklist.js +++ b/test/blacklist.js @@ -72,4 +72,9 @@ describe('blacklist', function () { assert(blacklist.test('1.1.1.1')); done(); }); + + it('should pass ip test and not crash with ipv6 address', function (done) { + assert(!blacklist.test('2001:db8:85a3:0:0:8a2e:370:7334')); + done(); + }); }); From 2086a64a5eda4d67ad69e0acc78611c0d6ca7fb2 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Tue, 3 Oct 2017 09:40:52 -0400 Subject: [PATCH 13/20] fixes #5947 --- src/upgrades/1.6.0/generate-email-logo.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/upgrades/1.6.0/generate-email-logo.js b/src/upgrades/1.6.0/generate-email-logo.js index 2f713f675f..0e95c3b384 100644 --- a/src/upgrades/1.6.0/generate-email-logo.js +++ b/src/upgrades/1.6.0/generate-email-logo.js @@ -26,7 +26,7 @@ module.exports = { } fs.access(sourcePath, function (err) { - if (err) { + if (err || path.extname(sourcePath) === '.svg') { skip = true; return setImmediate(next); } @@ -46,6 +46,7 @@ module.exports = { meta.configs.setMultiple({ 'brand:logo': path.join(nconf.get('upload_path'), 'system', path.basename(meta.config['brand:logo'])), + 'brand:emailLogo': '/assets/uploads/system/site-logo-x50.png', }, next); }, ], callback); From 1fd160a4e63d3c7372e24ebc35a4ebc0dcf1a15c Mon Sep 17 00:00:00 2001 From: RoiEX <8350879+RoiEXLab@users.noreply.github.com> Date: Thu, 21 Sep 2017 23:55:46 +0200 Subject: [PATCH 14/20] Add Support for Firefox OSD --- public/src/modules/helpers.js | 3 ++- src/controllers/osd.js | 25 +++++++++++++++++++++---- src/meta/tags.js | 1 + 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/public/src/modules/helpers.js b/public/src/modules/helpers.js index 28f853ed60..736926101d 100644 --- a/public/src/modules/helpers.js +++ b/public/src/modules/helpers.js @@ -77,8 +77,9 @@ var type = tag.type ? 'type="' + tag.type + '" ' : ''; var href = tag.href ? 'href="' + tag.href + '" ' : ''; var sizes = tag.sizes ? 'sizes="' + tag.sizes + '" ' : ''; + var title = tag.title ? 'title="' + tag.title + '" ' : ''; - return '\n\t'; + return '\n\t'; } function stringify(obj) { diff --git a/src/controllers/osd.js b/src/controllers/osd.js index c83f7f142c..856d956ef5 100644 --- a/src/controllers/osd.js +++ b/src/controllers/osd.js @@ -8,7 +8,7 @@ var meta = require('../meta'); module.exports.handle = function (req, res, next) { if (plugins.hasListeners('filter:search.query')) { - res.type('application/xml').send(generateXML()); + res.type('application/opensearchdescription+xml').send(generateXML()); } else { next(); } @@ -17,9 +17,21 @@ module.exports.handle = function (req, res, next) { function generateXML() { return xml([{ OpenSearchDescription: [ - { _attr: { xmlns: 'http://a9.com/-/spec/opensearch/1.1/' } }, - { ShortName: String(meta.config.title || meta.config.browserTitle || 'NodeBB') }, - { Description: String(meta.config.description || '') }, + { _attr: { + xmlns: 'http://a9.com/-/spec/opensearch/1.1/', + 'xmlns:moz': 'http://www.mozilla.org/2006/browser/search/', + } }, + { ShortName: trimToLength(String(meta.config.title || meta.config.browserTitle || 'NodeBB'), 16) }, + { Description: trimToLength(String(meta.config.description || ''), 1024) }, + { InputEncoding: 'UTF-8' }, + { Image: [ + { _attr: { + width: '16', + height: '16', + type: 'image/x-icon', + } }, + nconf.get('url') + '/favicon.ico', + ] }, { Url: { _attr: { type: 'text/html', @@ -27,6 +39,11 @@ function generateXML() { template: nconf.get('url') + '/search?term={searchTerms}&in=titlesposts', }, } }, + { 'moz:SearchForm': nconf.get('url') + '/search' }, ], }], { declaration: true, indent: '\t' }); } + +function trimToLength(string, length) { + return string.trim().substring(0, length).trim(); +} diff --git a/src/meta/tags.js b/src/meta/tags.js index c347b18d4e..79cb04cded 100644 --- a/src/meta/tags.js +++ b/src/meta/tags.js @@ -66,6 +66,7 @@ Tags.parse = function (req, data, meta, link, callback) { defaultLinks.push({ rel: 'search', type: 'application/opensearchdescription+xml', + title: validator.escape(String(Meta.config.title || Meta.config.browserTitle || 'NodeBB')), href: nconf.get('relative_path') + '/osd.xml', }); } From 5e4e5231988058d5ec13a30e5cd2ca7cdaa2c01e Mon Sep 17 00:00:00 2001 From: RoiEX Date: Tue, 5 Sep 2017 18:31:01 +0200 Subject: [PATCH 15/20] Make progress bar finer --- public/src/modules/navigator.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/src/modules/navigator.js b/public/src/modules/navigator.js index d8b8cb4fe2..df5621f287 100644 --- a/public/src/modules/navigator.js +++ b/public/src/modules/navigator.js @@ -165,7 +165,7 @@ define('navigator', ['forum/pagination', 'components'], function (pagination, co index = index > count ? count : index; $('.pagination-block .pagination-text').translateHtml('[[global:pagination.out_of, ' + index + ', ' + count + ']]'); - $('.pagination-block .progress-bar').width((index / count * 100) + '%'); + $('.pagination-block .progress-bar').width(($(window).scrollTop() / ($(document).height() - $(window).height()) * 100) + '%'); }; navigator.scrollUp = function () { From ce9a3f20c5a49628fa10aa19e8eee27496c32fb9 Mon Sep 17 00:00:00 2001 From: RoiEX Date: Tue, 5 Sep 2017 22:41:40 +0200 Subject: [PATCH 16/20] Optimize transition --- public/src/modules/navigator.js | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/public/src/modules/navigator.js b/public/src/modules/navigator.js index df5621f287..2f2a79a05a 100644 --- a/public/src/modules/navigator.js +++ b/public/src/modules/navigator.js @@ -4,7 +4,7 @@ define('navigator', ['forum/pagination', 'components'], function (pagination, co var navigator = {}; var index = 1; var count = 0; - var navigatorUpdateTimeoutId = 0; + var navigatorUpdateTimeoutId = undefined; navigator.scrollActive = false; @@ -91,11 +91,12 @@ define('navigator', ['forum/pagination', 'components'], function (pagination, co } navigator.delayedUpdate = function () { - if (navigatorUpdateTimeoutId) { - clearTimeout(navigatorUpdateTimeoutId); - navigatorUpdateTimeoutId = 0; + if (!navigatorUpdateTimeoutId) { + navigatorUpdateTimeoutId = setTimeout(function () { + navigator.update(); + navigatorUpdateTimeoutId = undefined; + }, 100); } - navigatorUpdateTimeoutId = setTimeout(navigator.update, 100); }; navigator.update = function (threshold) { @@ -165,7 +166,9 @@ define('navigator', ['forum/pagination', 'components'], function (pagination, co index = index > count ? count : index; $('.pagination-block .pagination-text').translateHtml('[[global:pagination.out_of, ' + index + ', ' + count + ']]'); - $('.pagination-block .progress-bar').width(($(window).scrollTop() / ($(document).height() - $(window).height()) * 100) + '%'); + var fraction = $(window).scrollTop() / ($(document).height() - $(window).height()); + $('.pagination-block meter').val(fraction); + $('.pagination-block .progress-bar').width((fraction * 100) + '%'); }; navigator.scrollUp = function () { From e1f180ea3ffc969ad76aed39b056529dcdd5d2bf Mon Sep 17 00:00:00 2001 From: RoiEX Date: Tue, 5 Sep 2017 23:10:38 +0200 Subject: [PATCH 17/20] Remove uneccessary undefined declaration --- public/src/modules/navigator.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/src/modules/navigator.js b/public/src/modules/navigator.js index 2f2a79a05a..ac6c06ac88 100644 --- a/public/src/modules/navigator.js +++ b/public/src/modules/navigator.js @@ -4,7 +4,7 @@ define('navigator', ['forum/pagination', 'components'], function (pagination, co var navigator = {}; var index = 1; var count = 0; - var navigatorUpdateTimeoutId = undefined; + var navigatorUpdateTimeoutId; navigator.scrollActive = false; From d0ec7fdaef5afc80022803d3c5004598dde7d875 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Tue, 3 Oct 2017 14:19:29 -0400 Subject: [PATCH 18/20] update themes to support #5733 --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 0707481f2e..766ab87ee0 100644 --- a/package.json +++ b/package.json @@ -65,10 +65,10 @@ "nodebb-plugin-soundpack-default": "1.0.0", "nodebb-plugin-spam-be-gone": "0.5.1", "nodebb-rewards-essentials": "0.0.9", - "nodebb-theme-lavender": "4.0.5", - "nodebb-theme-persona": "6.0.1", + "nodebb-theme-lavender": "4.1.0", + "nodebb-theme-persona": "6.1.0", "nodebb-theme-slick": "1.1.1", - "nodebb-theme-vanilla": "7.0.1", + "nodebb-theme-vanilla": "7.1.0", "nodebb-widget-essentials": "3.0.5", "nodemailer": "4.1.1", "passport": "^0.4.0", From dd5651b859153353b44a25505f3024f77da07ba2 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Tue, 3 Oct 2017 14:29:45 -0400 Subject: [PATCH 19/20] bump composer to test new composer submit behaviour --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 766ab87ee0..91573a77c1 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,7 @@ "morgan": "^1.9.0", "mousetrap": "^1.6.1", "nconf": "^0.8.5", - "nodebb-plugin-composer-default": "6.0.0", + "nodebb-plugin-composer-default": "6.0.1", "nodebb-plugin-dbsearch": "2.0.6", "nodebb-plugin-emoji-extended": "1.1.1", "nodebb-plugin-emoji-one": "1.2.1", From 38900a996452a2f1147e8955d20f9a38697a2e2c Mon Sep 17 00:00:00 2001 From: Dravere Date: Thu, 5 Oct 2017 00:26:44 +0200 Subject: [PATCH 20/20] Smtp emailer issue 5951 (#5954) * Fixed typo at emailer.js line 66 (serice -> service) * When custom SMTP user and password is empty no authentication is attempted * Added options to choose custom smtp connection security * Made custom smtp connection security strings translatable * Changed switch to if-else for custom smtp security option * Fixed emailer.js lint errors * Move custom setting to top of list --- .../language/en-GB/admin/settings/email.json | 4 +++ src/emailer.js | 28 +++++++++++++++---- src/views/admin/settings/email.tpl | 15 +++++++--- 3 files changed, 37 insertions(+), 10 deletions(-) diff --git a/public/language/en-GB/admin/settings/email.json b/public/language/en-GB/admin/settings/email.json index 97696e1f44..50d210103b 100644 --- a/public/language/en-GB/admin/settings/email.json +++ b/public/language/en-GB/admin/settings/email.json @@ -15,6 +15,10 @@ "smtp-transport.gmail-warning2": "For more information about this workaround, please consult this NodeMailer article on the issue. An alternative would be to utilise a third-party emailer plugin such as SendGrid, Mailgun, etc. Browse available plugins here.", "smtp-transport.host": "SMTP Host", "smtp-transport.port": "SMTP Port", + "smtp-transport.security": "Connection security", + "smtp-transport.security-encrypted": "Encrypted", + "smtp-transport.security-starttls": "StartTLS", + "smtp-transport.security-none": "None", "smtp-transport.username": "Username", "smtp-transport.username-help": "For the Gmail service, enter the full email address here, especially if you are using a Google Apps managed domain.", "smtp-transport.password": "Password", diff --git a/src/emailer.js b/src/emailer.js index d82228d712..b1ed617445 100644 --- a/src/emailer.js +++ b/src/emailer.js @@ -56,17 +56,33 @@ Emailer.registerApp = function (expressApp) { // Enable Gmail transport if enabled in ACP if (parseInt(meta.config['email:smtpTransport:enabled'], 10) === 1) { - var smtpOptions = { - auth: { + var smtpOptions = {}; + + if (meta.config['email:smtpTransport:user'] || meta.config['email:smtpTransport:pass']) { + smtpOptions.auth = { user: meta.config['email:smtpTransport:user'], pass: meta.config['email:smtpTransport:pass'], - }, - }; + }; + } - if (meta.config['email:smtpTransport:serice'] === 'nodebb-custom-smtp') { + if (meta.config['email:smtpTransport:service'] === 'nodebb-custom-smtp') { smtpOptions.port = meta.config['email:smtpTransport:port']; smtpOptions.host = meta.config['email:smtpTransport:host']; - smtpOptions.secure = true; + + if (meta.config['email:smtpTransport:security'] === 'NONE') { + smtpOptions.secure = false; + smtpOptions.requireTLS = false; + smtpOptions.ignoreTLS = true; + } else if (meta.config['email:smtpTransport:security'] === 'STARTTLS') { + smtpOptions.secure = false; + smtpOptions.requireTLS = true; + smtpOptions.ignoreTLS = false; + } else { + // meta.config['email:smtpTransport:security'] === 'ENCRYPTED' or undefined + smtpOptions.secure = true; + smtpOptions.requireTLS = true; + smtpOptions.ignoreTLS = false; + } } else { smtpOptions.service = meta.config['email:smtpTransport:service']; } diff --git a/src/views/admin/settings/email.tpl b/src/views/admin/settings/email.tpl index 50a3423ece..7315564f1b 100644 --- a/src/views/admin/settings/email.tpl +++ b/src/views/admin/settings/email.tpl @@ -40,12 +40,12 @@

    [[admin/settings/email:smtp-transport.service-help]] @@ -63,6 +63,13 @@ + + +

    @@ -136,4 +143,4 @@
    - \ No newline at end of file +