{include file='formError'}
+<p class="info">{lang}wcf.user.newPassword.info{/lang}</p>
+
<form method="post" action="{link controller='NewPassword'}{/link}">
<div class="section">
- <dl{if $errorField == 'userID'} class="formError"{/if}>
- <dt>
- <label for="userID">{lang}wcf.user.userID{/lang}</label>
- </dt>
+ <dl{if $errorField == 'newPassword'} class="formError"{/if}>
+ <dt><label for="newPassword">{lang}wcf.user.newPassword{/lang}</label></dt>
<dd>
- <input type="text" id="userID" name="u" value="{@$userID}" required class="medium">
- {if $errorField == 'userID'}
+ <input type="password" id="newPassword" name="newPassword" value="{$newPassword}" class="medium">
+
+ {if $errorField == 'newPassword'}
<small class="innerError">
- {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}
</small>
{/if}
</dd>
</dl>
- <dl{if $errorField == 'lostPasswordKey'} class="formError"{/if}>
- <dt>
- <label for="lostPasswordKey">{lang}wcf.user.lostPasswordKey{/lang}</label>
- </dt>
+ <dl{if $errorField == 'confirmNewPassword'} class="formError"{/if}>
+ <dt><label for="confirmNewPassword">{lang}wcf.user.confirmPassword{/lang}</label></dt>
<dd>
- <input type="text" id="lostPasswordKey" name="k" value="{$lostPasswordKey}" required class="medium">
- {if $errorField == 'lostPasswordKey'}
+ <input type="password" id="confirmNewPassword" name="confirmNewPassword" value="{$confirmNewPassword}" class="medium">
+
+ {if $errorField == 'confirmNewPassword'}
<small class="innerError">
- {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}
</small>
{/if}
</dd>
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.
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', [
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.
*/
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');
}
}
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', [
]);
$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;
}
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();
- }
- }
}
<item name="wcf.user.lostPassword.mail.sent"><![CDATA[{if LANGUAGE_USE_INFORMAL_VARIANT}Du erhälst{else}Sie erhalten{/if} in Kürze eine E-Mail mit weiteren Informationen.]]></item>
<item name="wcf.user.lostPasswordKey"><![CDATA[Sicherheitsschlüssel]]></item>
<item name="wcf.user.lostPasswordKey.error.notValid"><![CDATA[{if LANGUAGE_USE_INFORMAL_VARIANT}Du hast{else}Sie haben{/if} einen ungültigen Sicherheitsschlüssel angegeben.]]></item>
+ <item name="wcf.user.newPassword"><![CDATA[Neues Kennwort]]></item>
+ <item name="wcf.user.newPassword.info"><![CDATA[{if LANGUAGE_USE_INFORMAL_VARIANT}Du bist{else}Sie sind{/if} im Begriff das Kennwort des Benutzers „{$user->username}“ zu ändern.]]></item>
+ <item name="wcf.user.newPassword.success"><![CDATA[Das Kennwort des Benutzers „{$user->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.]]></item>
<item name="wcf.user.userID.error.notValid"><![CDATA[{if LANGUAGE_USE_INFORMAL_VARIANT}Du hast{else}Sie haben{/if} eine ungültige Benutzer-ID angegeben.]]></item>
- <item name="wcf.user.newPassword.mail"><![CDATA[Hallo {@$username},
-
-{if LANGUAGE_USE_INFORMAL_VARIANT}dein{else}Ihr{/if} neues Kennwort für die Website "{@PAGE_TITLE|language}" lautet:
-{@$newPassword}
-
-
-{if LANGUAGE_USE_INFORMAL_VARIANT}Du kannst dein{else}Sie können Ihr{/if} Kennwort unter folgender Adresse jederzeit ändern:
-{link controller='AccountManagement' isEmail=true}{/link} ]]></item>
- <item name="wcf.user.newPassword.mail.subject"><![CDATA[Neues Kennwort auf der Website: {@PAGE_TITLE|language}]]></item>
- <item name="wcf.user.newPassword.success"><![CDATA[{if LANGUAGE_USE_INFORMAL_VARIANT}Du erhälst{else}Sie erhalten{/if} in Kürze eine E-Mail mit {if LANGUAGE_USE_INFORMAL_VARIANT}deinem{else}Ihrem{/if} neuen Kennwort.]]></item>
+ <item name="wcf.user.accountManagement"><![CDATA[Benutzerkonto-Verwaltung]]></item>
<item name="wcf.user.accountManagement.warning"><![CDATA[{if LANGUAGE_USE_INFORMAL_VARIANT}Du bearbeitest dein{else}Sie bearbeiten Ihr{/if} eigenes Benutzerkonto. Unbedachte Änderungen können dazu führen, dass {if LANGUAGE_USE_INFORMAL_VARIANT}du dich nicht mehr anmelden kannst. Bitte sei entsprechend vorsichtig!{else}Sie sich nicht mehr anmelden können. Bitte seien Sie entsprechend vorsichtig!{/if}]]></item>
<item name="wcf.user.accountManagement.password.description"><![CDATA[Bitte {if LANGUAGE_USE_INFORMAL_VARIANT}gib zur Bestätigung dein{else}geben Sie zur Bestätigung Ihr{/if} <u>bisheriges</u> Kennwort ein!]]></item>
- <item name="wcf.user.newPassword"><![CDATA[Neues Kennwort]]></item>
<item name="wcf.user.changeUsername"><![CDATA[Benutzernamen ändern]]></item>
<item name="wcf.user.changeUsername.description"><![CDATA[{if LANGUAGE_USE_INFORMAL_VARIANT}Du kannst deinen{else}Sie können Ihren{/if} Benutzernamen nur einmal alle {$renamePeriod} Tage ändern. Änderungen von Groß- auf Kleinschreibung und umgekehrt sind jederzeit möglich.
{if $__wcf->getUser()->lastUsernameChange}Die letzte Änderung erfolgte am {@$__wcf->getUser()->lastUsernameChange|date}.{/if}]]></item>
<item name="wcf.user.lostPassword.mail.sent"><![CDATA[You should receive an email shortly.]]></item>
<item name="wcf.user.lostPasswordKey"><![CDATA[Security Key]]></item>
<item name="wcf.user.lostPasswordKey.error.notValid"><![CDATA[Security Key is invalid.]]></item>
+ <item name="wcf.user.newPassword"><![CDATA[New Password]]></item>
+ <item name="wcf.user.newPassword.info"><![CDATA[You are setting a new password for the user “{$user->username}”.]]></item>
+ <item name="wcf.user.newPassword.success"><![CDATA[The password of the user “{$user->username}” has been changed successfully. You may now login with your new password.]]></item>
<item name="wcf.user.userID.error.notValid"><![CDATA[User ID is invalid.]]></item>
- <item name="wcf.user.newPassword.mail"><![CDATA[Dear {@$username},
-
-your new password for "{@PAGE_TITLE|language}" is:
-{@$newPassword}
-
-
-You can change your password any time at:
-{link controller='AccountManagement' isEmail=true}{/link} ]]></item>
- <item name="wcf.user.newPassword.mail.subject"><![CDATA[New Password for Website: {@PAGE_TITLE|language}]]></item>
- <item name="wcf.user.newPassword.success"><![CDATA[You should receive an email with your password shortly.]]></item>
+ <item name="wcf.user.accountManagement"><![CDATA[Account Management]]></item>
<item name="wcf.user.accountManagement.warning"><![CDATA[Heads up! You’re editing your own user account, careless changes might lock you out!]]></item>
<item name="wcf.user.accountManagement.password.description"><![CDATA[Please confirm changes with your <u>current</u> password!]]></item>
- <item name="wcf.user.newPassword"><![CDATA[New Password]]></item>
<item name="wcf.user.changeUsername"><![CDATA[Change Username]]></item>
<item name="wcf.user.changeUsername.description"><![CDATA[You may change your username every {$renamePeriod} days. Changes between uppercase or lowercase are always allowed.
{if $__wcf->getUser()->lastUsernameChange}Last change was {@$__wcf->getUser()->lastUsernameChange|date}.{/if}]]></item>
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 '',