From 5f6542f13c8bde2948f828a829c442a353617f12 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Tim=20D=C3=BCsterhus?= Date: Tue, 14 Jun 2016 21:58:59 +0200 Subject: [PATCH] Set new password in NewPasswordForm instead of mailing it --- com.woltlab.wcf/templates/newPassword.tpl | 34 ++++--- .../files/lib/form/LostPasswordForm.class.php | 4 +- .../files/lib/form/NewPasswordForm.class.php | 94 ++++++++++--------- wcfsetup/install/lang/de.xml | 15 +-- wcfsetup/install/lang/en.xml | 15 +-- wcfsetup/setup/db/install.sql | 2 +- 6 files changed, 79 insertions(+), 85 deletions(-) diff --git a/com.woltlab.wcf/templates/newPassword.tpl b/com.woltlab.wcf/templates/newPassword.tpl index 015c7632d5..9441088a87 100644 --- a/com.woltlab.wcf/templates/newPassword.tpl +++ b/com.woltlab.wcf/templates/newPassword.tpl @@ -2,35 +2,33 @@ {include file='formError'} +

{lang}wcf.user.newPassword.info{/lang}

+
- -
- -
+ +
- - {if $errorField == 'userID'} + + + {if $errorField == 'newPassword'} - {lang}wcf.user.userID.error.{$errorType}{/lang} + {if $errorType == 'empty'}{lang}wcf.global.form.error.empty{/lang}{/if} + {if $errorType == 'notSecure'}{lang}wcf.user.password.error.notSecure{/lang}{/if} {/if}
- -
- -
+ +
- - {if $errorField == 'lostPasswordKey'} + + + {if $errorField == 'confirmNewPassword'} - {if $errorType == 'empty'} - {lang}wcf.global.form.error.empty{/lang} - {else} - {lang}wcf.user.lostPasswordKey.error.{$errorType}{/lang} - {/if} + {if $errorType == 'empty'}{lang}wcf.global.form.error.empty{/lang}{/if} + {if $errorType == 'notEqual'}{lang}wcf.user.confirmPassword.error.notEqual{/lang}{/if} {/if}
diff --git a/wcfsetup/install/files/lib/form/LostPasswordForm.class.php b/wcfsetup/install/files/lib/form/LostPasswordForm.class.php index 11d1f7c558..3e67a26169 100644 --- a/wcfsetup/install/files/lib/form/LostPasswordForm.class.php +++ b/wcfsetup/install/files/lib/form/LostPasswordForm.class.php @@ -7,8 +7,8 @@ use wcf\system\exception\UserInputException; use wcf\system\mail\Mail; use wcf\system\request\LinkHandler; use wcf\system\WCF; +use wcf\util\CryptoUtil; use wcf\util\HeaderUtil; -use wcf\util\StringUtil; /** * Shows the lost password form. @@ -95,7 +95,7 @@ class LostPasswordForm extends AbstractCaptchaForm { parent::save(); // generate a new lost password key - $lostPasswordKey = StringUtil::getRandomID(); + $lostPasswordKey = bin2hex(CryptoUtil::randomBytes(20)); // save key and request time in database $this->objectAction = new UserAction([$this->user], 'update', [ diff --git a/wcfsetup/install/files/lib/form/NewPasswordForm.class.php b/wcfsetup/install/files/lib/form/NewPasswordForm.class.php index beb29fcfa3..dfc53c4871 100644 --- a/wcfsetup/install/files/lib/form/NewPasswordForm.class.php +++ b/wcfsetup/install/files/lib/form/NewPasswordForm.class.php @@ -2,14 +2,16 @@ namespace wcf\form; use wcf\data\user\User; use wcf\data\user\UserAction; +use wcf\data\user\UserEditor; use wcf\page\AbstractPage; +use wcf\system\exception\IllegalLinkException; use wcf\system\exception\UserInputException; -use wcf\system\mail\Mail; use wcf\system\request\LinkHandler; use wcf\system\WCF; use wcf\util\HeaderUtil; use wcf\util\PasswordUtil; use wcf\util\StringUtil; +use wcf\util\UserRegistrationUtil; /** * Shows the new password form. @@ -46,43 +48,71 @@ class NewPasswordForm extends AbstractForm { */ public $newPassword = ''; + /** + * confirmed new password + * @var string + */ + public $confirmNewPassword = ''; + /** * @inheritDoc */ public function readParameters() { parent::readParameters(); - if (isset($_REQUEST['u'])) $this->userID = intval($_REQUEST['u']); - if (isset($_REQUEST['k'])) $this->lostPasswordKey = StringUtil::trim($_REQUEST['k']); + if (isset($_GET['id'])) $this->userID = intval($_GET['id']); + else if (WCF::getSession()->getVar('lostPasswordRequest')) $this->userID = intval(WCF::getSession()->getVar('lostPasswordRequest')); + if (isset($_GET['k'])) $this->lostPasswordKey = StringUtil::trim($_GET['k']); + + $this->user = new User($this->userID); + if (!$this->user->userID) throw new IllegalLinkException(); - // disable check for security token for GET requests - if ($this->userID || $this->lostPasswordKey) { - $_POST['t'] = WCF::getSession()->getSecurityToken(); + if ($this->lostPasswordKey) { + if (!$this->user->lostPasswordKey) throw new IllegalLinkException(); + if (!PasswordUtil::secureCompare($this->user->lostPasswordKey, $this->lostPasswordKey)) { + throw new IllegalLinkException(); + } + // expire lost password requests after a day + if ($this->user->lastLostPasswordRequestTime < TIME_NOW - 86400) throw new IllegalLinkException(); + + (new UserEditor($this->user))->update([ + 'lastLostPasswordRequestTime' => 0, + 'lostPasswordKey' => NULL + ]); + WCF::getSession()->register('lostPasswordRequest', $this->user->userID); } } + /** + * @inheritDoc + */ + public function readFormParameters() { + parent::readFormParameters(); + + if (isset($_POST['newPassword'])) $this->newPassword = $_POST['newPassword']; + if (isset($_POST['confirmNewPassword'])) $this->confirmNewPassword = $_POST['confirmNewPassword']; + } + /** * @inheritDoc */ public function validate() { parent::validate(); - // get user - $this->user = new User($this->userID); - - if (!$this->user->userID) { - throw new UserInputException('userID', 'notValid'); + if (empty($this->newPassword)) { + throw new UserInputException('newPassword'); } - if (!$this->lostPasswordKey) { - throw new UserInputException('lostPasswordKey'); + + if (empty($this->confirmNewPassword)) { + throw new UserInputException('confirmNewPassword'); } - if (!$this->user->lostPasswordKey) { - throw new UserInputException('lostPasswordKey', 'notValid'); + if (!UserRegistrationUtil::isSecurePassword($this->newPassword)) { + throw new UserInputException('newPassword', 'notSecure'); } - if (!PasswordUtil::secureCompare($this->user->lostPasswordKey, $this->lostPasswordKey)) { - throw new UserInputException('lostPasswordKey', 'notValid'); + if ($this->newPassword != $this->confirmNewPassword) { + throw new UserInputException('confirmNewPassword', 'notEqual'); } } @@ -92,8 +122,7 @@ class NewPasswordForm extends AbstractForm { public function save() { parent::save(); - // generate new password - $this->newPassword = PasswordUtil::getRandomPassword((REGISTER_PASSWORD_MIN_LENGTH > 12 ? REGISTER_PASSWORD_MIN_LENGTH : 12)); + WCF::getSession()->unregister('lostPasswordRequest'); // update user $this->objectAction = new UserAction([$this->user], 'update', [ @@ -105,17 +134,8 @@ class NewPasswordForm extends AbstractForm { ]); $this->objectAction->executeAction(); - // send mail - $mail = new Mail([$this->user->username => $this->user->email], WCF::getLanguage()->getDynamicVariable('wcf.user.newPassword.mail.subject'), WCF::getLanguage()->getDynamicVariable('wcf.user.newPassword.mail', [ - 'username' => $this->user->username, - 'userID' => $this->user->userID, - 'newPassword' => $this->newPassword - ])); - $mail->send(); - $this->saved(); - // forward to index page - HeaderUtil::delayedRedirect(LinkHandler::getInstance()->getLink(), WCF::getLanguage()->get('wcf.user.newPassword.success')); + HeaderUtil::delayedRedirect(LinkHandler::getInstance()->getLink(), WCF::getLanguage()->getDynamicVariable('wcf.user.newPassword.success', ['user' => $this->user])); exit; } @@ -126,19 +146,9 @@ class NewPasswordForm extends AbstractForm { parent::assignVariables(); WCF::getTPL()->assign([ - 'userID' => $this->userID, - 'lostPasswordKey' => $this->lostPasswordKey + 'user' => $this->user, + 'newPassword' => $this->newPassword, + 'confirmNewPassword' => $this->confirmNewPassword ]); } - - /** - * @inheritDoc - */ - public function readData() { - AbstractPage::readData(); - - if (!empty($_POST) || (!empty($this->userID) && !empty($this->lostPasswordKey))) { - $this->submit(); - } - } } diff --git a/wcfsetup/install/lang/de.xml b/wcfsetup/install/lang/de.xml index 50d4cc43bd..dc1489a080 100644 --- a/wcfsetup/install/lang/de.xml +++ b/wcfsetup/install/lang/de.xml @@ -2847,20 +2847,13 @@ Fehler sind beispielsweise: + + username}“ zu ändern.]]> + username}“ wurde erfolgreich geändert. {if LANGUAGE_USE_INFORMAL_VARIANT}Du kannst dich{else}Sie können sich{/if} nun mit dem neuen Kennwort einloggen.]]> - - - + bisheriges Kennwort ein!]]> - getUser()->lastUsernameChange}Die letzte Änderung erfolgte am {@$__wcf->getUser()->lastUsernameChange|date}.{/if}]]> diff --git a/wcfsetup/install/lang/en.xml b/wcfsetup/install/lang/en.xml index 739179225f..e4e94b849d 100644 --- a/wcfsetup/install/lang/en.xml +++ b/wcfsetup/install/lang/en.xml @@ -2888,20 +2888,13 @@ If you have not lost your password, you can safely ignore this email.]]> + + username}”.]]> + username}” has been changed successfully. You may now login with your new password.]]> - - - + current password!]]> - getUser()->lastUsernameChange}Last change was {@$__wcf->getUser()->lastUsernameChange|date}.{/if}]]> diff --git a/wcfsetup/setup/db/install.sql b/wcfsetup/setup/db/install.sql index 494a428c39..133029dc3e 100644 --- a/wcfsetup/setup/db/install.sql +++ b/wcfsetup/setup/db/install.sql @@ -1273,7 +1273,7 @@ CREATE TABLE wcf1_user ( banExpires INT(10) NOT NULL DEFAULT 0, activationCode INT(10) NOT NULL DEFAULT 0, lastLostPasswordRequestTime INT(10) NOT NULL DEFAULT 0, - lostPasswordKey VARCHAR(40) NOT NULL DEFAULT '', + lostPasswordKey CHAR(40) DEFAULT NULL, lastUsernameChange INT(10) NOT NULL DEFAULT 0, newEmail VARCHAR(255) NOT NULL DEFAULT '', oldUsername VARCHAR(255) NOT NULL DEFAULT '', -- 2.20.1