public function ChangePassword($LOGIN, $CHECKWORD, $PASSWORD, $CONFIRM_PASSWORD, $SITE_ID = false, $captcha_word = '', $captcha_sid = 0, $authActions = true, $phoneNumber = '', $currentPassword = '')
{
/** @global CMain $APPLICATION */
global $DB, $APPLICATION;
$arParams = [
"LOGIN" => &$LOGIN,
"CHECKWORD" => &$CHECKWORD,
"PASSWORD" => &$PASSWORD,
"CONFIRM_PASSWORD" => &$CONFIRM_PASSWORD,
"SITE_ID" => &$SITE_ID,
"PHONE_NUMBER" => &$phoneNumber,
"CURRENT_PASSWORD" => &$currentPassword,
];
$APPLICATION->ResetException();
foreach (GetModuleEvents('main', 'OnBeforeUserChangePassword', true) as $arEvent)
{
if (ExecuteModuleEventEx($arEvent, [&$arParams]) === false)
{
if ($err = $APPLICATION->GetException())
{
return ["MESSAGE" => $err->GetString() . "
", "TYPE" => "ERROR"];
}
return ["MESSAGE" => GetMessage("main_change_pass_error") . "
", "TYPE" => "ERROR"];
}
}
if (Option::get('main', 'captcha_restoring_password', 'N') == 'Y')
{
if (!($APPLICATION->CaptchaCheckCode($captcha_word, $captcha_sid)))
{
return ["MESSAGE" => GetMessage("main_user_captcha_error") . "
", "TYPE" => "ERROR"];
}
}
$phoneAuth = ($arParams["PHONE_NUMBER"] != '' && Option::get('main', 'new_user_phone_auth', 'N') == 'Y');
$strAuthError = '';
if (mb_strlen($arParams["LOGIN"]) < 3 && !$phoneAuth)
{
$strAuthError .= GetMessage('MIN_LOGIN') . "
";
}
if ($arParams["CHECKWORD"] == '' && $arParams["CURRENT_PASSWORD"] == '')
{
$strAuthError .= GetMessage("main_change_pass_empty_checkword") . "
";
}
if ($arParams["PASSWORD"] != $arParams["CONFIRM_PASSWORD"])
{
$strAuthError .= GetMessage('WRONG_CONFIRMATION') . "
";
}
if ($strAuthError != '')
{
return ["MESSAGE" => $strAuthError, "TYPE" => "ERROR"];
}
$updateFields = [
"PASSWORD" => $arParams["PASSWORD"],
];
$res = [];
if ($phoneAuth)
{
$userId = static::VerifyPhoneCode($arParams["PHONE_NUMBER"], $arParams["CHECKWORD"]);
if (!$userId)
{
return ["MESSAGE" => GetMessage("main_change_pass_code_error"), "TYPE" => "ERROR"];
}
//activate user after phone number confirmation
$updateFields["ACTIVE"] = 'Y';
}
else
{
CTimeZone::Disable();
$db_check = $DB->Query(
"SELECT ID, LID, CHECKWORD, " . $DB->DateToCharFunction("CHECKWORD_TIME") . " as CHECKWORD_TIME, PASSWORD, LOGIN_ATTEMPTS, ACTIVE, BLOCKED " .
"FROM b_user " .
"WHERE LOGIN='" . $DB->ForSql($arParams["LOGIN"]) . "'" .
(
// $arParams["EXTERNAL_AUTH_ID"] can be changed in the OnBeforeUserChangePassword event
$arParams["EXTERNAL_AUTH_ID"] != '' ?
" AND EXTERNAL_AUTH_ID='" . $DB->ForSQL($arParams["EXTERNAL_AUTH_ID"]) . "' " :
" AND (EXTERNAL_AUTH_ID IS NULL OR EXTERNAL_AUTH_ID='') "
)
);
CTimeZone::Enable();
if (!($res = $db_check->Fetch()))
{
return ["MESSAGE" => GetMessage('LOGIN_NOT_FOUND1'), "TYPE" => "ERROR", "FIELD" => "LOGIN"];
}
$userId = $res["ID"];
}
$policy = static::getPolicy($userId);
$arPolicy = $policy->getValues();
$passwordErrors = static::CheckPasswordAgainstPolicy($arParams["PASSWORD"], $arPolicy);
if (!empty($passwordErrors))
{
return ["MESSAGE" => implode("
", $passwordErrors) . "
", "TYPE" => "ERROR"];
}
if (!$phoneAuth)
{
if ($arParams["CHECKWORD"] != '')
{
//change the password using the checkword
if ($res["CHECKWORD"] == '' || !Password::equals($res["CHECKWORD"], $arParams["CHECKWORD"]))
{
return ["MESSAGE" => GetMessage("CHECKWORD_INCORRECT1") . "
", "TYPE" => "ERROR", "FIELD" => "CHECKWORD"];
}
$site_format = CSite::GetDateFormat();
if (time() - $policy->getCheckwordTimeout() * 60 > MakeTimeStamp($res["CHECKWORD_TIME"], $site_format))
{
return ["MESSAGE" => GetMessage("CHECKWORD_EXPIRE") . "
", "TYPE" => "ERROR", "FIELD" => "CHECKWORD_EXPIRE"];
}
}
else
{
//change the password using the current password
$loginAttempts = intval($res["LOGIN_ATTEMPTS"]) + 1;
//show captcha after a serial of incorrect login attempts
$policyLoginAttempts = (int)$policy->getLoginAttempts();
if ($policyLoginAttempts > 0 && $loginAttempts > $policyLoginAttempts)
{
$APPLICATION->SetNeedCAPTHA(true);
if (!$APPLICATION->CaptchaCheckCode($captcha_word, $captcha_sid))
{
return ["MESSAGE" => GetMessage("main_user_captcha_error") . "
", "TYPE" => "ERROR"];
}
}
$passwordCorrect = false;
if ($res["BLOCKED"] != 'Y')
{
$passwordCorrect = Password::equals($res["PASSWORD"], $arParams["CURRENT_PASSWORD"]);
if (!$passwordCorrect)
{
//block the user after numerous incorrect login attempts
$policyBlockAttempts = (int)$policy->getBlockLoginAttempts();
$policyBlockTime = (int)$policy->getBlockTime();
if ($policyBlockAttempts > 0 && $policyBlockTime > 0 && $loginAttempts >= $policyBlockAttempts)
{
if ($res["ACTIVE"] == 'Y')
{
static::blockUser($res["ID"], $policyBlockTime, $loginAttempts);
}
}
}
if ($passwordCorrect)
{
$passwordErrors = static::CheckPasswordAgainstPolicy($arParams["PASSWORD"], $arPolicy, $res["ID"]);
if (!empty($passwordErrors))
{
return ["MESSAGE" => implode("
", $passwordErrors) . "
", "TYPE" => "ERROR"];
}
$APPLICATION->SetNeedCAPTHA(false);
}
}
if (!$passwordCorrect)
{
//incorrect password
$DB->Query("UPDATE b_user SET LOGIN_ATTEMPTS = " . $loginAttempts . ", TIMESTAMP_X = TIMESTAMP_X WHERE ID = " . intval($res["ID"]));
return ["MESSAGE" => GetMessage("main_change_pass_incorrect_pass") . "
", "TYPE" => "ERROR", "FIELD" => "CURRENT_PASSWORD"];
}
}
if ($arParams["SITE_ID"] === false)
{
if (defined("ADMIN_SECTION") && ADMIN_SECTION === true)
{
$arParams["SITE_ID"] = CSite::GetDefSite($res["LID"]);
}
else
{
$arParams["SITE_ID"] = SITE_ID;
}
}
}
// change the password
$obUser = new CUser;
$res = $obUser->Update($userId, $updateFields, $authActions);
if (!$res && $obUser->LAST_ERROR != '')
{
return ["MESSAGE" => $obUser->LAST_ERROR . "
", "TYPE" => "ERROR"];
}
if ($phoneAuth)
{
return ["MESSAGE" => GetMessage("main_change_pass_changed") . "
", "TYPE" => "OK"];
}
else
{
static::SendUserInfo($userId, $arParams["SITE_ID"], GetMessage('CHANGE_PASS_SUCC'), true, 'USER_PASS_CHANGED');
return ["MESSAGE" => GetMessage('PASSWORD_CHANGE_OK') . "
", "TYPE" => "OK"];
}
}