-{include file='header' __disableAds=true}
-
-{include file='formError'}
+{include file='authFlowHeader'}
<woltlab-core-notice type="info">{lang}wcf.user.newPassword.info{/lang}</woltlab-core-notice>
-<form method="post" action="{link controller='NewPassword'}{/link}">
- <div class="section">
- <dl{if $errorField == 'newPassword'} class="formError"{/if}>
- <dt><label for="newPassword">{lang}wcf.user.newPassword{/lang}</label></dt>
- <dd>
- <input type="password" id="newPassword" name="newPassword" value="{$newPassword}" class="medium" autocomplete="new-password" passwordrules="{$passwordRulesAttributeValue}">
-
- {if $errorField == 'newPassword'}
- <small class="innerError">
- {if $errorType == 'empty'}
- {lang}wcf.global.form.error.empty{/lang}
- {else}
- {lang}wcf.user.password.error.{@$errorType}{/lang}
- {/if}
- </small>
- {/if}
- </dd>
- </dl>
-
- <dl{if $errorField == 'confirmNewPassword'} class="formError"{/if}>
- <dt><label for="confirmNewPassword">{lang}wcf.user.confirmPassword{/lang}</label></dt>
- <dd>
- <input type="password" id="confirmNewPassword" name="confirmNewPassword" value="{$confirmNewPassword}" class="medium" autocomplete="new-password" passwordrules="{$passwordRulesAttributeValue}">
-
- {if $errorField == 'confirmNewPassword'}
- <small class="innerError">
- {if $errorType == 'empty'}
- {lang}wcf.global.form.error.empty{/lang}
- {else}
- {lang}wcf.user.confirmPassword.error.{@$errorType}{/lang}
- {/if}
- </small>
- {/if}
- </dd>
- </dl>
-
- {event name='fields'}
-
- <script data-relocate="true">
- require(['WoltLabSuite/Core/Ui/User/PasswordStrength', 'Language'], function (PasswordStrength, Language) {
- {include file='passwordStrengthLanguage'}
-
- new PasswordStrength(elById('newPassword'), {
- staticDictionary: [
- '{$user->username|encodeJS}',
- '{$user->email|encodeJS}',
- ]
- });
- })
- </script>
- </div>
-
- {event name='sections'}
+{@$form->getHtml()}
+
+<script data-relocate="true">
+ require(['WoltLabSuite/Core/Ui/User/PasswordStrength', 'Language'], (PasswordStrength, Language) => {
+ {include file='passwordStrengthLanguage'}
- <div class="formSubmit">
- <input type="submit" value="{lang}wcf.global.button.submit{/lang}" accesskey="s">
- {csrfToken}
- </div>
-</form>
+ new PasswordStrength(document.getElementById('newPassword'), {
+ staticDictionary: [
+ '{$user->username|encodeJS}',
+ '{$user->email|encodeJS}',
+ ]
+ });
+ })
+</script>
-{include file='footer' __disableAds=true}
+{include file='authFlowFooter'}
use wcf\system\exception\NamedUserException;
use wcf\system\exception\PermissionDeniedException;
use wcf\system\exception\SystemException;
-use wcf\system\exception\UserInputException;
+use wcf\system\form\builder\container\FormContainer;
+use wcf\system\form\builder\field\PasswordFormField;
+use wcf\system\form\builder\field\validation\FormFieldValidationError;
+use wcf\system\form\builder\field\validation\FormFieldValidator;
+use wcf\system\form\builder\FormDocument;
use wcf\system\request\LinkHandler;
use wcf\system\WCF;
use wcf\util\HeaderUtil;
/**
* Shows the new password form.
*
- * @author Marcel Werk
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @author Marcel Werk
+ * @copyright 2001-2023 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
*/
-class NewPasswordForm extends AbstractForm
+final class NewPasswordForm extends AbstractFormBuilderForm
{
const AVAILABLE_DURING_OFFLINE_MODE = true;
- /**
- * user id
- * @var int
- */
- public $userID = 0;
-
- /**
- * lost password key
- * @var string
- */
- public $lostPasswordKey = '';
-
- /**
- * User object
- * @var User
- */
- public $user;
-
- /**
- * new password
- * @var string
- */
- public $newPassword = '';
-
- /**
- * @var mixed[]
- */
- public $newPasswordStrengthVerdict = [];
-
- /**
- * confirmed new password
- * @var string
- */
- public $confirmNewPassword = '';
+ public int $userID;
+ public string $lostPasswordKey;
+ public User $user;
/**
* @inheritDoc
/**
* @inheritDoc
*/
- public function readFormParameters()
+ protected function createForm()
{
- parent::readFormParameters();
+ // We have to create the form manually here to avoid the form getting the ID 'newPassword'.
+ $this->form = FormDocument::create('newPasswordForm');
+
+ $this->form->appendChild(
+ FormContainer::create('data')
+ ->appendChildren([
+ PasswordFormField::create('newPassword')
+ ->label('wcf.user.newPassword')
+ ->required()
+ ->autoFocus()
+ ->removeFieldClass('medium')
+ ->addFieldClass('long')
+ ->autocomplete('new-password')
+ ->fieldAttribute('passwordrules', UserRegistrationUtil::getPasswordRulesAttributeValue())
+ ->addValidator(new FormFieldValidator(
+ 'passwordValidator',
+ $this->validatePassword(...)
+ )),
+ ])
+ );
+ }
- if (isset($_POST['newPassword'])) {
- $this->newPassword = $_POST['newPassword'];
- }
+ private function validatePassword(PasswordFormField $formField): void
+ {
if (isset($_POST['newPassword_passwordStrengthVerdict'])) {
try {
- $this->newPasswordStrengthVerdict = JSON::decode($_POST['newPassword_passwordStrengthVerdict']);
+ $newPasswordStrengthVerdict = JSON::decode($_POST['newPassword_passwordStrengthVerdict']);
} catch (SystemException $e) {
// ignore
}
}
- if (isset($_POST['confirmNewPassword'])) {
- $this->confirmNewPassword = $_POST['confirmNewPassword'];
+
+ if (($newPasswordStrengthVerdict['score'] ?? 4) < PASSWORD_MIN_SCORE) {
+ $formField->addValidationError(
+ new FormFieldValidationError(
+ 'notSecure',
+ 'wcf.user.newPassword.error.notSecure'
+ )
+ );
}
}
/**
* @inheritDoc
*/
- public function validate()
+ public function assignVariables()
{
- parent::validate();
-
- if (empty($this->newPassword)) {
- throw new UserInputException('newPassword');
- }
-
- if (empty($this->confirmNewPassword)) {
- throw new UserInputException('confirmNewPassword');
- }
-
- if (($this->newPasswordStrengthVerdict['score'] ?? 4) < PASSWORD_MIN_SCORE) {
- throw new UserInputException('newPassword', 'notSecure');
- }
+ parent::assignVariables();
- if ($this->newPassword != $this->confirmNewPassword) {
- throw new UserInputException('confirmNewPassword', 'notEqual');
- }
+ WCF::getTPL()->assign([
+ 'user' => $this->user,
+ ]);
}
/**
*/
public function save()
{
- parent::save();
+ AbstractForm::save();
WCF::getSession()->unregister('lostPasswordRequest');
+ $this->updateUser();
+ $this->saved();
+ $this->forwardToIndexPage();
+
+ exit;
+ }
- // update user
+ private function updateUser(): void
+ {
+ $formData = $this->form->getData()['data'];
$this->objectAction = new UserAction([$this->user], 'update', [
'data' => \array_merge($this->additionalFields, [
- 'password' => $this->newPassword,
+ 'password' => $formData['newPassword'],
'lastLostPasswordRequestTime' => 0,
'lostPasswordKey' => '',
]),
]);
$this->objectAction->executeAction();
+ }
- // forward to index page
+ private function forwardToIndexPage(): void
+ {
HeaderUtil::delayedRedirect(
LinkHandler::getInstance()->getLink(),
- WCF::getLanguage()->getDynamicVariable('wcf.user.newPassword.success', ['user' => $this->user])
+ WCF::getLanguage()->getDynamicVariable('wcf.user.newPassword.success', ['user' => $this->user]),
+ 10,
+ 'success',
+ true
);
exit;
}
- /**
- * @inheritDoc
- */
- public function assignVariables()
- {
- parent::assignVariables();
-
- WCF::getTPL()->assign([
- 'user' => $this->user,
- 'newPassword' => $this->newPassword,
- 'confirmNewPassword' => $this->confirmNewPassword,
- 'passwordRulesAttributeValue' => UserRegistrationUtil::getPasswordRulesAttributeValue(),
- ]);
- }
-
- private function throwInvalidLinkException()
+ private function throwInvalidLinkException(): void
{
throw new NamedUserException(WCF::getLanguage()->getDynamicVariable('wcf.user.newPassword.error.invalidLink'));
}