diff --git a/api/models/authentication/RegistrationForm.php b/api/models/authentication/RegistrationForm.php index 776da8f..fea1245 100644 --- a/api/models/authentication/RegistrationForm.php +++ b/api/models/authentication/RegistrationForm.php @@ -16,6 +16,7 @@ use Ramsey\Uuid\Uuid; use Yii; use yii\base\ErrorException; use yii\base\InvalidConfigException; +use yii\helpers\ArrayHelper; use const common\LATEST_RULES_VERSION; class RegistrationForm extends ApiForm { @@ -48,6 +49,7 @@ class RegistrationForm extends ApiForm { ['rePassword', 'validatePasswordAndRePasswordMatch'], ['lang', LanguageValidator::class], + ['lang', 'default', 'value' => 'en'], ]; } @@ -80,7 +82,7 @@ class RegistrationForm extends ApiForm { * @throws Exception */ public function signup() { - if (!$this->validate()) { + if (!$this->validate() && !$this->canContinue($this->getFirstErrors())) { return null; } @@ -95,7 +97,7 @@ class RegistrationForm extends ApiForm { $account->status = Account::STATUS_REGISTERED; $account->rules_agreement_version = LATEST_RULES_VERSION; $account->setRegistrationIp(Yii::$app->request->getUserIP()); - if (!$account->save()) { + if (!$account->save(false)) { throw new ErrorException('Account not created.'); } @@ -157,4 +159,43 @@ class RegistrationForm extends ApiForm { } } + /** + * Метод проверяет, можно ли занять указанный при регистрации ник или e-mail. Так случается, + * что пользователи вводят неправильный e-mail или ник, после замечают это и пытаются вновь + * выпонить регистрацию. Мы не будем им мешать и просто удаляем существующие недозарегистрированные + * аккаунты, позволяя им зарегистрироваться. + * + * @param array $errors массив, где ключ - это поле, а значение - первая ошибка из нашего + * стандартного словаря ошибок + * + * @return bool + */ + protected function canContinue(array $errors) : bool { + if (ArrayHelper::getValue($errors, 'username') === E::USERNAME_NOT_AVAILABLE) { + $duplicatedUsername = Account::findOne([ + 'username' => $this->username, + 'status' => Account::STATUS_REGISTERED, + ]); + + if ($duplicatedUsername !== null) { + $duplicatedUsername->delete(); + unset($errors['username']); + } + } + + if (ArrayHelper::getValue($errors, 'email') === E::EMAIL_NOT_AVAILABLE) { + $duplicatedEmail = Account::findOne([ + 'email' => $this->email, + 'status' => Account::STATUS_REGISTERED, + ]); + + if ($duplicatedEmail !== null) { + $duplicatedEmail->delete(); + unset($errors['email']); + } + } + + return empty($errors); + } + } diff --git a/api/models/profile/ChangeLanguageForm.php b/api/models/profile/ChangeLanguageForm.php index fa44d26..391687a 100644 --- a/api/models/profile/ChangeLanguageForm.php +++ b/api/models/profile/ChangeLanguageForm.php @@ -31,7 +31,7 @@ class ChangeLanguageForm extends ApiForm { $account = $this->getAccount(); $account->lang = $this->lang; - if (!$account->save()) { + if (!$account->save(false)) { throw new ErrorException('Cannot change user language'); } diff --git a/common/models/Account.php b/common/models/Account.php index 4227e9d..4c94f08 100644 --- a/common/models/Account.php +++ b/common/models/Account.php @@ -3,7 +3,6 @@ namespace common\models; use common\helpers\Error as E; use common\components\UserPass; -use common\validators\LanguageValidator; use Ely\Yii2\TempmailValidator; use Yii; use yii\base\InvalidConfigException; @@ -79,9 +78,6 @@ class Account extends ActiveRecord { [['email'], 'email', 'checkDNS' => true, 'enableIDN' => true, 'message' => E::EMAIL_INVALID], [['email'], TempmailValidator::class, 'message' => E::EMAIL_IS_TEMPMAIL], [['email'], 'unique', 'message' => E::EMAIL_NOT_AVAILABLE], - - [['lang'], LanguageValidator::class], - [['lang'], 'default', 'value' => 'en'], ]; } diff --git a/tests/codeception/api/functional/RegisterCest.php b/tests/codeception/api/functional/RegisterCest.php index 210afb3..4730d8f 100644 --- a/tests/codeception/api/functional/RegisterCest.php +++ b/tests/codeception/api/functional/RegisterCest.php @@ -1,7 +1,6 @@ true, 'lang' => 'ru', ]); + $this->assertSuccessRegistration($I); + } + + public function testUserCorrectRegistrationWithReassignUsername(FunctionalTester $I) { + $route = new SignupRoute($I); + + $I->wantTo('ensure that signup allow reassign not finished registration username'); + $route->register([ + 'username' => 'howe.garnett', + 'email' => 'custom-email@gmail.com', + 'password' => 'some_password', + 'rePassword' => 'some_password', + 'rulesAgreement' => true, + 'lang' => 'ru', + ]); + $this->assertSuccessRegistration($I); + } + + public function testUserCorrectRegistrationWithReassignEmail(FunctionalTester $I) { + $route = new SignupRoute($I); + + $I->wantTo('ensure that signup allow reassign not finished registration email'); + $route->register([ + 'username' => 'CustomUsername', + 'email' => 'achristiansen@gmail.com', + 'password' => 'some_password', + 'rePassword' => 'some_password', + 'rulesAgreement' => true, + 'lang' => 'ru', + ]); + $this->assertSuccessRegistration($I); + } + + private function assertSuccessRegistration(FunctionalTester $I) { $I->canSeeResponseCodeIs(200); $I->canSeeResponseIsJson(); $I->canSeeResponseContainsJson(['success' => true]);