Упразднён контроллер PasswordProtectedController и заменён на валидатор PasswordRequiredValidator

Реорганизованы тесты для ChangeUsernameFormTest
This commit is contained in:
ErickSkrauch 2016-07-25 14:07:14 +03:00
parent a4dad11be5
commit 31679b84cb
9 changed files with 121 additions and 105 deletions

View File

@ -1,31 +0,0 @@
<?php
namespace api\models\base;
use common\helpers\Error as E;
use Yii;
class PasswordProtectedForm extends ApiForm {
public $password;
public function rules() {
return [
[['password'], 'required', 'message' => E::PASSWORD_REQUIRED],
[['password'], 'validatePassword'],
];
}
public function validatePassword() {
if (!$this->getAccount()->validatePassword($this->password)) {
$this->addError('password', E::PASSWORD_INVALID);
}
}
/**
* @return \common\models\Account
*/
protected function getAccount() {
return Yii::$app->user->identity;
}
}

View File

@ -1,7 +1,8 @@
<?php
namespace api\models\profile\ChangeEmail;
use api\models\base\PasswordProtectedForm;
use api\models\base\ApiForm;
use api\validators\PasswordRequiredValidator;
use common\helpers\Error as E;
use common\models\Account;
use common\models\confirmations\CurrentEmailConfirmation;
@ -11,10 +12,12 @@ use yii\base\ErrorException;
use yii\base\Exception;
use yii\base\InvalidConfigException;
class InitStateForm extends PasswordProtectedForm {
class InitStateForm extends ApiForm {
public $email;
public $password;
private $account;
public function __construct(Account $account, array $config = []) {
@ -28,9 +31,10 @@ class InitStateForm extends PasswordProtectedForm {
}
public function rules() {
return array_merge(parent::rules(), [
return [
['email', 'validateFrequency'],
]);
['password', PasswordRequiredValidator::class, 'account' => $this->account],
];
}
public function validateFrequency($attribute) {
@ -90,7 +94,6 @@ class InitStateForm extends PasswordProtectedForm {
}
public function sendCode(EmailActivation $code) {
/** @var \yii\swiftmailer\Mailer $mailer */
$mailer = Yii::$app->mailer;
$fromEmail = Yii::$app->params['fromEmail'];
if (!$fromEmail) {
@ -98,7 +101,6 @@ class InitStateForm extends PasswordProtectedForm {
}
$acceptor = $code->account;
/** @var \yii\swiftmailer\Message $message */
$message = $mailer->compose([
'html' => '@app/mails/current-email-confirmation-html',
'text' => '@app/mails/current-email-confirmation-text',

View File

@ -1,7 +1,8 @@
<?php
namespace api\models\profile;
use api\models\base\PasswordProtectedForm;
use api\models\base\ApiForm;
use api\validators\PasswordRequiredValidator;
use common\helpers\Error as E;
use common\models\Account;
use common\validators\PasswordValidate;
@ -9,7 +10,7 @@ use Yii;
use yii\base\ErrorException;
use yii\helpers\ArrayHelper;
class ChangePasswordForm extends PasswordProtectedForm {
class ChangePasswordForm extends ApiForm {
public $newPassword;
@ -17,6 +18,8 @@ class ChangePasswordForm extends PasswordProtectedForm {
public $logoutAll;
public $password;
/**
* @var \common\models\Account
*/
@ -37,6 +40,7 @@ class ChangePasswordForm extends PasswordProtectedForm {
['newPassword', PasswordValidate::class],
['newRePassword', 'validatePasswordAndRePasswordMatch'],
['logoutAll', 'boolean'],
['password', PasswordRequiredValidator::class, 'account' => $this->_account],
]);
}
@ -49,7 +53,8 @@ class ChangePasswordForm extends PasswordProtectedForm {
}
/**
* @return boolean
* @return bool
* @throws ErrorException
*/
public function changePassword() : bool {
if (!$this->validate()) {

View File

@ -1,7 +1,9 @@
<?php
namespace api\models\profile;
use api\models\base\PasswordProtectedForm;
use api\models\AccountIdentity;
use api\models\base\ApiForm;
use api\validators\PasswordRequiredValidator;
use common\helpers\Error;
use common\helpers\Amqp;
use common\models\amqp\UsernameChanged;
@ -10,17 +12,19 @@ use Exception;
use PhpAmqpLib\Message\AMQPMessage;
use Yii;
use yii\base\ErrorException;
use yii\helpers\ArrayHelper;
class ChangeUsernameForm extends PasswordProtectedForm {
class ChangeUsernameForm extends ApiForm {
public $username;
public $password;
public function rules() {
return ArrayHelper::merge(parent::rules(), [
return [
['username', 'required', 'message' => Error::USERNAME_REQUIRED],
['username', 'validateUsername'],
]);
['password', PasswordRequiredValidator::class],
];
}
public function validateUsername($attribute) {
@ -84,4 +88,8 @@ class ChangeUsernameForm extends PasswordProtectedForm {
Amqp::sendToEventsExchange('accounts.username-changed', $message);
}
protected function getAccount() : AccountIdentity {
return Yii::$app->user->identity;
}
}

View File

@ -0,0 +1,45 @@
<?php
namespace api\validators;
use common\helpers\Error as E;
use common\models\Account;
use Yii;
use yii\base\InvalidConfigException;
use yii\validators\Validator;
class PasswordRequiredValidator extends Validator {
/**
* @var Account
*/
public $account;
/**
* @inheritdoc
*/
public $skipOnEmpty = false;
public function init() {
parent::init();
if ($this->account === null) {
$this->account = Yii::$app->user->identity;
}
if (!$this->account instanceof Account) {
throw new InvalidConfigException('account should be instance of ' . Account::class);
}
}
protected function validateValue($value) {
if (empty($value)) {
return [E::PASSWORD_REQUIRED, []];
}
if ($this->account->validatePassword($value) === false) {
return [E::PASSWORD_INVALID, []];
}
return null;
}
}

View File

@ -89,7 +89,7 @@ class Account extends ActiveRecord {
* @return bool if password provided is valid for current user
* @throws InvalidConfigException
*/
public function validatePassword($password, $passwordHashStrategy = NULL) {
public function validatePassword($password, $passwordHashStrategy = NULL) : bool {
if ($passwordHashStrategy === NULL) {
$passwordHashStrategy = $this->password_hash_strategy;
}

View File

@ -1,38 +0,0 @@
<?php
namespace tests\codeception\api\models\base;
use api\models\base\PasswordProtectedForm;
use Codeception\Specify;
use common\models\Account;
use tests\codeception\api\unit\TestCase;
class PasswordProtectedFormTest extends TestCase {
use Specify;
public function testValidatePassword() {
$this->specify('error.password_invalid on passing invalid account password', function() {
$model = new DummyBasePasswordProtectedForm();
$model->password = 'some-invalid-password';
$model->validatePassword();
expect($model->getErrors('password'))->equals(['error.password_invalid']);
});
$this->specify('no errors on passing valid account password', function() {
$model = new DummyBasePasswordProtectedForm();
$model->password = 'password_0';
$model->validatePassword();
expect($model->getErrors('password'))->isEmpty();
});
}
}
class DummyBasePasswordProtectedForm extends PasswordProtectedForm {
protected function getAccount() {
return new Account([
'password' => 'password_0',
]);
}
}

View File

@ -1,6 +1,7 @@
<?php
namespace tests\codeception\api\models\profile;
use api\models\AccountIdentity;
use api\models\profile\ChangeUsernameForm;
use Codeception\Specify;
use common\models\Account;
@ -8,6 +9,7 @@ use common\models\UsernameHistory;
use tests\codeception\api\unit\DbTestCase;
use tests\codeception\common\fixtures\AccountFixture;
use tests\codeception\common\fixtures\UsernameHistoryFixture;
use Yii;
/**
* @property AccountFixture $accounts
@ -22,9 +24,15 @@ class ChangeUsernameFormTest extends DbTestCase {
];
}
public function setUp() {
parent::setUp();
$account = AccountIdentity::findOne($this->getAccountId());
Yii::$app->user->setIdentity($account);
}
public function testChange() {
$this->specify('successfully change username to new one', function() {
$model = $this->createModel([
$model = new ChangeUsernameForm([
'password' => 'password_0',
'username' => 'my_new_nickname',
]);
@ -36,7 +44,7 @@ class ChangeUsernameFormTest extends DbTestCase {
public function testChangeWithoutChange() {
$this->specify('no new UsernameHistory record, if we don\'t change nickname', function() {
$model = $this->createModel([
$model = new ChangeUsernameForm([
'password' => 'password_0',
'username' => $this->accounts['admin']['username'],
]);
@ -53,7 +61,7 @@ class ChangeUsernameFormTest extends DbTestCase {
public function testChangeCase() {
$this->specify('username should change, if we change case of some letters', function() {
$newUsername = mb_strtoupper($this->accounts['admin']['username']);
$model = $this->createModel([
$model = new ChangeUsernameForm([
'password' => 'password_0',
'username' => $newUsername,
]);
@ -65,7 +73,7 @@ class ChangeUsernameFormTest extends DbTestCase {
public function testValidateUsername() {
$this->specify('error.username_not_available expected if username is already taken', function() {
$model = $this->createModel([
$model = new ChangeUsernameForm([
'password' => 'password_0',
'username' => 'Jon',
]);
@ -74,7 +82,7 @@ class ChangeUsernameFormTest extends DbTestCase {
});
$this->specify('error.username_not_available is NOT expected if username is already taken by CURRENT user', function() {
$model = $this->createModel([
$model = new ChangeUsernameForm([
'password' => 'password_0',
'username' => $this->accounts['admin']['username'],
]);
@ -84,27 +92,12 @@ class ChangeUsernameFormTest extends DbTestCase {
}
public function testCreateTask() {
$model = $this->createModel();
$model = new ChangeUsernameForm();
$model->createEventTask('1', 'test1', 'test');
// TODO: у меня пока нет идей о том, чтобы это как-то успешно протестировать, увы
// но по крайней мере можно убедиться, что оно не падает где-то на этом шаге
}
private function createModel(array $params = []) : ChangeUsernameForm {
/** @noinspection PhpUnusedLocalVariableInspection */
$params = array_merge($params, [
'accountId' => $this->getAccountId(),
]);
return new class($params) extends ChangeUsernameForm {
public $accountId;
protected function getAccount() {
return Account::findOne($this->accountId);
}
};
}
private function getAccountId() {
return $this->accounts['admin']['id'];
}

View File

@ -0,0 +1,32 @@
<?php
namespace codeception\api\unit\validators;
use api\validators\PasswordRequiredValidator;
use Codeception\Specify;
use common\models\Account;
use tests\codeception\api\unit\DbTestCase;
use tests\codeception\common\_support\ProtectedCaller;
class PasswordRequiredValidatorTest extends DbTestCase {
use Specify;
use ProtectedCaller;
public function testValidateValue() {
$account = new Account(['password' => '12345678']);
$this->specify('get error.password_required if password is empty', function () use ($account) {
$model = new PasswordRequiredValidator(['account' => $account]);
expect($this->callProtected($model, 'validateValue', ''))->equals(['error.password_required', []]);
});
$this->specify('get error.password_invalid if password is incorrect', function () use ($account) {
$model = new PasswordRequiredValidator(['account' => $account]);
expect($this->callProtected($model, 'validateValue', '87654321'))->equals(['error.password_invalid', []]);
});
$this->specify('no errors, if password is correct for provided account', function () use ($account) {
$model = new PasswordRequiredValidator(['account' => $account]);
expect($this->callProtected($model, 'validateValue', '12345678'))->null();
});
}
}