diff --git a/main/admin/configure_inscription.php b/main/admin/configure_inscription.php
index faf736ab31..fdbd75e223 100755
--- a/main/admin/configure_inscription.php
+++ b/main/admin/configure_inscription.php
@@ -218,9 +218,7 @@ if ($display_all_form) {
$form->addRule('pass1', get_lang('ThisFieldIsRequired'), 'required');
$form->addRule('pass2', get_lang('ThisFieldIsRequired'), 'required');
$form->addRule(array('pass1', 'pass2'), get_lang('PassTwo'), 'compare');
- if (CHECK_PASS_EASY_TO_FIND === true) {
- $form->addRule('pass1', get_lang('PassTooEasy').': '.api_generate_password(), 'callback', 'api_check_password');
- }
+ $form->addPasswordRule('pass1');
// PHONE
$form->addElement('text', 'phone', get_lang('Phone'), array('size' => 40, 'disabled' => 'disabled'));
diff --git a/main/admin/user_add.php b/main/admin/user_add.php
index deb7a2075e..00837f2a4d 100755
--- a/main/admin/user_add.php
+++ b/main/admin/user_add.php
@@ -210,6 +210,7 @@ $group[] = $form->createElement(
);
$form->addGroup($group, 'password', get_lang('Password'));
+$form->addPasswordRule('password', 'password');
$form->addGroupRule('password', get_lang('EnterPassword'), 'required', null, 1);
if ($checkPass) {
@@ -472,3 +473,5 @@ $tpl = new Template($tool_name);
$tpl->assign('message', $message);
$tpl->assign('content', $content);
$tpl->display_one_col_template();
+
+
diff --git a/main/admin/user_edit.php b/main/admin/user_edit.php
index 247e42202a..9c39057a0e 100755
--- a/main/admin/user_edit.php
+++ b/main/admin/user_edit.php
@@ -231,7 +231,9 @@ $group[] = $form->createElement(
null,
array('onkeydown' => 'javascript: password_switch_radio_button();')
);
+
$form->addGroup($group, 'password', null, null, false);
+$form->addPasswordRule('password', 'password');
// Status
$status = array();
diff --git a/main/auth/inscription.php b/main/auth/inscription.php
index 72a789254f..f6f30135d4 100755
--- a/main/auth/inscription.php
+++ b/main/auth/inscription.php
@@ -178,15 +178,7 @@ if ($user_already_registered_show_terms === false) {
$form->addRule('pass1', get_lang('ThisFieldIsRequired'), 'required');
$form->addRule('pass2', get_lang('ThisFieldIsRequired'), 'required');
$form->addRule(array('pass1', 'pass2'), get_lang('PassTwo'), 'compare');
-
- if (CHECK_PASS_EASY_TO_FIND === true) {
- $form->addRule(
- 'pass1',
- get_lang('PassTooEasy') . ': ' . api_generate_password(),
- 'callback',
- 'api_check_password'
- );
- }
+ $form->addPasswordRule('pass1');
// PHONE
if (in_array('phone', $allowedFields)) {
diff --git a/main/auth/profile.php b/main/auth/profile.php
index c6f9b2fff0..c8b9c3b787 100755
--- a/main/auth/profile.php
+++ b/main/auth/profile.php
@@ -316,9 +316,7 @@ if (is_platform_authentication() &&
$form->addElement('password', 'password2', get_lang('Confirmation'), array('size' => 40));
// user must enter identical password twice so we can prevent some user errors
$form->addRule(array('password1', 'password2'), get_lang('PassTwo'), 'compare');
- if (CHECK_PASS_EASY_TO_FIND === true) {
- $form->addRule('password1', get_lang('CurrentPasswordEmptyOrIncorrect'), 'callback', 'api_check_password');
- }
+ $form->addPasswordRule('password1');
}
$extraField = new ExtraField('user');
diff --git a/main/inc/lib/api.lib.php b/main/inc/lib/api.lib.php
index ae3bd4dd31..9757a0cfb7 100644
--- a/main/inc/lib/api.lib.php
+++ b/main/inc/lib/api.lib.php
@@ -2008,29 +2008,24 @@ function api_generate_password($length = 8)
* 2. Only English letters (uppercase or lowercase, it doesn't matter) and digits are allowed.
* 3. The password should contain at least 3 letters.
* 4. It should contain at least 2 digits.
- * 5. It should not contain 3 or more consequent (according to ASCII table) characters.
* Settings will change if the configuration value is set: password_requirements
*/
function api_check_password($password)
{
- $passwordRequirements = api_get_configuration_value('password_requirements');
+ $passwordRequirements = Security::getPasswordRequirements();
- $minLength = 5;
- $minLetters = 3;
- $minNumbers = 2;
- $minLowerCase = 0; // Is only use if password_requirements is set
- $minUpperCase = 0; // Is only use if password_requirements is set
- if (!empty($passwordRequirements)) {
- $minLength = $passwordRequirements['min']['length'];
- $minNumbers = $passwordRequirements['min']['numeric'];
- $minLowerCase = $passwordRequirements['min']['lowercase'];
- $minUpperCase = $passwordRequirements['min']['uppercase'];
- $minLetters = $minLowerCase + $minUpperCase;
- }
+ $minLength = $passwordRequirements['min']['length'];
+ $minNumbers = $passwordRequirements['min']['numeric'];
+ // Optional
+ $minLowerCase = $passwordRequirements['min']['lowercase'];
+ $minUpperCase = $passwordRequirements['min']['uppercase'];
+
+ $minLetters = $minLowerCase + $minUpperCase;
$passwordLength = api_strlen($password);
- if ($passwordLength < $minLength) {
- return false;
- }
+
+ $conditions = [
+ 'min_length' => $passwordLength >= $minLength
+ ];
$digits = 0;
$lowerCase = 0;
@@ -2049,17 +2044,40 @@ function api_check_password($password)
$digits++;
}
}
+
+ // Min number of digits
+ $conditions['min_numeric'] = $digits >= $minNumbers;
+
+ if (!empty($minUpperCase)) {
+ // Uppercase
+ $conditions['min_uppercase'] = $upperCase >= $minUpperCase;
+ }
+
+ if (!empty($minLowerCase)) {
+ // Lowercase
+ $conditions['min_lowercase'] = $upperCase >= $minLowerCase;
+ }
+
+ // Min letters
$letters = $upperCase + $lowerCase;
+ $conditions['min_letters'] = $letters >= $minLetters;
- if (!empty($passwordRequirements)) {
- return (
- $upperCase >= $minUpperCase &&
- $lowerCase >= $minLowerCase &&
- $digits >= $minNumbers
- );
+ $isPasswordOk = true;
+ foreach ($conditions as $condition) {
+ if ($condition === false) {
+ $isPasswordOk = false;
+ break;
+ }
+ }
+
+ if ($isPasswordOk === false) {
+ $output = get_lang('NewPasswordRequirementsNotMatched').'
';
+ $output .= Security::getPasswordRequirementsToString($conditions);
+
+ Display::addFlash(Display::return_message($output, 'warning', false));
}
- return $letters >= $minLetters && $digits >= $minNumbers;
+ return $isPasswordOk;
}
/**
diff --git a/main/inc/lib/formvalidator/FormValidator.class.php b/main/inc/lib/formvalidator/FormValidator.class.php
index 93a708130e..2bdd92f622 100755
--- a/main/inc/lib/formvalidator/FormValidator.class.php
+++ b/main/inc/lib/formvalidator/FormValidator.class.php
@@ -1679,6 +1679,47 @@ EOT;
});
");
}
+
+ /**
+ * @param string $elementName
+ * @param string $groupName if element is inside a group
+ * @throws Exception
+ */
+ public function addPasswordRule($elementName, $groupName = '')
+ {
+ // Constant defined in old config/profile.conf.php
+ if (CHECK_PASS_EASY_TO_FIND === true) {
+ $message = get_lang('PassTooEasy').': '.api_generate_password();
+
+ if (!empty($groupName)) {
+ $groupObj = $this->getElement($groupName);
+
+ if ($groupObj instanceof HTML_QuickForm_group) {
+ $elementName = $groupObj->getElementName($elementName);
+
+ if ($elementName === false) {
+ throw new Exception("The $groupName doesn't have the element $elementName");
+ }
+
+ $this->_rules[$elementName][] = array(
+ 'type' => 'callback',
+ 'format' => 'api_check_password',
+ 'message' => $message,
+ 'validation' => '',
+ 'reset' => false,
+ 'group' => $groupName
+ );
+ }
+ } else {
+ $this->addRule(
+ $elementName,
+ $message,
+ 'callback',
+ 'api_check_password'
+ );
+ }
+ }
+ }
}
/**
diff --git a/main/inc/lib/security.lib.php b/main/inc/lib/security.lib.php
index 6509200f47..b250d6b6b0 100755
--- a/main/inc/lib/security.lib.php
+++ b/main/inc/lib/security.lib.php
@@ -432,4 +432,58 @@ class Security
}
return $image_path;
}
+
+ /**
+ * Get password requirements
+ * It checks config value 'password_requirements' or uses the "classic"
+ * Chamilo password requirements.
+ *
+ * @return array
+ */
+ public static function getPasswordRequirements()
+ {
+ // Default
+ $requirements = [
+ 'min' => [
+ 'lowercase' => 0,
+ 'uppercase' => 0,
+ 'numeric' => 2,
+ 'length' => 5
+ ]
+ ];
+
+ $passwordRequirements = api_get_configuration_value('password_requirements');
+ if (!empty($passwordRequirements)) {
+ $requirements = $passwordRequirements;
+ }
+
+ return $requirements;
+ }
+
+ /**
+ * Gets password requirements in the platform language using get_lang
+ * based in platform settings. See function 'self::getPasswordRequirements'
+ * @return string
+ */
+ public static function getPasswordRequirementsToString($passedConditions = [])
+ {
+ $output = '';
+ $setting = Security::getPasswordRequirements();
+ foreach ($setting as $type => $rules) {
+ foreach ($rules as $rule => $parameter) {
+ if (empty($parameter)) {
+ continue;
+ }
+ $output .= sprintf(
+ get_lang(
+ 'NewPasswordRequirement'.ucfirst($type).'X'.ucfirst($rule)
+ ),
+ $parameter
+ );
+ $output .= '
';
+ }
+ }
+
+ return $output;
+ }
}