From 45c31dfbbe12f6bec2c783939751838274e09b41 Mon Sep 17 00:00:00 2001 From: ErickSkrauch Date: Mon, 4 Jan 2016 18:31:14 +0300 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=BE=20=D0=BF=D0=BE=D0=BB=D0=B5=20username=20=D0=B2=20?= =?UTF-8?q?=D0=BC=D0=BE=D0=B4=D0=B5=D0=BB=D1=8C=20Account,=20=D1=81=D0=BA?= =?UTF-8?q?=D0=BE=D1=80=D1=80=D0=B5=D1=82=D0=B8=D1=80=D0=BE=D0=B2=D0=B0?= =?UTF-8?q?=D0=BD=D0=B0=20=D1=84=D0=BE=D1=80=D0=BC=D0=B0=20=D0=B2=D1=85?= =?UTF-8?q?=D0=BE=D0=B4=D0=B0=20=D0=B8=20=D0=B5=D1=91=20=D1=82=D0=B5=D1=81?= =?UTF-8?q?=D1=82=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../login/models/AuthenticationForm.php | 26 +++++--- common/models/Account.php | 3 +- .../m160104_150157_account_extended_info.php | 15 +++++ .../unit/fixtures/data/models/accounts.php | 3 +- .../login/models/AuthenticationFormTest.php | 64 ++++++++++++------- 5 files changed, 76 insertions(+), 35 deletions(-) create mode 100644 console/migrations/m160104_150157_account_extended_info.php diff --git a/api/modules/login/models/AuthenticationForm.php b/api/modules/login/models/AuthenticationForm.php index a658042..d27ff95 100644 --- a/api/modules/login/models/AuthenticationForm.php +++ b/api/modules/login/models/AuthenticationForm.php @@ -7,17 +7,16 @@ use yii\base\Model; class AuthenticationForm extends Model { - public $email; + public $login; public $password; public $rememberMe = true; - private $_user; + private $_account; public function rules() { return [ - ['email', 'required', 'message' => 'error.email_required'], - ['email', 'email', 'message' => 'error.email_invalid'], - ['email', 'exist', 'targetClass' => Account::class, 'skipOnError' => true, 'message' => 'error.email_not_exist'], + ['login', 'required', 'message' => 'error.login_required'], + ['login', 'validateLogin'], ['password', 'required', 'when' => function(self $model) { return !$model->hasErrors(); @@ -28,11 +27,19 @@ class AuthenticationForm extends Model { ]; } + public function validateLogin($attribute) { + if (!$this->hasErrors()) { + if (!$this->getAccount()) { + $this->addError($attribute, 'error.' . $attribute . '_not_exist'); + } + } + } + public function validatePassword($attribute) { if (!$this->hasErrors()) { $account = $this->getAccount(); if (!$account || !$account->validatePassword($this->password)) { - $this->addError($attribute, 'error.password_incorrect'); + $this->addError($attribute, 'error.' . $attribute . '_incorrect'); } } } @@ -54,11 +61,12 @@ class AuthenticationForm extends Model { * @return Account|null */ protected function getAccount() { - if ($this->_user === NULL) { - $this->_user = Account::findByEmail($this->email); + if ($this->_account === NULL) { + $attribute = strpos($this->login, '@') ? 'email' : 'username'; + $this->_account = Account::findOne([$attribute => $this->login]); } - return $this->_user; + return $this->_account; } } diff --git a/common/models/Account.php b/common/models/Account.php index c7ed76a..a104452 100644 --- a/common/models/Account.php +++ b/common/models/Account.php @@ -13,10 +13,11 @@ use yii\web\IdentityInterface; * Поля модели: * @property integer $id * @property string $uuid + * @property string $username + * @property string $email * @property string $password_hash * @property integer $password_hash_strategy * @property string $password_reset_token - * @property string $email * @property string $auth_key * @property integer $status * @property integer $created_at diff --git a/console/migrations/m160104_150157_account_extended_info.php b/console/migrations/m160104_150157_account_extended_info.php new file mode 100644 index 0000000..b83b060 --- /dev/null +++ b/console/migrations/m160104_150157_account_extended_info.php @@ -0,0 +1,15 @@ +addColumn('{{%accounts}}', 'username', $this->string()->unique()->notNull() . ' AFTER `uuid`'); + } + + public function safeDown() { + $this->dropColumn('{{%accounts}}', 'username'); + } + +} diff --git a/tests/codeception/api/unit/fixtures/data/models/accounts.php b/tests/codeception/api/unit/fixtures/data/models/accounts.php index b6e70ee..6c702f3 100644 --- a/tests/codeception/api/unit/fixtures/data/models/accounts.php +++ b/tests/codeception/api/unit/fixtures/data/models/accounts.php @@ -3,10 +3,11 @@ return [ [ 'id' => 1, 'uuid' => 'df936908-b2e1-544d-96f8-2977ec213022', + 'username' => 'Admin', + 'email' => 'admin@ely.by', 'password_hash' => '$2y$13$CXT0Rkle1EMJ/c1l5bylL.EylfmQ39O5JlHJVFpNn618OUS1HwaIi', # password_0 'password_hash_strategy' => 1, 'password_reset_token' => NULL, - 'email' => 'admin@ely.by', 'auth_key' => 'iwTNae9t34OmnK6l4vT4IeaTk-YWI2Rv', 'status' => 10, 'created_at' => 1451775316, diff --git a/tests/codeception/api/unit/modules/login/models/AuthenticationFormTest.php b/tests/codeception/api/unit/modules/login/models/AuthenticationFormTest.php index bebc6cd..aceb455 100644 --- a/tests/codeception/api/unit/modules/login/models/AuthenticationFormTest.php +++ b/tests/codeception/api/unit/modules/login/models/AuthenticationFormTest.php @@ -25,60 +25,60 @@ class AuthenticationFormTest extends DbTestCase { ]; } - protected function createModel($email = '', $password = '') { + protected function createModel($login = '', $password = '') { return new AuthenticationForm([ - 'email' => $email, + 'login' => $login, 'password' => $password, ]); } - public function testLoginEmail() { + public function testLoginEmailOrUsername() { $model = $this->createModel(); - $this->specify('error.email_required expected if email is not set', function() use ($model) { + $this->specify('error.login_required expected if login is not set', function() use ($model) { expect($model->login())->false(); - expect($model->getErrors('email'))->equals(['error.email_required']); + expect($model->getErrors('login'))->equals(['error.login_required']); expect(Yii::$app->user->isGuest)->true(); }); - $model = $this->createModel('wrong-email-string'); - $this->specify('error.email_invalid expected if email not correct', function() use ($model) { + $model = $this->createModel('non-exist-username'); + $this->specify('error.login_not_exist expected if username not exists in database', function() use ($model) { expect($model->login())->false(); expect(Yii::$app->user->isGuest)->true(); - expect($model->getErrors('email'))->equals(['error.email_invalid']); - }); - - $model = $this->createModel('wrong@email'); - $this->specify('error.email_invalid expected if email not correct', function() use ($model) { - expect($model->login())->false(); - expect(Yii::$app->user->isGuest)->true(); - expect($model->getErrors('email'))->equals(['error.email_invalid']); + expect($model->getErrors('login'))->equals(['error.login_not_exist']); }); $model = $this->createModel('not-exist@user.com'); - $this->specify('error.email_not_exist expected if email not exists in database', function() use ($model) { + $this->specify('error.login_not_exist expected if email not exists in database', function() use ($model) { expect($model->login())->false(); expect(Yii::$app->user->isGuest)->true(); - expect($model->getErrors('email'))->equals(['error.email_not_exist']); + expect($model->getErrors('login'))->equals(['error.login_not_exist']); + }); + + $model = $this->createModel('Admin'); + $this->specify('no errors on login field if username is correct and exists in database', function() use ($model) { + expect($model->login())->false(); + expect(Yii::$app->user->isGuest)->true(); + expect($model->getErrors('login'))->isEmpty(); }); $model = $this->createModel('admin@ely.by'); - $this->specify('no errors on email field if email is correct and exists in database', function() use ($model) { + $this->specify('no errors on login field if email is correct and exists in database', function() use ($model) { expect($model->login())->false(); expect(Yii::$app->user->isGuest)->true(); - expect($model->getErrors('email'))->isEmpty(); + expect($model->getErrors('login'))->isEmpty(); }); } public function testLoginPassword() { $model = $this->createModel(); - $this->specify('password don\'t has errors if email not set', function() use ($model) { + $this->specify('password don\'t has errors if email or username not set', function() use ($model) { expect($model->login())->false(); expect(Yii::$app->user->isGuest)->true(); expect($model->getErrors('password'))->isEmpty(); }); - $model = $this->createModel('wrong-email-string', 'random-password'); - $this->specify('password don\'t has errors if email invalid', function() use ($model) { + $model = $this->createModel('non-exist-username', 'random-password'); + $this->specify('password don\'t has errors if username not exists in database', function() use ($model) { expect($model->login())->false(); expect(Yii::$app->user->isGuest)->true(); expect($model->getErrors('password'))->isEmpty(); @@ -97,11 +97,27 @@ class AuthenticationFormTest extends DbTestCase { expect(Yii::$app->user->isGuest)->true(); expect($model->getErrors('password'))->equals(['error.password_incorrect']); }); + + $model = $this->createModel('Admin', 'wrong-password'); + $this->specify('error.password_incorrect expected if username correct, but password wrong', function() use ($model) { + expect($model->login())->false(); + expect(Yii::$app->user->isGuest)->true(); + expect($model->getErrors('password'))->equals(['error.password_incorrect']); + }); } - public function testLoginCorrect() { + public function testLoginByUsernameCorrect() { + $model = $this->createModel('Admin', 'password_0'); + $this->specify('user should be able to login with correct username and password', function () use ($model) { + expect('model should login user', $model->login())->true(); + expect('error message should not be set', $model->errors)->isEmpty(); + expect('user should be logged in', Yii::$app->user->isGuest)->false(); + }); + } + + public function testLoginByEmailCorrect() { $model = $this->createModel('admin@ely.by', 'password_0'); - $this->specify('user should be able to login with correct credentials', function () use ($model) { + $this->specify('user should be able to login with correct email and password', function () use ($model) { expect('model should login user', $model->login())->true(); expect('error message should not be set', $model->errors)->isEmpty(); expect('user should be logged in', Yii::$app->user->isGuest)->false();