mirror of
				https://github.com/NodeBB/NodeBB.git
				synced 2025-10-31 11:05:54 +01:00 
			
		
		
		
	Closes #5521
This commit is contained in:
		| @@ -95,7 +95,8 @@ | ||||
|     "validator": "^6.1.0", | ||||
|     "winston": "^2.1.0", | ||||
|     "xml": "^1.0.1", | ||||
|     "xregexp": "~3.1.0" | ||||
|     "xregexp": "~3.1.0", | ||||
|     "zxcvbn": "^4.4.2" | ||||
|   }, | ||||
|   "devDependencies": { | ||||
|     "coveralls": "^2.11.14", | ||||
|   | ||||
| @@ -37,6 +37,7 @@ | ||||
| 	"min-username-length": "Minimum Username Length", | ||||
| 	"max-username-length": "Maximum Username Length", | ||||
| 	"min-password-length": "Minimum Password Length", | ||||
| 	"min-password-strength": "Minimum Password Strength", | ||||
| 	"max-about-me-length": "Maximum About Me Length", | ||||
| 	"terms-of-use": "Forum Terms of Use <small>(Leave blank to disable)</small>", | ||||
| 	"user-search": "User Search", | ||||
|   | ||||
| @@ -62,6 +62,7 @@ | ||||
| 	"username_taken_workaround": "The username you requested was already taken, so we have altered it slightly. You are now known as <strong>%1</strong>", | ||||
| 	"password_same_as_username": "Your password is the same as your username, please select another password.", | ||||
| 	"password_same_as_email": "Your password is the same as your email, please select another password.", | ||||
| 	"weak_password": "Weak password.", | ||||
|  | ||||
| 	"upload_picture": "Upload picture", | ||||
| 	"upload_a_picture": "Upload a picture", | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| 'use strict'; | ||||
|  | ||||
|  | ||||
| define('forum/account/edit/password', ['forum/account/header', 'translator'], function (header, translator) { | ||||
| define('forum/account/edit/password', ['forum/account/header', 'translator', 'zxcvbn'], function (header, translator, zxcvbn) { | ||||
| 	var AccountEditPassword = {}; | ||||
|  | ||||
| 	AccountEditPassword.init = function () { | ||||
| @@ -20,6 +20,7 @@ define('forum/account/edit/password', ['forum/account/header', 'translator'], fu | ||||
| 		var passwordsmatch = false; | ||||
|  | ||||
| 		function onPasswordChanged() { | ||||
| 			var passwordStrength = zxcvbn(password.val()); | ||||
| 			passwordvalid = false; | ||||
| 			if (password.val().length < ajaxify.data.minimumPasswordLength) { | ||||
| 				showError(password_notify, '[[user:change_password_error_length]]'); | ||||
| @@ -29,6 +30,8 @@ define('forum/account/edit/password', ['forum/account/header', 'translator'], fu | ||||
| 				showError(password_notify, '[[user:password_same_as_username]]'); | ||||
| 			} else if (password.val() === ajaxify.data.email) { | ||||
| 				showError(password_notify, '[[user:password_same_as_email]]'); | ||||
| 			} else if (passwordStrength.score < ajaxify.data.minimumPasswordStrength) { | ||||
| 				showError(password_notify, '[[user:weak_password]]'); | ||||
| 			} else { | ||||
| 				showSuccess(password_notify); | ||||
| 				passwordvalid = true; | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| 'use strict'; | ||||
|  | ||||
|  | ||||
| define('forum/register', ['translator'], function (translator) { | ||||
| define('forum/register', ['translator', 'zxcvbn'], function (translator, zxcvbn) { | ||||
| 	var Register = {}; | ||||
| 	var validationError = false; | ||||
| 	var successIcon = ''; | ||||
| @@ -170,6 +170,7 @@ define('forum/register', ['translator'], function (translator) { | ||||
| 	function validatePassword(password, password_confirm) { | ||||
| 		var password_notify = $('#password-notify'); | ||||
| 		var password_confirm_notify = $('#password-confirm-notify'); | ||||
| 		var passwordStrength = zxcvbn(password); | ||||
|  | ||||
| 		if (password.length < ajaxify.data.minimumPasswordLength) { | ||||
| 			showError(password_notify, '[[user:change_password_error_length]]'); | ||||
| @@ -181,6 +182,8 @@ define('forum/register', ['translator'], function (translator) { | ||||
| 			showError(password_notify, '[[user:password_same_as_username]]'); | ||||
| 		} else if (password === $('#email').val()) { | ||||
| 			showError(password_notify, '[[user:password_same_as_email]]'); | ||||
| 		} else if (passwordStrength.score < ajaxify.data.minimumPasswordStrength) { | ||||
| 			showError(password_notify, '[[user:weak_password]]'); | ||||
| 		} else { | ||||
| 			showSuccess(password_notify, successIcon); | ||||
| 		} | ||||
|   | ||||
| @@ -36,15 +36,12 @@ editController.get = function (req, res, callback) { | ||||
| 		}); | ||||
|  | ||||
| 		userData.title = '[[pages:account/edit, ' + userData.username + ']]'; | ||||
| 		userData.breadcrumbs = helpers.buildBreadcrumbs([ | ||||
| 			{ | ||||
| 				text: userData.username, | ||||
| 				url: '/user/' + userData.userslug, | ||||
| 			}, | ||||
| 			{ | ||||
| 				text: '[[user:edit]]', | ||||
| 			}, | ||||
| 		]); | ||||
| 		userData.breadcrumbs = helpers.buildBreadcrumbs([{ | ||||
| 			text: userData.username, | ||||
| 			url: '/user/' + userData.userslug, | ||||
| 		}, { | ||||
| 			text: '[[user:edit]]', | ||||
| 		}]); | ||||
| 		userData.editButtons = []; | ||||
|  | ||||
| 		plugins.fireHook('filter:user.account.edit', userData, function (err, userData) { | ||||
| @@ -80,22 +77,19 @@ function renderRoute(name, req, res, next) { | ||||
|  | ||||
| 		if (name === 'password') { | ||||
| 			userData.minimumPasswordLength = parseInt(meta.config.minimumPasswordLength, 10); | ||||
| 			userData.minimumPasswordStrength = parseInt(meta.config.minimumPasswordStrength || 0, 10); | ||||
| 		} | ||||
|  | ||||
| 		userData.title = '[[pages:account/edit/' + name + ', ' + userData.username + ']]'; | ||||
| 		userData.breadcrumbs = helpers.buildBreadcrumbs([ | ||||
| 			{ | ||||
| 				text: userData.username, | ||||
| 				url: '/user/' + userData.userslug, | ||||
| 			}, | ||||
| 			{ | ||||
| 				text: '[[user:edit]]', | ||||
| 				url: '/user/' + userData.userslug + '/edit', | ||||
| 			}, | ||||
| 			{ | ||||
| 				text: '[[user:' + name + ']]', | ||||
| 			}, | ||||
| 		]); | ||||
| 		userData.breadcrumbs = helpers.buildBreadcrumbs([{ | ||||
| 			text: userData.username, | ||||
| 			url: '/user/' + userData.userslug, | ||||
| 		}, { | ||||
| 			text: '[[user:edit]]', | ||||
| 			url: '/user/' + userData.userslug + '/edit', | ||||
| 		}, { | ||||
| 			text: '[[user:' + name + ']]', | ||||
| 		}]); | ||||
|  | ||||
| 		res.render('account/edit/' + name, userData); | ||||
| 	}); | ||||
|   | ||||
| @@ -48,7 +48,11 @@ Controllers.home = function (req, res, next) { | ||||
| 		var hook = 'action:homepage.get:' + route; | ||||
|  | ||||
| 		if (plugins.hasListeners(hook)) { | ||||
| 			return plugins.fireHook(hook, { req: req, res: res, next: next }); | ||||
| 			return plugins.fireHook(hook, { | ||||
| 				req: req, | ||||
| 				res: res, | ||||
| 				next: next, | ||||
| 			}); | ||||
| 		} | ||||
|  | ||||
| 		if (route === 'categories' || route === '/') { | ||||
| @@ -85,7 +89,12 @@ Controllers.reset = function (req, res, next) { | ||||
| 				displayExpiryNotice: req.session.passwordExpired, | ||||
| 				code: req.params.code, | ||||
| 				minimumPasswordLength: parseInt(meta.config.minimumPasswordLength, 10), | ||||
| 				breadcrumbs: helpers.buildBreadcrumbs([{ text: '[[reset_password:reset_password]]', url: '/reset' }, { text: '[[reset_password:update_password]]' }]), | ||||
| 				breadcrumbs: helpers.buildBreadcrumbs([{ | ||||
| 					text: '[[reset_password:reset_password]]', | ||||
| 					url: '/reset', | ||||
| 				}, { | ||||
| 					text: '[[reset_password:update_password]]', | ||||
| 				}]), | ||||
| 				title: '[[pages:reset]]', | ||||
| 			}); | ||||
|  | ||||
| @@ -94,7 +103,9 @@ Controllers.reset = function (req, res, next) { | ||||
| 	} else { | ||||
| 		res.render('reset', { | ||||
| 			code: null, | ||||
| 			breadcrumbs: helpers.buildBreadcrumbs([{ text: '[[reset_password:reset_password]]' }]), | ||||
| 			breadcrumbs: helpers.buildBreadcrumbs([{ | ||||
| 				text: '[[reset_password:reset_password]]', | ||||
| 			}]), | ||||
| 			title: '[[pages:reset]]', | ||||
| 		}); | ||||
| 	} | ||||
| @@ -124,7 +135,9 @@ Controllers.login = function (req, res, next) { | ||||
| 	data.allowLocalLogin = parseInt(meta.config.allowLocalLogin, 10) === 1 || parseInt(req.query.local, 10) === 1; | ||||
| 	data.allowRegistration = registrationType === 'normal' || registrationType === 'admin-approval' || registrationType === 'admin-approval-ip'; | ||||
| 	data.allowLoginWith = '[[login:' + allowLoginWith + ']]'; | ||||
| 	data.breadcrumbs = helpers.buildBreadcrumbs([{ text: '[[global:login]]' }]); | ||||
| 	data.breadcrumbs = helpers.buildBreadcrumbs([{ | ||||
| 		text: '[[global:login]]', | ||||
| 	}]); | ||||
| 	data.error = req.flash('error')[0] || errorText; | ||||
| 	data.title = '[[pages:login]]'; | ||||
|  | ||||
| @@ -171,7 +184,11 @@ Controllers.register = function (req, res, next) { | ||||
| 			} | ||||
| 		}, | ||||
| 		function (next) { | ||||
| 			plugins.fireHook('filter:parse.post', { postData: { content: meta.config.termsOfUse || '' } }, next); | ||||
| 			plugins.fireHook('filter:parse.post', { | ||||
| 				postData: { | ||||
| 					content: meta.config.termsOfUse || '', | ||||
| 				}, | ||||
| 			}, next); | ||||
| 		}, | ||||
| 	], function (err, termsOfUse) { | ||||
| 		if (err) { | ||||
| @@ -188,8 +205,11 @@ Controllers.register = function (req, res, next) { | ||||
| 		data.minimumUsernameLength = parseInt(meta.config.minimumUsernameLength, 10); | ||||
| 		data.maximumUsernameLength = parseInt(meta.config.maximumUsernameLength, 10); | ||||
| 		data.minimumPasswordLength = parseInt(meta.config.minimumPasswordLength, 10); | ||||
| 		data.minimumPasswordStrength = parseInt(meta.config.minimumPasswordStrength || 0, 10); | ||||
| 		data.termsOfUse = termsOfUse.postData.content; | ||||
| 		data.breadcrumbs = helpers.buildBreadcrumbs([{ text: '[[register:register]]' }]); | ||||
| 		data.breadcrumbs = helpers.buildBreadcrumbs([{ | ||||
| 			text: '[[register:register]]', | ||||
| 		}]); | ||||
| 		data.regFormEntry = []; | ||||
| 		data.error = req.flash('error')[0] || errorText; | ||||
| 		data.title = '[[pages:register]]'; | ||||
| @@ -333,7 +353,9 @@ Controllers.outgoing = function (req, res, next) { | ||||
| 	res.render('outgoing', { | ||||
| 		outgoing: validator.escape(String(url)), | ||||
| 		title: meta.config.title, | ||||
| 		breadcrumbs: helpers.buildBreadcrumbs([{ text: '[[notifications:outgoing_link]]' }]), | ||||
| 		breadcrumbs: helpers.buildBreadcrumbs([{ | ||||
| 			text: '[[notifications:outgoing_link]]', | ||||
| 		}]), | ||||
| 	}); | ||||
| }; | ||||
|  | ||||
| @@ -341,7 +363,9 @@ Controllers.termsOfUse = function (req, res, next) { | ||||
| 	if (!meta.config.termsOfUse) { | ||||
| 		return next(); | ||||
| 	} | ||||
| 	res.render('tos', { termsOfUse: meta.config.termsOfUse }); | ||||
| 	res.render('tos', { | ||||
| 		termsOfUse: meta.config.termsOfUse, | ||||
| 	}); | ||||
| }; | ||||
|  | ||||
| Controllers.ping = function (req, res) { | ||||
|   | ||||
| @@ -89,6 +89,7 @@ module.exports = function (Meta) { | ||||
| 				'jqueryui.js': 'public/vendor/jquery/js/jquery-ui.js', | ||||
| 				'buzz.js': 'public/vendor/buzz/buzz.js', | ||||
| 				'cropper.js': './node_modules/cropperjs/dist/cropper.min.js', | ||||
| 				'zxcvbn.js': './node_modules/zxcvbn/dist/zxcvbn.js', | ||||
| 			}, | ||||
| 		}, | ||||
| 	}; | ||||
| @@ -110,7 +111,9 @@ module.exports = function (Meta) { | ||||
| 						} | ||||
|  | ||||
| 						if (filePath.endsWith('.min.js')) { | ||||
| 							minified = { code: buffer.toString() }; | ||||
| 							minified = { | ||||
| 								code: buffer.toString(), | ||||
| 							}; | ||||
| 							return cb(); | ||||
| 						} | ||||
|  | ||||
| @@ -345,7 +348,9 @@ module.exports = function (Meta) { | ||||
| 			/** | ||||
| 			 * otherwise, just clean up --debug/--debug-brk options which are set up by default from the parent one | ||||
| 			 */ | ||||
| 			forkProcessParams = { execArgv: [] }; | ||||
| 			forkProcessParams = { | ||||
| 				execArgv: [], | ||||
| 			}; | ||||
| 		} | ||||
|  | ||||
| 		return forkProcessParams; | ||||
|   | ||||
| @@ -167,6 +167,16 @@ | ||||
| 				<label>[[admin/settings/user:min-password-length]]</label> | ||||
| 				<input type="text" class="form-control" value="6" data-field="minimumPasswordLength"> | ||||
| 			</div> | ||||
| 			<div class="form-group"> | ||||
| 				<label>[[admin/settings/user:min-password-strength]]</label> | ||||
| 				<select class="form-control" data-field="minimumPasswordStrength"> | ||||
| 					<option value="0">0 - too guessable: risky password</option> | ||||
| 					<option value="1">1 - very guessable</option> | ||||
| 					<option value="2">2 - somewhat guessable</option> | ||||
| 					<option value="3">3 - safely unguessable</option> | ||||
| 					<option value="4">4 - very unguessable</option> | ||||
| 				</select> | ||||
| 			</div> | ||||
| 			<div class="form-group"> | ||||
| 				<label>[[admin/settings/user:max-about-me-length]]</label> | ||||
| 				<input type="text" class="form-control" value="500" data-field="maximumAboutMeLength"> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user