diff --git a/install/data/defaults.json b/install/data/defaults.json index 9e08416ce6..3d45ff6565 100644 --- a/install/data/defaults.json +++ b/install/data/defaults.json @@ -38,5 +38,5 @@ "bookmarkThreshold": 5, "topicsPerList": 20, "autoDetectLang": 1, - "privileges:flag": 0 + "min:rep:flag": 0 } diff --git a/install/package.json b/install/package.json index f3538ddbcf..2bbdcedca7 100644 --- a/install/package.json +++ b/install/package.json @@ -69,9 +69,9 @@ "nodebb-plugin-spam-be-gone": "0.5.1", "nodebb-rewards-essentials": "0.0.9", "nodebb-theme-lavender": "5.0.0", - "nodebb-theme-persona": "7.2.11", + "nodebb-theme-persona": "7.2.12", "nodebb-theme-slick": "1.1.2", - "nodebb-theme-vanilla": "8.1.5", + "nodebb-theme-vanilla": "8.1.6", "nodebb-widget-essentials": "4.0.1", "nodemailer": "4.4.1", "passport": "^0.4.0", diff --git a/public/language/en-GB/admin/settings/reputation.json b/public/language/en-GB/admin/settings/reputation.json index f0e59e8db9..c698592cff 100644 --- a/public/language/en-GB/admin/settings/reputation.json +++ b/public/language/en-GB/admin/settings/reputation.json @@ -5,5 +5,8 @@ "votes-are-public": "All Votes Are Public", "thresholds": "Activity Thresholds", "min-rep-downvote": "Minimum reputation to downvote posts", - "min-rep-flag": "Minimum reputation to flag posts" + "min-rep-flag": "Minimum reputation to flag posts", + "min-rep-website": "Minimum reputation to add \"Website\" to user profile", + "min-rep-aboutme": "Minimum reputation to add \"About me\" to user profile", + "min-rep-signature": "Minimum reputation to add \"Signature\" to user profile" } \ No newline at end of file diff --git a/public/language/en-GB/error.json b/public/language/en-GB/error.json index 7700006520..df48972483 100644 --- a/public/language/en-GB/error.json +++ b/public/language/en-GB/error.json @@ -146,6 +146,9 @@ "downvoting-disabled": "Downvoting is disabled", "not-enough-reputation-to-downvote": "You do not have enough reputation to downvote this post", "not-enough-reputation-to-flag": "You do not have enough reputation to flag this post", + "not-enough-reputation-min-rep-website": "You do not have enough reputation to add a website", + "not-enough-reputation-min-rep-aboutme": "You do not have enough reputation to add an about me", + "not-enough-reputation-min-rep-signature": "You do not have enough reputation to add a signature", "already-flagged": "You have already flagged this post", "self-vote": "You cannot vote on your own post", diff --git a/src/controllers/accounts/edit.js b/src/controllers/accounts/edit.js index b5bd4cf3a5..5e40b83ef2 100644 --- a/src/controllers/accounts/edit.js +++ b/src/controllers/accounts/edit.js @@ -28,6 +28,9 @@ editController.get = function (req, res, callback) { userData.maximumProfileImageSize = parseInt(meta.config.maximumProfileImageSize, 10); userData.allowProfileImageUploads = parseInt(meta.config.allowProfileImageUploads, 10) === 1; userData.allowAccountDelete = parseInt(meta.config.allowAccountDelete, 10) === 1; + userData.allowWebsite = !userData.isSelf || parseInt(userData.reputation, 10) >= (parseInt(meta.config['min:rep:website'], 10) || 0); + userData.allowAboutMe = !userData.isSelf || parseInt(userData.reputation, 10) >= (parseInt(meta.config['min:rep:aboutme'], 10) || 0); + userData.allowSignature = !userData.isSelf || parseInt(userData.reputation, 10) >= (parseInt(meta.config['min:rep:signature'], 10) || 0); userData.profileImageDimension = parseInt(meta.config.profileImageDimension, 10) || 200; userData.defaultAvatar = user.getDefaultAvatar(); diff --git a/src/flags.js b/src/flags.js index 4118cf8fb2..f906954318 100644 --- a/src/flags.js +++ b/src/flags.js @@ -241,7 +241,7 @@ Flags.validate = function (payload, callback) { return callback(err); } - var minimumReputation = utils.isNumber(meta.config['privileges:flag']) ? parseInt(meta.config['privileges:flag'], 10) : 0; + var minimumReputation = utils.isNumber(meta.config['min:rep:flag']) ? parseInt(meta.config['min:rep:flag'], 10) : 0; // 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]]')); @@ -257,7 +257,7 @@ Flags.validate = function (payload, callback) { return callback(err); } - var minimumReputation = utils.isNumber(meta.config['privileges:flag']) ? parseInt(meta.config['privileges:flag'], 10) : 0; + var minimumReputation = utils.isNumber(meta.config['min:rep:flag']) ? parseInt(meta.config['min:rep:flag'], 10) : 0; // 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/posts/votes.js b/src/posts/votes.js index 529fcbd0c3..422ca67efa 100644 --- a/src/posts/votes.js +++ b/src/posts/votes.js @@ -179,7 +179,7 @@ module.exports = function (Posts) { return callback(new Error('[[error:self-vote]]')); } - if (command === 'downvote' && parseInt(results.reputation, 10) < parseInt(meta.config['privileges:downvote'], 10)) { + if (command === 'downvote' && parseInt(results.reputation, 10) < parseInt(meta.config['min:rep:downvote'], 10)) { return callback(new Error('[[error:not-enough-reputation-to-downvote]]')); } diff --git a/src/privileges/posts.js b/src/privileges/posts.js index b157fa798b..1741dfa587 100644 --- a/src/privileges/posts.js +++ b/src/privileges/posts.js @@ -200,7 +200,7 @@ module.exports = function (privileges) { }, next); }, function (results, next) { - var minimumReputation = utils.isNumber(meta.config['privileges:flag']) ? parseInt(meta.config['privileges:flag'], 10) : 0; + var minimumReputation = utils.isNumber(meta.config['min:rep:flag']) ? parseInt(meta.config['min:rep:flag'], 10) : 0; var canFlag = results.isAdminOrMod || parseInt(results.userReputation, 10) >= minimumReputation; next(null, { flag: canFlag }); }, diff --git a/src/upgrades/1.8.0/rename_min_reputation_settings.js b/src/upgrades/1.8.0/rename_min_reputation_settings.js new file mode 100644 index 0000000000..1abbce1378 --- /dev/null +++ b/src/upgrades/1.8.0/rename_min_reputation_settings.js @@ -0,0 +1,25 @@ +'use strict'; + +var db = require('../../database'); + +module.exports = { + name: 'Rename privileges:downvote and privileges:flag to min:rep:downvote, min:rep:flag respectively', + timestamp: Date.UTC(2018, 0, 12), + method: function (callback) { + db.getObjectFields('config', ['privileges:downvote', 'privileges:flag'], function (err, config) { + if (err) { + return callback(err); + } + + db.setObject('config', { + 'min:rep:downvote': parseInt(config['privileges:downvote'], 10) || 0, + 'min:rep:flag': parseInt(config['privileges:downvote'], 10) || 0, + }, function (err) { + if (err) { + return callback(err); + } + db.deleteObjectFields('config', ['privileges:downvote', 'privileges:flag'], callback); + }); + }); + }, +}; diff --git a/src/user/profile.js b/src/user/profile.js index ae1e31c475..1af4821f49 100644 --- a/src/user/profile.js +++ b/src/user/profile.js @@ -17,14 +17,6 @@ module.exports = function (User) { var updateUid = data.uid; var oldData; - if (data.aboutme !== undefined && data.aboutme.length > meta.config.maximumAboutMeLength) { - return callback(new Error('[[error:about-me-too-long, ' + meta.config.maximumAboutMeLength + ']]')); - } - - if (data.signature !== undefined && data.signature.length > meta.config.maximumSignatureLength) { - return callback(new Error('[[error:signature-too-long, ' + meta.config.maximumSignatureLength + ']]')); - } - async.waterfall([ function (next) { plugins.fireHook('filter:user.updateProfile', { uid: uid, data: data, fields: fields }, next); @@ -33,13 +25,7 @@ module.exports = function (User) { fields = data.fields; data = data.data; - async.series([ - async.apply(isEmailAvailable, data, updateUid), - async.apply(isUsernameAvailable, data, updateUid), - async.apply(isGroupTitleValid, data), - ], function (err) { - next(err); - }); + validateData(uid, data, next); }, function (next) { User.getUserFields(updateUid, fields, next); @@ -73,6 +59,19 @@ module.exports = function (User) { ], callback); }; + function validateData(callerUid, data, callback) { + async.series([ + async.apply(isEmailAvailable, data, data.uid), + async.apply(isUsernameAvailable, data, data.uid), + async.apply(isGroupTitleValid, data), + async.apply(isWebsiteValid, callerUid, data), + async.apply(isAboutMeValid, callerUid, data), + async.apply(isSignatureValid, callerUid, data), + ], function (err) { + callback(err); + }); + } + function isEmailAvailable(data, uid, callback) { if (!data.email) { return callback(); @@ -141,6 +140,52 @@ module.exports = function (User) { } } + function isWebsiteValid(callerUid, data, callback) { + if (!data.website) { + return setImmediate(callback); + } + checkMinReputation(callerUid, data.uid, 'min:rep:website', callback); + } + + function isAboutMeValid(callerUid, data, callback) { + if (!data.aboutme) { + return setImmediate(callback); + } + if (data.aboutme !== undefined && data.aboutme.length > meta.config.maximumAboutMeLength) { + return callback(new Error('[[error:about-me-too-long, ' + meta.config.maximumAboutMeLength + ']]')); + } + + checkMinReputation(callerUid, data.uid, 'min:rep:aboutme', callback); + } + + function isSignatureValid(callerUid, data, callback) { + if (!data.signature) { + return setImmediate(callback); + } + if (data.signature !== undefined && data.signature.length > meta.config.maximumSignatureLength) { + return callback(new Error('[[error:signature-too-long, ' + meta.config.maximumSignatureLength + ']]')); + } + checkMinReputation(callerUid, data.uid, 'min:rep:signature', callback); + } + + function checkMinReputation(callerUid, uid, setting, callback) { + var isSelf = parseInt(callerUid, 10) === parseInt(uid, 10); + if (!isSelf) { + return setImmediate(callback); + } + async.waterfall([ + function (next) { + User.getUserField(uid, 'reputation', next); + }, + function (reputation, next) { + if (parseInt(reputation, 10) < (parseInt(meta.config[setting], 10) || 0)) { + return next(new Error('[[error:not-enough-reputation-' + setting.replace(/:/g, '-') + ']]')); + } + next(); + }, + ], callback); + } + function updateEmail(uid, newEmail, callback) { async.waterfall([ function (next) { diff --git a/src/views/admin/settings/reputation.tpl b/src/views/admin/settings/reputation.tpl index aee71910d4..7843273d2d 100644 --- a/src/views/admin/settings/reputation.tpl +++ b/src/views/admin/settings/reputation.tpl @@ -32,8 +32,11 @@