Fix #6730: Invitation link for existing user (#6916)

This commit is contained in:
Marc Farré 2024-04-04 10:25:31 +02:00 committed by GitHub
parent 45c5912329
commit 39379bc8b6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 38 additions and 19 deletions

View File

@ -75,3 +75,4 @@ HumHub Changelog
- Fix #6908: Fix default mentioning URL
- Enh #6901: Auto load pages on content search
- Fix #6913: Fix API tests
- Fix #6730: Invitation link for existing user

View File

@ -113,7 +113,7 @@ class AuthController extends Controller
// Self Invite
$invite = new Invite();
$invite->scenario = 'invite';
$invite->scenario = Invite::SCENARIO_INVITE;
if ($invite->load(Yii::$app->request->post()) && $invite->selfInvite()) {
if (Yii::$app->request->isAjax) {
return $this->renderAjax('register_success_modal', ['model' => $invite]);

View File

@ -147,10 +147,13 @@ class RegistrationController extends Controller
$linkRegistrationService->storeInSession();
$form = new Invite(['source' => Invite::SOURCE_INVITE_BY_LINK]);
$form = new Invite([
'source' => Invite::SOURCE_INVITE_BY_LINK,
'scenario' => Invite::SCENARIO_INVITE_BY_LINK_FORM,
]);
if ($form->load(Yii::$app->request->post()) && $form->validate()) {
$invite = $linkRegistrationService->convertToInvite($form->email);
$invite->sendInviteMail();
$invite?->sendInviteMail();
return $this->render('@user/views/auth/register_success', ['model' => $invite]);
}

View File

@ -43,6 +43,8 @@ class Invite extends ActiveRecord
public const SOURCE_SELF = 'self';
public const SOURCE_INVITE = 'invite';
public const SOURCE_INVITE_BY_LINK = 'invite_by_link';
public const SCENARIO_INVITE = 'invite';
public const SCENARIO_INVITE_BY_LINK_FORM = 'invite_by_link_form';
public const EMAIL_TOKEN_LENGTH = 12;
public const LINK_TOKEN_LENGTH = 14; // Should be different that EMAIL_TOKEN_LENGTH
@ -74,9 +76,9 @@ class Invite extends ActiveRecord
[['email'], 'string', 'max' => 150],
[['language'], 'string', 'max' => 10],
[['email'], 'required'],
[['email'], 'unique'],
[['email'], 'unique', 'except' => self::SCENARIO_INVITE_BY_LINK_FORM],
[['email'], 'email'],
[['captcha'], 'captcha', 'captchaAction' => 'user/auth/captcha', 'on' => static::SOURCE_INVITE],
[['captcha'], 'captcha', 'captchaAction' => 'user/auth/captcha', 'on' => [self::SCENARIO_INVITE, self::SCENARIO_INVITE_BY_LINK_FORM]],
];
}
@ -86,10 +88,12 @@ class Invite extends ActiveRecord
public function scenarios()
{
$scenarios = parent::scenarios();
$scenarios['invite'] = ['email'];
$scenarios[self::SCENARIO_INVITE] = ['email'];
$scenarios[self::SCENARIO_INVITE_BY_LINK_FORM] = ['email'];
if ($this->showCaptureInRegisterForm()) {
$scenarios['invite'][] = 'captcha';
$scenarios[self::SCENARIO_INVITE][] = 'captcha';
$scenarios[self::SCENARIO_INVITE_BY_LINK_FORM][] = 'captcha';
}
return $scenarios;
@ -175,13 +179,12 @@ class Invite extends ActiveRecord
'html' => '@humhub/modules/user/views/mails/UserInviteSelf',
'text' => '@humhub/modules/user/views/mails/plaintext/UserInviteSelf'
], [
'token' => $this->token,
'registrationUrl' => $registrationUrl
]);
$mail->setTo($this->email);
$mail->setSubject(Yii::t('UserModule.base', 'Welcome to %appName%', ['%appName%' => Yii::$app->name]));
$result = $mail->send();
} elseif ($this->source == self::SOURCE_INVITE && $this->space !== null) {
} elseif ($this->source === self::SOURCE_INVITE && $this->space !== null) {
if ($module->sendInviteMailsInGlobalLanguage) {
Yii::$app->setLanguage(Yii::$app->settings->get('defaultLanguage'));
}
@ -190,7 +193,6 @@ class Invite extends ActiveRecord
'html' => '@humhub/modules/user/views/mails/UserInviteSpace',
'text' => '@humhub/modules/user/views/mails/plaintext/UserInviteSpace'
], [
'token' => $this->token,
'originator' => $this->originator,
'originatorName' => $this->originator->displayName,
'space' => $this->space,
@ -202,7 +204,7 @@ class Invite extends ActiveRecord
// Switch back to users language
Yii::$app->setLanguage(Yii::$app->user->language);
} elseif ($this->source == self::SOURCE_INVITE) {
} elseif ($this->source === self::SOURCE_INVITE) {
// Switch to systems default language
if ($module->sendInviteMailsInGlobalLanguage) {
@ -215,7 +217,6 @@ class Invite extends ActiveRecord
], [
'originator' => $this->originator,
'originatorName' => $this->originator->displayName,
'token' => $this->token,
'registrationUrl' => $registrationUrl
]);
$mail->setTo($this->email);
@ -234,7 +235,7 @@ class Invite extends ActiveRecord
*
* @return bool
*/
private function isRegisteredUser(): bool
public function isRegisteredUser(): bool
{
return User::find()->where(['email' => $this->email])->exists();
}

View File

@ -12,8 +12,10 @@ use humhub\modules\space\models\Space;
use humhub\modules\user\models\Invite;
use humhub\modules\user\models\User;
use humhub\modules\user\Module;
use Throwable;
use Yii;
use yii\base\Exception;
use yii\db\StaleObjectException;
/**
* LinkRegistrationService is responsible for registrations (Global or per Space) using an Invite Link.
@ -88,17 +90,21 @@ final class LinkRegistrationService
return $newToken;
}
public function convertToInvite(string $email): Invite
/**
* @throws Exception
* @throws Throwable
* @throws StaleObjectException
*/
public function convertToInvite(string $email): ?Invite
{
// Deleting any previous email invitation or abandoned link invitation
$oldInvite = Invite::findOne(['email' => $email]);
if ($oldInvite !== null) {
$oldInvites = Invite::findAll(['email' => $email]);
foreach ($oldInvites as $oldInvite) {
$oldInvite->delete();
}
$invite = new Invite([
'email' => $email,
'scenario' => 'invite',
'language' => Yii::$app->language,
]);
$invite->skipCaptchaValidation = true;
@ -107,6 +113,11 @@ final class LinkRegistrationService
$invite->space_invite_id = $this->space->id;
}
if ($invite->isRegisteredUser()) {
$invite->sendAlreadyRegisteredUserMail();
return null;
}
if (!$invite->save()) {
throw new Exception('Could not create invite!');
}

View File

@ -1,9 +1,12 @@
<?php
use humhub\modules\ui\mail\DefaultMailStyle;
use yii\helpers\Url;
use yii\helpers\Html;
/**
* @var $registrationUrl string
*/
?>
<tr>
<td align="center" valign="top" class="fix-box">
@ -126,7 +129,7 @@ use yii\helpers\Html;
<span
style="color: <?= Yii::$app->view->theme->variable('text-color-contrast', '#fff') ?>; font-weight: 300;">
<a href="<?php echo Url::toRoute(['/user/registration', 'token' => $token], true); ?>"
<a href="<?= $registrationUrl ?>"
style="text-decoration: none; color: <?= Yii::$app->view->theme->variable('text-color-contrast', '#fff') ?>; font-weight: 300;">
<strong><?php echo Yii::t('UserModule.base', 'Sign up'); ?></strong>
</a>