diff --git a/app/lib/server/lib/PasswordPolicyClass.js b/app/lib/server/lib/PasswordPolicyClass.js index adee50bf7d4ab..3aed85a656e39 100644 --- a/app/lib/server/lib/PasswordPolicyClass.js +++ b/app/lib/server/lib/PasswordPolicyClass.js @@ -88,6 +88,41 @@ class PasswordPolicy { return true; } + + getPasswordPolicy() { + const data = { + enabled: false, + policy: [], + }; + if (this.enabled) { + data.enabled = true; + if (this.minLength >= 1) { + data.policy.push('get-password-policy-minLength', { minLength: this.minLength }); + } + if (this.maxLength >= 1) { + data.policy.push('get-password-policy-maxLength', { maxLength: this.maxLength }); + } + if (this.forbidRepeatingCharacters) { + data.policy.push('get-password-policy-forbidRepeatingCharacters'); + } + if (this.forbidRepeatingCharactersCount) { + data.policy.push('get-password-policy-forbidRepeatingCharactersCount', { forbidRepeatingCharactersCount: this.forbidRepeatingCharactersCount }); + } + if (this.mustContainAtLeastOneLowercase) { + data.policy.push('get-password-policy-mustContainAtLeastOneLowercase'); + } + if (this.mustContainAtLeastOneUppercase) { + data.policy.push('get-password-policy-mustContainAtLeastOneUppercase'); + } + if (this.mustContainAtLeastOneNumber) { + data.policy.push('get-password-policy-mustContainAtLeastOneNumber'); + } + if (this.mustContainAtLeastOneSpecialCharacter) { + data.policy.push('get-password-policy-mustContainAtLeastOneSpecialCharacter'); + } + } + return data; + } } export default PasswordPolicy; diff --git a/app/ui-login/client/reset-password/resetPassword.html b/app/ui-login/client/reset-password/resetPassword.html index 549d1fafb753a..733b0c8088860 100644 --- a/app/ui-login/client/reset-password/resetPassword.html +++ b/app/ui-login/client/reset-password/resetPassword.html @@ -26,5 +26,12 @@ + {{#if passwordPolicyEnabled}} +
+ {{#each passwordPolicy}} +

* {{_ this}}

+ {{/each}} +
+ {{/if}} diff --git a/app/ui-login/client/reset-password/resetPassword.js b/app/ui-login/client/reset-password/resetPassword.js index e5eaff9559fa0..f0784e60bb964 100644 --- a/app/ui-login/client/reset-password/resetPassword.js +++ b/app/ui-login/client/reset-password/resetPassword.js @@ -4,6 +4,7 @@ import { FlowRouter } from 'meteor/kadira:flow-router'; import { Template } from 'meteor/templating'; import toastr from 'toastr'; import { ReactiveDict } from 'meteor/reactive-dict'; +import { ReactiveVar } from 'meteor/reactive-var'; import { modal, call } from '../../../ui-utils/client'; import { t } from '../../../utils'; @@ -25,6 +26,12 @@ Template.resetPassword.helpers({ return user.requirePasswordChangeReason; } }, + passwordPolicyEnabled() { + return Template.instance().passwordPolicyEnabled.get(); + }, + passwordPolicy() { + return Template.instance().passwordPolicyRules.get(); + }, }); const resetPassword = (token, password) => new Promise((resolve, reject) => { @@ -105,4 +112,12 @@ Template.resetPassword.onRendered(function() { Template.resetPassword.onCreated(function() { this.state = new ReactiveDict({ password: '' }); + this.passwordPolicyEnabled = new ReactiveVar(false); + this.passwordPolicyRules = new ReactiveVar(); + Meteor.call('getPasswordPolicy', (error, result) => { + if (result.enabled) { + this.passwordPolicyEnabled.set(true); + this.passwordPolicyRules.set(result.policy); + } + }); }); diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index fb3223682d644..fbbbaa5d3f987 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -1685,6 +1685,14 @@ "Generate_new_key": "Generate a new key", "Generating_key": "Generating key", "Get_link": "Get Link", + "get-password-policy-forbidRepeatingCharacters": "The password should not contain repeating characters", + "get-password-policy-forbidRepeatingCharactersCount": "The password should not contain more than __forbidRepeatingCharactersCount__ repeating characters", + "get-password-policy-maxLength": "The password should be maximum __maxLength__ characters long", + "get-password-policy-minLength": "The password should be minimum __minLength__ characters long", + "get-password-policy-mustContainAtLeastOneLowercase": "The password should contain atleast one lowercase letter", + "get-password-policy-mustContainAtLeastOneNumber": "The password should contain atleast one number", + "get-password-policy-mustContainAtLeastOneSpecialCharacter": "The password should contain atleast one special character", + "get-password-policy-mustContainAtLeastOneUppercase": "The password should contain atleast one uppercase letter", "Generate_New_Link": "Generate New Link", "github_no_public_email": "You don't have any email as public email in your GitHub account", "Give_a_unique_name_for_the_custom_oauth": "Give a unique name for the custom oauth", diff --git a/server/main.js b/server/main.js index fd0439b8d8900..faaa47169fb55 100644 --- a/server/main.js +++ b/server/main.js @@ -28,6 +28,7 @@ import './methods/deleteFileMessage'; import './methods/deleteUser'; import './methods/eraseRoom'; import './methods/getAvatarSuggestion'; +import './methods/getPasswordPolicy'; import './methods/getRoomById'; import './methods/getRoomIdByNameOrId'; import './methods/getRoomNameById'; diff --git a/server/methods/getPasswordPolicy.js b/server/methods/getPasswordPolicy.js new file mode 100644 index 0000000000000..b2e2a64a4f405 --- /dev/null +++ b/server/methods/getPasswordPolicy.js @@ -0,0 +1,14 @@ +import { Meteor } from 'meteor/meteor'; + +import { passwordPolicy } from '../../app/lib'; + +Meteor.methods({ + getPasswordPolicy() { + if (!Meteor.userId()) { + throw new Meteor.Error('error-invalid-user', 'Invalid user', { + method: 'getPasswordPolicy', + }); + } + return passwordPolicy.getPasswordPolicy(); + }, +});