diff --git a/api/models/authentication/ConfirmEmailForm.php b/api/models/authentication/ConfirmEmailForm.php index a568308..34b3556 100644 --- a/api/models/authentication/ConfirmEmailForm.php +++ b/api/models/authentication/ConfirmEmailForm.php @@ -2,56 +2,53 @@ namespace api\models\authentication; use api\models\AccountIdentity; -use api\models\base\KeyConfirmationForm; +use api\models\base\ApiForm; use api\models\profile\ChangeUsernameForm; +use api\validators\EmailActivationKeyValidator; use common\models\Account; use common\models\EmailActivation; use Yii; use yii\base\ErrorException; -class ConfirmEmailForm extends KeyConfirmationForm { +class ConfirmEmailForm extends ApiForm { + public $key; + + public function rules() { + return [ + ['key', EmailActivationKeyValidator::class, 'type' => EmailActivation::TYPE_REGISTRATION_EMAIL_CONFIRMATION], + ]; + } + + /** + * @return \api\components\User\LoginResult|bool + * @throws ErrorException + */ public function confirm() { if (!$this->validate()) { return false; } - $confirmModel = $this->getActivationCodeModel(); - if ($confirmModel->type !== EmailActivation::TYPE_REGISTRATION_EMAIL_CONFIRMATION) { - $confirmModel->delete(); - // TODO: вот где-то здесь нужно ещё попутно сгенерировать соответствующую ошибку - return false; - } - $transaction = Yii::$app->db->beginTransaction(); - try { - $account = $confirmModel->account; - $account->status = Account::STATUS_ACTIVE; - if (!$confirmModel->delete()) { - throw new ErrorException('Unable remove activation key.'); - } - if (!$account->save()) { - throw new ErrorException('Unable activate user account.'); - } - - $changeUsernameForm = new ChangeUsernameForm(); - $changeUsernameForm->createEventTask($account->id, $account->username, null); - - $transaction->commit(); - } catch (ErrorException $e) { - $transaction->rollBack(); - if (YII_DEBUG) { - throw $e; - } else { - return false; - } + /** @var \common\models\confirmations\RegistrationConfirmation $confirmModel */ + $confirmModel = $this->key; + $account = $confirmModel->account; + $account->status = Account::STATUS_ACTIVE; + if (!$confirmModel->delete()) { + throw new ErrorException('Unable remove activation key.'); } - /** @var \api\components\User\Component $component */ - $component = Yii::$app->user; + if (!$account->save()) { + throw new ErrorException('Unable activate user account.'); + } - return $component->login(new AccountIdentity($account->attributes), true); + $changeUsernameForm = new ChangeUsernameForm(); + $changeUsernameForm->createEventTask($account->id, $account->username, null); + + $transaction->commit(); + + return Yii::$app->user->login(new AccountIdentity($account->attributes), true); } } diff --git a/api/models/authentication/RecoverPasswordForm.php b/api/models/authentication/RecoverPasswordForm.php index 867268c..661fbea 100644 --- a/api/models/authentication/RecoverPasswordForm.php +++ b/api/models/authentication/RecoverPasswordForm.php @@ -2,26 +2,30 @@ namespace api\models\authentication; use api\models\AccountIdentity; -use api\models\base\KeyConfirmationForm; +use api\models\base\ApiForm; +use api\validators\EmailActivationKeyValidator; use common\helpers\Error as E; use common\models\EmailActivation; use common\validators\PasswordValidator; use Yii; use yii\base\ErrorException; -class RecoverPasswordForm extends KeyConfirmationForm { +class RecoverPasswordForm extends ApiForm { + + public $key; public $newPassword; public $newRePassword; public function rules() { - return array_merge(parent::rules(), [ + return [ + ['key', EmailActivationKeyValidator::class, 'type' => EmailActivation::TYPE_FORGOT_PASSWORD_KEY], ['newPassword', 'required', 'message' => E::NEW_PASSWORD_REQUIRED], ['newRePassword', 'required', 'message' => E::NEW_RE_PASSWORD_REQUIRED], ['newPassword', PasswordValidator::class], ['newRePassword', 'validatePasswordAndRePasswordMatch'], - ]); + ]; } public function validatePasswordAndRePasswordMatch($attribute) { @@ -32,46 +36,32 @@ class RecoverPasswordForm extends KeyConfirmationForm { } } + /** + * @return \api\components\User\LoginResult|bool + * @throws ErrorException + */ public function recoverPassword() { if (!$this->validate()) { return false; } - $confirmModel = $this->getActivationCodeModel(); - if ($confirmModel->type !== EmailActivation::TYPE_FORGOT_PASSWORD_KEY) { - $confirmModel->delete(); - // TODO: вот где-то здесь нужно ещё попутно сгенерировать соответствующую ошибку - return false; - } - $transaction = Yii::$app->db->beginTransaction(); - try { - $account = $confirmModel->account; - $account->password = $this->newPassword; - if (!$confirmModel->delete()) { - throw new ErrorException('Unable remove activation key.'); - } - if (!$account->save(false)) { - throw new ErrorException('Unable activate user account.'); - } - - $transaction->commit(); - } catch (ErrorException $e) { - $transaction->rollBack(); - if (YII_DEBUG) { - throw $e; - } else { - return false; - } + /** @var \common\models\confirmations\ForgotPassword $confirmModel */ + $confirmModel = $this->key; + $account = $confirmModel->account; + $account->password = $this->newPassword; + if (!$confirmModel->delete()) { + throw new ErrorException('Unable remove activation key.'); } - // TODO: ещё было бы неплохо уведомить пользователя о том, что его пароль изменился + if (!$account->save(false)) { + throw new ErrorException('Unable activate user account.'); + } - /** @var \api\components\User\Component $component */ - $component = Yii::$app->user; + $transaction->commit(); - return $component->login(new AccountIdentity($account->attributes), false); + return Yii::$app->user->login(new AccountIdentity($account->attributes), false); } } diff --git a/api/models/base/KeyConfirmationForm.php b/api/models/base/KeyConfirmationForm.php deleted file mode 100644 index 9148351..0000000 --- a/api/models/base/KeyConfirmationForm.php +++ /dev/null @@ -1,33 +0,0 @@ - E::KEY_REQUIRED], - ['key', EmailActivationKeyValidator::class], - ]; - } - - /** - * @return EmailActivation|null - */ - public function getActivationCodeModel() { - if ($this->model === null) { - $this->model = EmailActivation::findOne($this->key); - } - - return $this->model; - } - -} diff --git a/api/models/profile/ChangeEmail/ConfirmNewEmailForm.php b/api/models/profile/ChangeEmail/ConfirmNewEmailForm.php index d5683f9..2a8bfc9 100644 --- a/api/models/profile/ChangeEmail/ConfirmNewEmailForm.php +++ b/api/models/profile/ChangeEmail/ConfirmNewEmailForm.php @@ -1,60 +1,60 @@ account = $account; - parent::__construct($config); + public function rules() { + return [ + ['key', EmailActivationKeyValidator::class, 'type' => EmailActivation::TYPE_NEW_EMAIL_CONFIRMATION], + ]; } /** * @return Account */ - public function getAccount() : Account { + public function getAccount(): Account { return $this->account; } - public function changeEmail() : bool { + public function changeEmail(): bool { if (!$this->validate()) { return false; } $transaction = Yii::$app->db->beginTransaction(); - try { - /** @var \common\models\confirmations\NewEmailConfirmation $activation */ - $activation = $this->getActivationCodeModel(); - $activation->delete(); - $account = $this->getAccount(); - $oldEmail = $account->email; - $account->email = $activation->newEmail; - if (!$account->save()) { - throw new ErrorException('Cannot save new account email value'); - } + /** @var \common\models\confirmations\NewEmailConfirmation $activation */ + $activation = $this->key; + $activation->delete(); - $this->createTask($account->id, $account->email, $oldEmail); - - $transaction->commit(); - } catch (Exception $e) { - $transaction->rollBack(); - throw $e; + $account = $this->getAccount(); + $oldEmail = $account->email; + $account->email = $activation->newEmail; + if (!$account->save()) { + throw new ErrorException('Cannot save new account email value'); } + $this->createTask($account->id, $account->email, $oldEmail); + + $transaction->commit(); + return true; } @@ -77,4 +77,9 @@ class ConfirmNewEmailForm extends KeyConfirmationForm { Amqp::sendToEventsExchange('accounts.email-changed', $message); } + public function __construct(Account $account, array $config = []) { + $this->account = $account; + parent::__construct($config); + } + } diff --git a/api/models/profile/ChangeEmail/NewEmailForm.php b/api/models/profile/ChangeEmail/NewEmailForm.php index 9dd8b76..9f05948 100644 --- a/api/models/profile/ChangeEmail/NewEmailForm.php +++ b/api/models/profile/ChangeEmail/NewEmailForm.php @@ -1,17 +1,19 @@ account = $account; - parent::__construct($config); - } - public function rules() { - return array_merge(parent::rules(), [ + return [ + ['key', EmailActivationKeyValidator::class, 'type' => EmailActivation::TYPE_CURRENT_EMAIL_CONFIRMATION], ['email', EmailValidator::class], - ]); + ]; } - public function getAccount() : Account { + public function getAccount(): Account { return $this->account; } - public function sendNewEmailConfirmation() { + public function sendNewEmailConfirmation(): bool { if (!$this->validate()) { return false; } $transaction = Yii::$app->db->beginTransaction(); - try { - $previousActivation = $this->getActivationCodeModel(); - $previousActivation->delete(); - $activation = $this->createCode(); - $this->sendCode($activation); + /** @var \common\models\confirmations\CurrentEmailConfirmation $previousActivation */ + $previousActivation = $this->key; + $previousActivation->delete(); - $transaction->commit(); - } catch (Exception $e) { - $transaction->rollBack(); - throw $e; - } + $activation = $this->createCode(); + $this->sendCode($activation); + + $transaction->commit(); return true; } @@ -98,4 +93,9 @@ class NewEmailForm extends KeyConfirmationForm { } } + public function __construct(Account $account, array $config = []) { + $this->account = $account; + parent::__construct($config); + } + } diff --git a/api/validators/EmailActivationKeyValidator.php b/api/validators/EmailActivationKeyValidator.php index 16293d1..fb02ed1 100644 --- a/api/validators/EmailActivationKeyValidator.php +++ b/api/validators/EmailActivationKeyValidator.php @@ -22,6 +22,8 @@ class EmailActivationKeyValidator extends Validator { public $expired = E::KEY_EXPIRE; + public $skipOnEmpty = false; + public function validateAttribute($model, $attribute) { $value = $model->$attribute; if (empty($value)) { diff --git a/tests/codeception/api/unit/models/base/KeyConfirmationFormTest.php b/tests/codeception/api/unit/models/base/KeyConfirmationFormTest.php deleted file mode 100644 index 6a06378..0000000 --- a/tests/codeception/api/unit/models/base/KeyConfirmationFormTest.php +++ /dev/null @@ -1,29 +0,0 @@ - EmailActivationFixture::class, - ]; - } - - public function testGetActivationCodeModel() { - $model = new KeyConfirmationForm(); - $model->key = $this->tester->grabFixture('emailActivations', 'freshRegistrationConfirmation')['key']; - $this->assertInstanceOf(EmailActivation::class, $model->getActivationCodeModel()); - - $model = new KeyConfirmationForm(); - $model->key = 'this-is-invalid-key'; - $this->assertNull($model->getActivationCodeModel()); - } - -}