Skip to content

Commit

Permalink
Allow re-sending confirmation e-mail - fixes #955
Browse files Browse the repository at this point in the history
  • Loading branch information
CatoTH committed Oct 19, 2024
1 parent 2c3ce14 commit 600bcd5
Show file tree
Hide file tree
Showing 19 changed files with 87 additions and 33 deletions.
6 changes: 5 additions & 1 deletion controllers/UserController.php
Original file line number Diff line number Diff line change
Expand Up @@ -271,8 +271,11 @@ public function actionConfirmregistration(string $backUrl = '', string $email =
$msgError = '';
$prefillCode = '';
$usernamePasswordForm = new LoginUsernamePasswordForm(RequestContext::getSession(), User::getExternalAuthenticator());
$ongoingSessionUser = $usernamePasswordForm->getOngoingEmailConfirmationSessionUser();

if ($this->isRequestSet('email') && $this->isRequestSet('code')) {
if ($this->isRequestSet('resend') && $ongoingSessionUser && !$ongoingSessionUser->hasTooRecentRecoveryEmail()) {
$usernamePasswordForm->sendConfirmationEmail($ongoingSessionUser);
} elseif ($this->isRequestSet('email') && $this->isRequestSet('code')) {
/** @var User|null $user */
$user = User::findOne(['auth' => 'email:' . $this->getRequestValue('email')]);
if (!$user) {
Expand Down Expand Up @@ -313,6 +316,7 @@ public function actionConfirmregistration(string $backUrl = '', string $email =
'prefillCode' => $prefillCode,
'errors' => $msgError,
'backUrl' => $backUrl,
'allowResend' => ($ongoingSessionUser && !$ongoingSessionUser->hasTooRecentRecoveryEmail()),
]
));
}
Expand Down
1 change: 1 addition & 0 deletions messages/de/user.php
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@
hier den Code in der E-Mail eingibst.',
'confirm_code' => 'Bestätigungs-Code',
'confirm_btn_do' => 'Bestätigen',
'confirm_resend' => 'Bestätigungsmail erneut verschicken',

'confirmed_title' => 'Zugang bestätigt',
'confirmed_msg' => 'Alles klar! Dein Zugang ist freigeschaltet und du kannst loslegen!',
Expand Down
1 change: 1 addition & 0 deletions messages/en/user.php
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@
'confirm_mail_sent' => 'An email was just sent to your address. Please confirm receiving this mail by clicking on the link in the mail or by entering the given code on this page.',
'confirm_code' => 'Confirmation code',
'confirm_btn_do' => 'Confirm',
'confirm_resend' => 'Resend confirmation e-mail',

'confirmed_title' => 'Account confirmed',
'confirmed_msg' => 'Your\'re all set! Your account is confirmed and you are good to go.',
Expand Down
17 changes: 12 additions & 5 deletions models/db/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -713,18 +713,25 @@ public function getAuthType(): int
}
}

public function hasTooRecentRecoveryEmail(): bool
{
if (!$this->recoveryAt) {
return false;
}
$recTs = Tools::dateSql2timestamp($this->recoveryAt);

return ($recTs + 3600) > time();
}

/**
* @throws MailNotSent
* @throws FormError
* @throws \app\models\exceptions\ServerConfiguration
*/
public function sendRecoveryMail(): void
{
if ($this->recoveryAt) {
$recTs = Tools::dateSql2timestamp($this->recoveryAt);
if (time() - $recTs < 24 * 3600) {
throw new FormError(\Yii::t('user', 'err_recover_mail_sent'));
}
if ($this->hasTooRecentRecoveryEmail()) {
throw new FormError(\Yii::t('user', 'err_recover_mail_sent'));
}
if ($this->email === null) {
return;
Expand Down
23 changes: 17 additions & 6 deletions models/forms/LoginUsernamePasswordForm.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,19 +48,19 @@ public function rules(): array
/**
* @throws MailNotSent
*/
private function sendConfirmationEmail(User $user): void
public function sendConfirmationEmail(User $user): void
{
if ($this->externalAuthenticator && !$this->externalAuthenticator->supportsCreatingAccounts()) {
throw new Internal('Creating account is not supported');
}
$bestCode = $user->createEmailConfirmationCode();
$params = ['/user/confirmregistration', 'email' => $this->username, 'code' => $bestCode, 'subdomain' => null];
$params = ['/user/confirmregistration', 'email' => $user->email, 'code' => $bestCode, 'subdomain' => null];
$link = UrlHelper::absolutizeLink(UrlHelper::createUrl($params));

\app\components\mail\Tools::sendWithLog(
EMailLog::TYPE_REGISTRATION,
null,
$this->username,
$user->email,
$user->id,
\Yii::t('user', 'create_emailconfirm_title'),
\Yii::t('user', 'create_emailconfirm_msg'),
Expand All @@ -70,8 +70,10 @@ private function sendConfirmationEmail(User $user): void
'%BEST_LINK%' => $link,
]
);
}

$user->recoveryAt = date('Y-m-d H:i:s');
$user->save();
}

/**
* @throws Login
Expand All @@ -96,7 +98,7 @@ private function doCreateAccountValidate(?Site $site): void
throw new Login($this->error);
}
if (strlen($this->password) < static::PASSWORD_MIN_LEN) {
$this->error = str_replace('%MINLEN%', static::PASSWORD_MIN_LEN, \Yii::t('user', 'create_err_pwdlength'));
$this->error = str_replace('%MINLEN%', (string)static::PASSWORD_MIN_LEN, \Yii::t('user', 'create_err_pwdlength'));
throw new Login($this->error);
}
if ($this->password !== $this->passwordConfirm) {
Expand Down Expand Up @@ -136,7 +138,7 @@ public function supportsCreatingAccounts(): bool
public function doCreateAccount(?Site $site): User
{
if (!$this->supportsCreatingAccounts()) {
throw new Internal('Creating account is not supported');
throw new Internal('Creating accounts is not supported');
}
if ($this->externalAuthenticator) {
return $this->externalAuthenticator->performRegistration($this->username, $this->password);
Expand Down Expand Up @@ -294,6 +296,15 @@ public function hasOngoingEmailConfirmationSession(User $user): bool
return $data['user_id'] === $user->id;
}

public function getOngoingEmailConfirmationSessionUser(): ?User
{
$data = $this->session->get(self::SESSION_KEY_EMAIL_CONFIRMATION);
if (!$data) {
return null;
}
return User::findOne(['id' => $data['user_id']]);
}

public function setLoggedInAwaitingPasswordChange(User $user): void
{
$this->session->set(self::SESSION_KEY_PWD_CHANGE, [
Expand Down
2 changes: 1 addition & 1 deletion plugins/green_layout/assets/layout-green_layout.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion plugins/green_layout/assets/layout-green_layout.css.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion plugins/gruen_ci/assets/layout-gruen_ci1.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion plugins/gruen_ci/assets/layout-gruen_ci1.css.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion plugins/gruen_ci/assets/layout-gruen_ci2.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion plugins/gruen_ci/assets/layout-gruen_ci2.css.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion plugins/gruen_ci/assets/layout-gruen_ci3.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion plugins/gruen_ci/assets/layout-gruen_ci3.css.map

Large diffs are not rendered by default.

29 changes: 20 additions & 9 deletions views/user/confirm_registration.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
* @var string $prefillCode
* @var string $backUrl
* @var string $email
* @var \app\models\db\User|null $allowResend
*/

$this->title = Yii::t('user', 'confirm_title');
Expand Down Expand Up @@ -39,14 +40,14 @@
echo Html::beginForm(UrlHelper::createUrl($params), 'post', ['id' => 'confirmAccountForm']);
?>

<div class="form-group">
<label for="username"><?= Yii::t('user', 'confirm_username') ?>:</label>
<input type="text" value="<?= Html::encode($email) ?>" id="username" name="email" class="form-control"
<?php if ($email != '') echo "disabled"; ?>
>
</div>
<div class="inputHolder">
<label for="username"><?= Yii::t('user', 'confirm_username') ?>:</label>
<input type="text" value="<?= Html::encode($email) ?>" id="username" name="email" class="form-control"
<?php if ($email != '') echo "disabled"; ?>
>
</div>

<div class="form-group">
<div class="inputHolder">
<label for="code"><?= Yii::t('user', 'confirm_code') ?>:</label>
<input type="text" name="code" value="<?= Html::encode($prefillCode) ?>" id="code" class="form-control" autocomplete="off">
</div>
Expand All @@ -65,8 +66,18 @@
}
?>

<div>
<input type="submit" value="<?= Yii::t('user', 'confirm_btn_do') ?>" class="btn btn-primary">
<div class="saveResetRow">
<div class="save">
<input type="submit" value="<?= Yii::t('user', 'confirm_btn_do') ?>" class="btn btn-primary">
</div>

<?php if ($allowResend) { ?>
<div class="resend">
<button type="submit" class="btn btn-link" name="resend">
<?= Yii::t('user', 'confirm_resend') ?>
</button>
</div>
<?php } ?>
</div>

<?= Html::endForm() ?>
Expand Down
19 changes: 19 additions & 0 deletions web/css/_user_pages.scss
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,25 @@
width: 400px;
}
}
#confirmAccountForm {
.inputHolder {
margin-bottom: 15px;
}
.saveResetRow {
overflow: auto;
.save {
float: left;
}
.resend {
float: right;
button {
font-weight: normal;
font-size: 0.8em;
font-style: italic;
}
}
}
}

#conPwdForm {
@media (min-width: $screenMinWith) {
Expand Down
2 changes: 1 addition & 1 deletion web/css/layout-classic.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion web/css/layout-classic.css.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion web/css/layout-dbjr.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion web/css/layout-dbjr.css.map

Large diffs are not rendered by default.

0 comments on commit 600bcd5

Please sign in to comment.