mirror of
https://github.com/elyby/accounts.git
synced 2024-11-08 13:42:30 +05:30
Описана базовая миграция, добавлена модель аккаунта, добавлена модель авторизации, написаны первичные тесты для этой модели, добавлен модуль авторизации, настроен базовый контроллер. Короче много чего сделано
This commit is contained in:
parent
841303b8ab
commit
7b650e2654
@ -13,7 +13,7 @@ return [
|
|||||||
'controllerNamespace' => 'api\controllers',
|
'controllerNamespace' => 'api\controllers',
|
||||||
'components' => [
|
'components' => [
|
||||||
'user' => [
|
'user' => [
|
||||||
'identityClass' => 'common\models\User',
|
'identityClass' => 'common\models\Account',
|
||||||
'enableAutoLogin' => true,
|
'enableAutoLogin' => true,
|
||||||
],
|
],
|
||||||
'log' => [
|
'log' => [
|
||||||
@ -28,6 +28,17 @@ return [
|
|||||||
'errorHandler' => [
|
'errorHandler' => [
|
||||||
'errorAction' => 'site/error',
|
'errorAction' => 'site/error',
|
||||||
],
|
],
|
||||||
|
'request' => [
|
||||||
|
'baseUrl' => '/api',
|
||||||
|
],
|
||||||
|
'urlManager' => [
|
||||||
|
'enablePrettyUrl' => true,
|
||||||
|
'showScriptName' => false,
|
||||||
|
'rules' => [],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'modules' => [
|
||||||
|
'login' => 'api\modules\login\Module',
|
||||||
],
|
],
|
||||||
'params' => $params,
|
'params' => $params,
|
||||||
];
|
];
|
||||||
|
17
api/controllers/Controller.php
Normal file
17
api/controllers/Controller.php
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
namespace api\controllers;
|
||||||
|
|
||||||
|
|
||||||
|
class Controller extends \yii\rest\Controller {
|
||||||
|
|
||||||
|
public $enableCsrfValidation = true;
|
||||||
|
|
||||||
|
public function behaviors() {
|
||||||
|
$parentBehaviors = parent::behaviors();
|
||||||
|
// xml нам не понадобится
|
||||||
|
unset($parentBehaviors['contentNegotiator']['formats']['application/xml']);
|
||||||
|
|
||||||
|
return $parentBehaviors;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,17 +1,17 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace api\controllers;
|
namespace api\controllers;
|
||||||
|
|
||||||
use Yii;
|
use api\models\ContactForm;
|
||||||
use common\models\LoginForm;
|
use api\models\LoginForm;
|
||||||
use api\models\PasswordResetRequestForm;
|
use api\models\PasswordResetRequestForm;
|
||||||
use api\models\ResetPasswordForm;
|
use api\models\ResetPasswordForm;
|
||||||
use api\models\SignupForm;
|
use api\models\SignupForm;
|
||||||
use api\models\ContactForm;
|
use Yii;
|
||||||
use yii\base\InvalidParamException;
|
use yii\base\InvalidParamException;
|
||||||
|
use yii\filters\AccessControl;
|
||||||
|
use yii\filters\VerbFilter;
|
||||||
use yii\web\BadRequestHttpException;
|
use yii\web\BadRequestHttpException;
|
||||||
use yii\web\Controller;
|
use yii\web\Controller;
|
||||||
use yii\filters\VerbFilter;
|
|
||||||
use yii\filters\AccessControl;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Site controller
|
* Site controller
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace common\models;
|
namespace api\models;
|
||||||
|
|
||||||
|
use common\models\Account;
|
||||||
use Yii;
|
use Yii;
|
||||||
use yii\base\Model;
|
use yii\base\Model;
|
||||||
|
|
||||||
@ -65,12 +66,12 @@ class LoginForm extends Model
|
|||||||
/**
|
/**
|
||||||
* Finds user by [[username]]
|
* Finds user by [[username]]
|
||||||
*
|
*
|
||||||
* @return User|null
|
* @return Account|null
|
||||||
*/
|
*/
|
||||||
protected function getUser()
|
protected function getUser()
|
||||||
{
|
{
|
||||||
if ($this->_user === null) {
|
if ($this->_user === null) {
|
||||||
$this->_user = User::findByUsername($this->username);
|
$this->_user = Account::findByEmail($this->username);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->_user;
|
return $this->_user;
|
@ -1,7 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace api\models;
|
namespace api\models;
|
||||||
|
|
||||||
use common\models\User;
|
use common\models\Account;
|
||||||
use yii\base\Model;
|
use yii\base\Model;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -22,7 +22,7 @@ class PasswordResetRequestForm extends Model
|
|||||||
['email', 'email'],
|
['email', 'email'],
|
||||||
['email', 'exist',
|
['email', 'exist',
|
||||||
'targetClass' => '\common\models\User',
|
'targetClass' => '\common\models\User',
|
||||||
'filter' => ['status' => User::STATUS_ACTIVE],
|
'filter' => ['status' => Account::STATUS_ACTIVE],
|
||||||
'message' => 'There is no user with such email.'
|
'message' => 'There is no user with such email.'
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
@ -35,14 +35,14 @@ class PasswordResetRequestForm extends Model
|
|||||||
*/
|
*/
|
||||||
public function sendEmail()
|
public function sendEmail()
|
||||||
{
|
{
|
||||||
/* @var $user User */
|
/* @var $user Account */
|
||||||
$user = User::findOne([
|
$user = Account::findOne([
|
||||||
'status' => User::STATUS_ACTIVE,
|
'status' => Account::STATUS_ACTIVE,
|
||||||
'email' => $this->email,
|
'email' => $this->email,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if ($user) {
|
if ($user) {
|
||||||
if (!User::isPasswordResetTokenValid($user->password_reset_token)) {
|
if (!Account::isPasswordResetTokenValid($user->password_reset_token)) {
|
||||||
$user->generatePasswordResetToken();
|
$user->generatePasswordResetToken();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace api\models;
|
namespace api\models;
|
||||||
|
|
||||||
use common\models\User;
|
use common\models\Account;
|
||||||
use yii\base\InvalidParamException;
|
use yii\base\InvalidParamException;
|
||||||
use yii\base\Model;
|
use yii\base\Model;
|
||||||
use Yii;
|
use Yii;
|
||||||
@ -14,7 +14,7 @@ class ResetPasswordForm extends Model
|
|||||||
public $password;
|
public $password;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var \common\models\User
|
* @var \common\models\Account
|
||||||
*/
|
*/
|
||||||
private $_user;
|
private $_user;
|
||||||
|
|
||||||
@ -31,7 +31,7 @@ class ResetPasswordForm extends Model
|
|||||||
if (empty($token) || !is_string($token)) {
|
if (empty($token) || !is_string($token)) {
|
||||||
throw new InvalidParamException('Password reset token cannot be blank.');
|
throw new InvalidParamException('Password reset token cannot be blank.');
|
||||||
}
|
}
|
||||||
$this->_user = User::findByPasswordResetToken($token);
|
$this->_user = Account::findByPasswordResetToken($token);
|
||||||
if (!$this->_user) {
|
if (!$this->_user) {
|
||||||
throw new InvalidParamException('Wrong password reset token.');
|
throw new InvalidParamException('Wrong password reset token.');
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace api\models;
|
namespace api\models;
|
||||||
|
|
||||||
use common\models\User;
|
use common\models\Account;
|
||||||
use yii\base\Model;
|
use yii\base\Model;
|
||||||
use Yii;
|
use Yii;
|
||||||
|
|
||||||
@ -39,13 +39,12 @@ class SignupForm extends Model
|
|||||||
/**
|
/**
|
||||||
* Signs user up.
|
* Signs user up.
|
||||||
*
|
*
|
||||||
* @return User|null the saved model or null if saving fails
|
* @return Account|null the saved model or null if saving fails
|
||||||
*/
|
*/
|
||||||
public function signup()
|
public function signup()
|
||||||
{
|
{
|
||||||
if ($this->validate()) {
|
if ($this->validate()) {
|
||||||
$user = new User();
|
$user = new Account();
|
||||||
$user->username = $this->username;
|
|
||||||
$user->email = $this->email;
|
$user->email = $this->email;
|
||||||
$user->setPassword($this->password);
|
$user->setPassword($this->password);
|
||||||
$user->generateAuthKey();
|
$user->generateAuthKey();
|
||||||
|
9
api/modules/login/Module.php
Normal file
9
api/modules/login/Module.php
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
namespace api\modules\login;
|
||||||
|
|
||||||
|
|
||||||
|
class Module extends \yii\base\Module {
|
||||||
|
|
||||||
|
public $id = 'login';
|
||||||
|
|
||||||
|
}
|
48
api/modules/login/controllers/AuthenticationController.php
Normal file
48
api/modules/login/controllers/AuthenticationController.php
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
namespace api\modules\login\controllers;
|
||||||
|
|
||||||
|
use api\controllers\Controller;
|
||||||
|
use api\modules\login\models\AuthenticationForm;
|
||||||
|
use Yii;
|
||||||
|
use yii\filters\AccessControl;
|
||||||
|
|
||||||
|
class AuthenticationController extends Controller {
|
||||||
|
|
||||||
|
public function behaviors() {
|
||||||
|
return array_merge(parent::behaviors(), [
|
||||||
|
'access' => [
|
||||||
|
'class' => AccessControl::className(),
|
||||||
|
'only' => ['login-info'],
|
||||||
|
'rules' => [
|
||||||
|
[
|
||||||
|
'actions' => ['login-info'],
|
||||||
|
'allow' => true,
|
||||||
|
'roles' => ['?'],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function verbs() {
|
||||||
|
return [
|
||||||
|
'loginInfo' => ['post'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function actionLoginInfo() {
|
||||||
|
$model = new AuthenticationForm();
|
||||||
|
$model->load(Yii::$app->request->post());
|
||||||
|
if (!$model->login()) {
|
||||||
|
return [
|
||||||
|
'success' => false,
|
||||||
|
'errors' => $model->getErrors(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'success' => true,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
12
api/modules/login/controllers/DefaultController.php
Normal file
12
api/modules/login/controllers/DefaultController.php
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
namespace api\modules\login\controllers;
|
||||||
|
|
||||||
|
use api\controllers\Controller;
|
||||||
|
|
||||||
|
class DefaultController extends Controller {
|
||||||
|
|
||||||
|
public function actionIndex() {
|
||||||
|
return ['hello' => 'world'];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
0
api/modules/login/models/.gitkeep
Normal file
0
api/modules/login/models/.gitkeep
Normal file
70
api/modules/login/models/AuthenticationForm.php
Normal file
70
api/modules/login/models/AuthenticationForm.php
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
<?php
|
||||||
|
namespace api\modules\login\models;
|
||||||
|
|
||||||
|
use common\models\Account;
|
||||||
|
use Yii;
|
||||||
|
use yii\base\Model;
|
||||||
|
|
||||||
|
class AuthenticationForm extends Model {
|
||||||
|
|
||||||
|
public $email;
|
||||||
|
public $password;
|
||||||
|
public $rememberMe = true;
|
||||||
|
|
||||||
|
private $_user;
|
||||||
|
|
||||||
|
public function rules() {
|
||||||
|
return [
|
||||||
|
['email', 'required', 'message' => 'error.email_required'],
|
||||||
|
['email', 'email', 'message' => 'error.email_invalid'],
|
||||||
|
['email', 'validateEmail'],
|
||||||
|
|
||||||
|
['password', 'required', 'message' => 'error.password_required'],
|
||||||
|
['password', 'validatePassword'],
|
||||||
|
|
||||||
|
['rememberMe', 'boolean'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function validateEmail($attribute) {
|
||||||
|
if (!$this->hasErrors()) {
|
||||||
|
if ($this->getAccount() === NULL) {
|
||||||
|
$this->addError($attribute, 'error.email_not_exist');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function validatePassword($attribute) {
|
||||||
|
if (!$this->hasErrors()) {
|
||||||
|
$account = $this->getAccount();
|
||||||
|
if (!$account || !$account->validatePassword($this->password)) {
|
||||||
|
$this->addError($attribute, 'error.password_incorrect');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs in a user using the provided username and password.
|
||||||
|
*
|
||||||
|
* @return boolean whether the user is logged in successfully
|
||||||
|
*/
|
||||||
|
public function login() {
|
||||||
|
if (!$this->validate()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Yii::$app->user->login($this->getAccount(), $this->rememberMe ? 3600 * 24 * 30 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Account|null
|
||||||
|
*/
|
||||||
|
protected function getAccount() {
|
||||||
|
if ($this->_user === NULL) {
|
||||||
|
$this->_user = Account::findByEmail($this->email);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->_user;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -34,17 +34,17 @@ AppAsset::register($this);
|
|||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
$menuItems = [
|
$menuItems = [
|
||||||
['label' => 'Home', 'url' => ['/site/index']],
|
['label' => 'Home', 'url' => ['site/index']],
|
||||||
['label' => 'About', 'url' => ['/site/about']],
|
['label' => 'About', 'url' => ['site/about']],
|
||||||
['label' => 'Contact', 'url' => ['/site/contact']],
|
['label' => 'Contact', 'url' => ['site/contact']],
|
||||||
];
|
];
|
||||||
if (Yii::$app->user->isGuest) {
|
if (Yii::$app->user->isGuest) {
|
||||||
$menuItems[] = ['label' => 'Signup', 'url' => ['/site/signup']];
|
$menuItems[] = ['label' => 'Signup', 'url' => ['site/signup']];
|
||||||
$menuItems[] = ['label' => 'Login', 'url' => ['/site/login']];
|
$menuItems[] = ['label' => 'Login', 'url' => ['site/login']];
|
||||||
} else {
|
} else {
|
||||||
$menuItems[] = [
|
$menuItems[] = [
|
||||||
'label' => 'Logout (' . Yii::$app->user->identity->username . ')',
|
'label' => 'Logout (' . Yii::$app->user->identity->username . ')',
|
||||||
'url' => ['/site/logout'],
|
'url' => ['site/logout'],
|
||||||
'linkOptions' => ['data-method' => 'post']
|
'linkOptions' => ['data-method' => 'post']
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -2,10 +2,10 @@
|
|||||||
|
|
||||||
/* @var $this yii\web\View */
|
/* @var $this yii\web\View */
|
||||||
/* @var $form yii\bootstrap\ActiveForm */
|
/* @var $form yii\bootstrap\ActiveForm */
|
||||||
/* @var $model \common\models\LoginForm */
|
/* @var $model \api\models\LoginForm */
|
||||||
|
|
||||||
use yii\helpers\Html;
|
|
||||||
use yii\bootstrap\ActiveForm;
|
use yii\bootstrap\ActiveForm;
|
||||||
|
use yii\helpers\Html;
|
||||||
|
|
||||||
$this->title = 'Login';
|
$this->title = 'Login';
|
||||||
$this->params['breadcrumbs'][] = $this->title;
|
$this->params['breadcrumbs'][] = $this->title;
|
||||||
|
15
common/components/UserPass.php
Normal file
15
common/components/UserPass.php
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
namespace api\components;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Этот класс был использован для изначальной генерации паролей на Ely.by и сейчас должен быть планомерно выпилен
|
||||||
|
* с проекта с целью заменить этот алгоритм каким-нибудь посерьёзнее.
|
||||||
|
*/
|
||||||
|
class UserPass {
|
||||||
|
|
||||||
|
public static function make ($email, $pass) {
|
||||||
|
return md5($pass . md5(strtolower($email)));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -13,5 +13,8 @@ return [
|
|||||||
'class' => 'yii\swiftmailer\Mailer',
|
'class' => 'yii\swiftmailer\Mailer',
|
||||||
'viewPath' => '@common/mail',
|
'viewPath' => '@common/mail',
|
||||||
],
|
],
|
||||||
|
'security' => [
|
||||||
|
'passwordHashStrategy' => 'password_hash',
|
||||||
|
]
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
@ -2,12 +2,12 @@
|
|||||||
use yii\helpers\Html;
|
use yii\helpers\Html;
|
||||||
|
|
||||||
/* @var $this yii\web\View */
|
/* @var $this yii\web\View */
|
||||||
/* @var $user common\models\User */
|
/* @var $user common\models\Account */
|
||||||
|
|
||||||
$resetLink = Yii::$app->urlManager->createAbsoluteUrl(['site/reset-password', 'token' => $user->password_reset_token]);
|
$resetLink = Yii::$app->urlManager->createAbsoluteUrl(['site/reset-password', 'token' => $user->password_reset_token]);
|
||||||
?>
|
?>
|
||||||
<div class="password-reset">
|
<div class="password-reset">
|
||||||
<p>Hello <?= Html::encode($user->username) ?>,</p>
|
<p>Hello <?= Html::encode($user->email) ?>,</p>
|
||||||
|
|
||||||
<p>Follow the link below to reset your password:</p>
|
<p>Follow the link below to reset your password:</p>
|
||||||
|
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/* @var $this yii\web\View */
|
/* @var $this yii\web\View */
|
||||||
/* @var $user common\models\User */
|
/* @var $user common\models\Account */
|
||||||
|
|
||||||
$resetLink = Yii::$app->urlManager->createAbsoluteUrl(['site/reset-password', 'token' => $user->password_reset_token]);
|
$resetLink = Yii::$app->urlManager->createAbsoluteUrl(['site/reset-password', 'token' => $user->password_reset_token]);
|
||||||
?>
|
?>
|
||||||
Hello <?= $user->username ?>,
|
Hello <?= $user->email ?>,
|
||||||
|
|
||||||
Follow the link below to reset your password:
|
Follow the link below to reset your password:
|
||||||
|
|
||||||
|
208
common/models/Account.php
Normal file
208
common/models/Account.php
Normal file
@ -0,0 +1,208 @@
|
|||||||
|
<?php
|
||||||
|
namespace common\models;
|
||||||
|
|
||||||
|
use api\components\UserPass;
|
||||||
|
use Yii;
|
||||||
|
use yii\base\InvalidConfigException;
|
||||||
|
use yii\base\NotSupportedException;
|
||||||
|
use yii\behaviors\TimestampBehavior;
|
||||||
|
use yii\db\ActiveRecord;
|
||||||
|
use yii\web\IdentityInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Поля модели:
|
||||||
|
* @property integer $id
|
||||||
|
* @property string $uuid
|
||||||
|
* @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
|
||||||
|
* @property integer $updated_at
|
||||||
|
*
|
||||||
|
* Геттеры-сеттеры:
|
||||||
|
* @property string $password пароль пользователя (только для записи)
|
||||||
|
*/
|
||||||
|
class Account extends ActiveRecord implements IdentityInterface {
|
||||||
|
|
||||||
|
const STATUS_DELETED = -10;
|
||||||
|
const STATUS_REGISTERED = 0;
|
||||||
|
const STATUS_ACTIVE = 10;
|
||||||
|
|
||||||
|
const PASS_HASH_STRATEGY_OLD_ELY = 0;
|
||||||
|
const PASS_HASH_STRATEGY_YII2 = 1;
|
||||||
|
|
||||||
|
public static function tableName() {
|
||||||
|
return '{{%accounts}}';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function behaviors() {
|
||||||
|
return [
|
||||||
|
TimestampBehavior::className(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rules() {
|
||||||
|
return [
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
public static function findIdentity($id) {
|
||||||
|
return static::findOne(['id' => $id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
public static function findIdentityByAccessToken($token, $type = null) {
|
||||||
|
throw new NotSupportedException('"findIdentityByAccessToken" is not implemented.');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $email
|
||||||
|
* @return static|null
|
||||||
|
*/
|
||||||
|
public static function findByEmail($email) {
|
||||||
|
return static::findOne(['email' => $email]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds user by password reset token
|
||||||
|
*
|
||||||
|
* @param string $token password reset token
|
||||||
|
*
|
||||||
|
* @return static|null
|
||||||
|
*
|
||||||
|
* TODO: этот метод нужно убрать из базовой модели
|
||||||
|
*/
|
||||||
|
public static function findByPasswordResetToken($token) {
|
||||||
|
if (!static::isPasswordResetTokenValid($token)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return static::findOne([
|
||||||
|
'password_reset_token' => $token,
|
||||||
|
'status' => self::STATUS_ACTIVE,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds out if password reset token is valid
|
||||||
|
*
|
||||||
|
* @param string $token password reset token
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*
|
||||||
|
* TODO: этот метод нужно убрать из базовой модели
|
||||||
|
*/
|
||||||
|
public static function isPasswordResetTokenValid($token) {
|
||||||
|
if (empty($token)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$timestamp = (int) substr($token, strrpos($token, '_') + 1);
|
||||||
|
$expire = Yii::$app->params['user.passwordResetTokenExpire'];
|
||||||
|
|
||||||
|
return $timestamp + $expire >= time();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
public function getId() {
|
||||||
|
return $this->getPrimaryKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
public function getAuthKey() {
|
||||||
|
return $this->auth_key;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
public function validateAuthKey($authKey) {
|
||||||
|
return $this->getAuthKey() === $authKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates password
|
||||||
|
*
|
||||||
|
* @param string $password password to validate
|
||||||
|
* @param integer $passwordHashStrategy
|
||||||
|
*
|
||||||
|
* @return bool if password provided is valid for current user
|
||||||
|
* @throws InvalidConfigException
|
||||||
|
*/
|
||||||
|
public function validatePassword($password, $passwordHashStrategy = NULL) {
|
||||||
|
if ($passwordHashStrategy === NULL) {
|
||||||
|
$passwordHashStrategy = $this->password_hash_strategy;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch($passwordHashStrategy) {
|
||||||
|
case self::PASS_HASH_STRATEGY_OLD_ELY:
|
||||||
|
$hashedPass = UserPass::make($this->email, $password);
|
||||||
|
return $hashedPass === $this->password_hash;
|
||||||
|
|
||||||
|
case self::PASS_HASH_STRATEGY_YII2:
|
||||||
|
return Yii::$app->security->validatePassword($password, $this->password_hash);
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new InvalidConfigException('You must set valid password_hash_strategy before you can validate password');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $password
|
||||||
|
* @throws InvalidConfigException
|
||||||
|
*/
|
||||||
|
public function setPassword($password) {
|
||||||
|
switch($this->password_hash_strategy) {
|
||||||
|
case self::PASS_HASH_STRATEGY_OLD_ELY:
|
||||||
|
$password = UserPass::make($this->email, $password);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case self::PASS_HASH_STRATEGY_YII2:
|
||||||
|
$password = Yii::$app->security->generatePasswordHash($password);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new InvalidConfigException('You must specify password_hash_strategy before you can set password');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->password_hash = $password;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates "remember me" authentication key
|
||||||
|
*/
|
||||||
|
public function generateAuthKey() {
|
||||||
|
$this->auth_key = Yii::$app->security->generateRandomString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates new password reset token
|
||||||
|
*
|
||||||
|
* TODO: этот метод нужно отсюда убрать
|
||||||
|
*/
|
||||||
|
public function generatePasswordResetToken() {
|
||||||
|
$this->password_reset_token = Yii::$app->security->generateRandomString() . '_' . time();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes password reset token
|
||||||
|
*
|
||||||
|
* TODO: этот метод нужно отсюда убрать
|
||||||
|
*/
|
||||||
|
public function removePasswordResetToken() {
|
||||||
|
$this->password_reset_token = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,188 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace common\models;
|
|
||||||
|
|
||||||
use Yii;
|
|
||||||
use yii\base\NotSupportedException;
|
|
||||||
use yii\behaviors\TimestampBehavior;
|
|
||||||
use yii\db\ActiveRecord;
|
|
||||||
use yii\web\IdentityInterface;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* User model
|
|
||||||
*
|
|
||||||
* @property integer $id
|
|
||||||
* @property string $username
|
|
||||||
* @property string $password_hash
|
|
||||||
* @property string $password_reset_token
|
|
||||||
* @property string $email
|
|
||||||
* @property string $auth_key
|
|
||||||
* @property integer $status
|
|
||||||
* @property integer $created_at
|
|
||||||
* @property integer $updated_at
|
|
||||||
* @property string $password write-only password
|
|
||||||
*/
|
|
||||||
class User extends ActiveRecord implements IdentityInterface
|
|
||||||
{
|
|
||||||
const STATUS_DELETED = 0;
|
|
||||||
const STATUS_ACTIVE = 10;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritdoc
|
|
||||||
*/
|
|
||||||
public static function tableName()
|
|
||||||
{
|
|
||||||
return '{{%user}}';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritdoc
|
|
||||||
*/
|
|
||||||
public function behaviors()
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
TimestampBehavior::className(),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritdoc
|
|
||||||
*/
|
|
||||||
public function rules()
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
['status', 'default', 'value' => self::STATUS_ACTIVE],
|
|
||||||
['status', 'in', 'range' => [self::STATUS_ACTIVE, self::STATUS_DELETED]],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritdoc
|
|
||||||
*/
|
|
||||||
public static function findIdentity($id)
|
|
||||||
{
|
|
||||||
return static::findOne(['id' => $id, 'status' => self::STATUS_ACTIVE]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritdoc
|
|
||||||
*/
|
|
||||||
public static function findIdentityByAccessToken($token, $type = null)
|
|
||||||
{
|
|
||||||
throw new NotSupportedException('"findIdentityByAccessToken" is not implemented.');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Finds user by username
|
|
||||||
*
|
|
||||||
* @param string $username
|
|
||||||
* @return static|null
|
|
||||||
*/
|
|
||||||
public static function findByUsername($username)
|
|
||||||
{
|
|
||||||
return static::findOne(['username' => $username, 'status' => self::STATUS_ACTIVE]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Finds user by password reset token
|
|
||||||
*
|
|
||||||
* @param string $token password reset token
|
|
||||||
* @return static|null
|
|
||||||
*/
|
|
||||||
public static function findByPasswordResetToken($token)
|
|
||||||
{
|
|
||||||
if (!static::isPasswordResetTokenValid($token)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return static::findOne([
|
|
||||||
'password_reset_token' => $token,
|
|
||||||
'status' => self::STATUS_ACTIVE,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Finds out if password reset token is valid
|
|
||||||
*
|
|
||||||
* @param string $token password reset token
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
public static function isPasswordResetTokenValid($token)
|
|
||||||
{
|
|
||||||
if (empty($token)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$timestamp = (int) substr($token, strrpos($token, '_') + 1);
|
|
||||||
$expire = Yii::$app->params['user.passwordResetTokenExpire'];
|
|
||||||
return $timestamp + $expire >= time();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritdoc
|
|
||||||
*/
|
|
||||||
public function getId()
|
|
||||||
{
|
|
||||||
return $this->getPrimaryKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritdoc
|
|
||||||
*/
|
|
||||||
public function getAuthKey()
|
|
||||||
{
|
|
||||||
return $this->auth_key;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritdoc
|
|
||||||
*/
|
|
||||||
public function validateAuthKey($authKey)
|
|
||||||
{
|
|
||||||
return $this->getAuthKey() === $authKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates password
|
|
||||||
*
|
|
||||||
* @param string $password password to validate
|
|
||||||
* @return boolean if password provided is valid for current user
|
|
||||||
*/
|
|
||||||
public function validatePassword($password)
|
|
||||||
{
|
|
||||||
return Yii::$app->security->validatePassword($password, $this->password_hash);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates password hash from password and sets it to the model
|
|
||||||
*
|
|
||||||
* @param string $password
|
|
||||||
*/
|
|
||||||
public function setPassword($password)
|
|
||||||
{
|
|
||||||
$this->password_hash = Yii::$app->security->generatePasswordHash($password);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates "remember me" authentication key
|
|
||||||
*/
|
|
||||||
public function generateAuthKey()
|
|
||||||
{
|
|
||||||
$this->auth_key = Yii::$app->security->generateRandomString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates new password reset token
|
|
||||||
*/
|
|
||||||
public function generatePasswordResetToken()
|
|
||||||
{
|
|
||||||
$this->password_reset_token = Yii::$app->security->generateRandomString() . '_' . time();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes password reset token
|
|
||||||
*/
|
|
||||||
public function removePasswordResetToken()
|
|
||||||
{
|
|
||||||
$this->password_reset_token = null;
|
|
||||||
}
|
|
||||||
}
|
|
@ -17,7 +17,8 @@
|
|||||||
"php": ">=5.4.0",
|
"php": ">=5.4.0",
|
||||||
"yiisoft/yii2": ">=2.0.6",
|
"yiisoft/yii2": ">=2.0.6",
|
||||||
"yiisoft/yii2-bootstrap": "*",
|
"yiisoft/yii2-bootstrap": "*",
|
||||||
"yiisoft/yii2-swiftmailer": "*"
|
"yiisoft/yii2-swiftmailer": "*",
|
||||||
|
"ramsey/uuid": "^3.1"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"yiisoft/yii2-codeception": "*",
|
"yiisoft/yii2-codeception": "*",
|
||||||
|
@ -21,5 +21,11 @@ return [
|
|||||||
],
|
],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
'controllerMap' => [
|
||||||
|
'migrate' => [
|
||||||
|
'class' => 'yii\console\controllers\MigrateController',
|
||||||
|
'templateFile' => '@console/views/migration.php',
|
||||||
|
],
|
||||||
|
],
|
||||||
'params' => $params,
|
'params' => $params,
|
||||||
];
|
];
|
||||||
|
21
console/db/Migration.php
Normal file
21
console/db/Migration.php
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
namespace console\db;
|
||||||
|
|
||||||
|
use yii\db\Migration as YiiMigration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property string $tableOptions
|
||||||
|
*/
|
||||||
|
class Migration extends YiiMigration {
|
||||||
|
|
||||||
|
public function getTableOptions($engine = 'InnoDB') {
|
||||||
|
$tableOptions = null;
|
||||||
|
if ($this->db->driverName === 'mysql') {
|
||||||
|
// http://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci
|
||||||
|
$tableOptions = 'CHARACTER SET utf8 COLLATE utf8_general_ci ENGINE=' . $engine;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $tableOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,34 +1,26 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
use yii\db\Schema;
|
use console\db\Migration;
|
||||||
use yii\db\Migration;
|
|
||||||
|
|
||||||
class m130524_201442_init extends Migration
|
class m130524_201442_init extends Migration {
|
||||||
{
|
|
||||||
public function up()
|
|
||||||
{
|
|
||||||
$tableOptions = null;
|
|
||||||
if ($this->db->driverName === 'mysql') {
|
|
||||||
// http://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci
|
|
||||||
$tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB';
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->createTable('{{%user}}', [
|
public function up() {
|
||||||
|
$this->createTable('{{%accounts}}', [
|
||||||
'id' => $this->primaryKey(),
|
'id' => $this->primaryKey(),
|
||||||
'username' => $this->string()->notNull()->unique(),
|
'uuid' => $this->string(36)->notNull(),
|
||||||
'auth_key' => $this->string(32)->notNull(),
|
|
||||||
'password_hash' => $this->string()->notNull(),
|
|
||||||
'password_reset_token' => $this->string()->unique(),
|
|
||||||
'email' => $this->string()->notNull()->unique(),
|
'email' => $this->string()->notNull()->unique(),
|
||||||
|
'password_hash' => $this->string()->notNull(),
|
||||||
'status' => $this->smallInteger()->notNull()->defaultValue(10),
|
'password_hash_strategy' => $this->smallInteger()->notNull(),
|
||||||
|
'password_reset_token' => $this->string()->unique(),
|
||||||
|
'status' => $this->smallInteger()->notNull()->defaultValue(0),
|
||||||
|
'auth_key' => $this->string(32)->notNull(),
|
||||||
'created_at' => $this->integer()->notNull(),
|
'created_at' => $this->integer()->notNull(),
|
||||||
'updated_at' => $this->integer()->notNull(),
|
'updated_at' => $this->integer()->notNull(),
|
||||||
], $tableOptions);
|
], $this->tableOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function down()
|
public function down() {
|
||||||
{
|
$this->dropTable('{{%accounts}}');
|
||||||
$this->dropTable('{{%user}}');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
19
console/views/migration.php
Normal file
19
console/views/migration.php
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
/* @var $className string the new migration class name */
|
||||||
|
|
||||||
|
echo "<?php\n";
|
||||||
|
?>
|
||||||
|
|
||||||
|
use console\db\Migration;
|
||||||
|
|
||||||
|
class <?= $className ?> extends Migration {
|
||||||
|
|
||||||
|
public function safeUp() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function safeDown() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
21
tests/codeception/api/_pages/LoginRoute.php
Normal file
21
tests/codeception/api/_pages/LoginRoute.php
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
namespace tests\codeception\api\_pages;
|
||||||
|
|
||||||
|
use yii\codeception\BasePage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents loging page
|
||||||
|
* @property \tests\codeception\api\FunctionalTester $actor
|
||||||
|
*/
|
||||||
|
class LoginRoute extends BasePage {
|
||||||
|
|
||||||
|
public $route = 'login/authentication/login-info';
|
||||||
|
|
||||||
|
public function login($email, $password) {
|
||||||
|
$this->actor->sendPOST($this->getUrl(), [
|
||||||
|
'email' => $email,
|
||||||
|
'password' => $password,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,13 +1,13 @@
|
|||||||
<?php
|
<?php
|
||||||
|
use tests\codeception\api\_pages\LoginRoute;
|
||||||
use tests\codeception\api\AcceptanceTester;
|
use tests\codeception\api\AcceptanceTester;
|
||||||
use tests\codeception\common\_pages\LoginPage;
|
|
||||||
|
|
||||||
/* @var $scenario Codeception\Scenario */
|
/* @var $scenario Codeception\Scenario */
|
||||||
|
|
||||||
$I = new AcceptanceTester($scenario);
|
$I = new AcceptanceTester($scenario);
|
||||||
$I->wantTo('ensure login page works');
|
$I->wantTo('ensure login page works');
|
||||||
|
|
||||||
$loginPage = LoginPage::openBy($I);
|
$loginPage = LoginRoute::openBy($I);
|
||||||
|
|
||||||
$I->amGoingTo('submit login form with no data');
|
$I->amGoingTo('submit login form with no data');
|
||||||
$loginPage->login('', '');
|
$loginPage->login('', '');
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
namespace tests\codeception\api\acceptance;
|
namespace tests\codeception\api\acceptance;
|
||||||
|
|
||||||
use tests\codeception\api\_pages\SignupPage;
|
use tests\codeception\api\_pages\SignupPage;
|
||||||
use common\models\User;
|
use common\models\Account;
|
||||||
|
|
||||||
class SignupCest
|
class SignupCest
|
||||||
{
|
{
|
||||||
@ -22,7 +22,7 @@ class SignupCest
|
|||||||
*/
|
*/
|
||||||
public function _after($event)
|
public function _after($event)
|
||||||
{
|
{
|
||||||
User::deleteAll([
|
Account::deleteAll([
|
||||||
'email' => 'tester.email@example.com',
|
'email' => 'tester.email@example.com',
|
||||||
'username' => 'tester',
|
'username' => 'tester',
|
||||||
]);
|
]);
|
||||||
|
@ -12,6 +12,7 @@ modules:
|
|||||||
- Filesystem
|
- Filesystem
|
||||||
- Yii2
|
- Yii2
|
||||||
- tests\codeception\common\_support\FixtureHelper
|
- tests\codeception\common\_support\FixtureHelper
|
||||||
|
- REST
|
||||||
config:
|
config:
|
||||||
Yii2:
|
Yii2:
|
||||||
configFile: '../config/api/functional.php'
|
configFile: '../config/api/functional.php'
|
||||||
|
@ -1,23 +1,33 @@
|
|||||||
<?php
|
<?php
|
||||||
|
use tests\codeception\api\_pages\LoginRoute;
|
||||||
use tests\codeception\api\FunctionalTester;
|
use tests\codeception\api\FunctionalTester;
|
||||||
use tests\codeception\common\_pages\LoginPage;
|
|
||||||
|
|
||||||
/* @var $scenario Codeception\Scenario */
|
/* @var $scenario Codeception\Scenario */
|
||||||
|
|
||||||
$I = new FunctionalTester($scenario);
|
$I = new FunctionalTester($scenario);
|
||||||
$I->wantTo('ensure login page works');
|
$I->wantTo('ensure login page works');
|
||||||
|
|
||||||
$loginPage = LoginPage::openBy($I);
|
$loginPage = LoginRoute::openBy($I);
|
||||||
|
|
||||||
$I->amGoingTo('submit login form with no data');
|
$I->amGoingTo('submit login form with no data');
|
||||||
$loginPage->login('', '');
|
$loginPage->login('', '');
|
||||||
$I->expectTo('see validations errors');
|
$I->expectTo('see validations errors');
|
||||||
$I->see('Username cannot be blank.', '.help-block');
|
$I->canSeeResponseContainsJson([
|
||||||
$I->see('Password cannot be blank.', '.help-block');
|
'success' => false,
|
||||||
|
'errors' => [
|
||||||
|
'email' => [
|
||||||
|
'error.email_required',
|
||||||
|
],
|
||||||
|
'password' => [
|
||||||
|
'error.password_required',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
/*
|
||||||
$I->amGoingTo('try to login with wrong credentials');
|
$I->amGoingTo('try to login with wrong credentials');
|
||||||
$I->expectTo('see validations errors');
|
$I->expectTo('see validations errors');
|
||||||
$loginPage->login('admin', 'wrong');
|
$loginPage->login('', 'wrong');
|
||||||
$I->expectTo('see validations errors');
|
$I->expectTo('see validations errors');
|
||||||
$I->see('Incorrect username or password.', '.help-block');
|
$I->see('Incorrect username or password.', '.help-block');
|
||||||
|
|
||||||
@ -27,3 +37,4 @@ $I->expectTo('see that user is logged');
|
|||||||
$I->seeLink('Logout (erau)');
|
$I->seeLink('Logout (erau)');
|
||||||
$I->dontSeeLink('Login');
|
$I->dontSeeLink('Login');
|
||||||
$I->dontSeeLink('Signup');
|
$I->dontSeeLink('Signup');
|
||||||
|
*/
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
namespace tests\codeception\api\functional;
|
namespace tests\codeception\api\functional;
|
||||||
|
|
||||||
use tests\codeception\api\_pages\SignupPage;
|
use tests\codeception\api\_pages\SignupPage;
|
||||||
use common\models\User;
|
use common\models\Account;
|
||||||
|
|
||||||
class SignupCest
|
class SignupCest
|
||||||
{
|
{
|
||||||
@ -22,7 +22,7 @@ class SignupCest
|
|||||||
*/
|
*/
|
||||||
public function _after($event)
|
public function _after($event)
|
||||||
{
|
{
|
||||||
User::deleteAll([
|
Account::deleteAll([
|
||||||
'email' => 'tester.email@example.com',
|
'email' => 'tester.email@example.com',
|
||||||
'username' => 'tester',
|
'username' => 'tester',
|
||||||
]);
|
]);
|
||||||
|
15
tests/codeception/api/unit/fixtures/data/models/accounts.php
Normal file
15
tests/codeception/api/unit/fixtures/data/models/accounts.php
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
return [
|
||||||
|
[
|
||||||
|
'id' => 1,
|
||||||
|
'uuid' => 'df936908-b2e1-544d-96f8-2977ec213022',
|
||||||
|
'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,
|
||||||
|
'updated_at' => 1451775316,
|
||||||
|
],
|
||||||
|
];
|
@ -6,7 +6,7 @@ use Yii;
|
|||||||
use tests\codeception\api\unit\DbTestCase;
|
use tests\codeception\api\unit\DbTestCase;
|
||||||
use api\models\PasswordResetRequestForm;
|
use api\models\PasswordResetRequestForm;
|
||||||
use tests\codeception\common\fixtures\UserFixture;
|
use tests\codeception\common\fixtures\UserFixture;
|
||||||
use common\models\User;
|
use common\models\Account;
|
||||||
use Codeception\Specify;
|
use Codeception\Specify;
|
||||||
|
|
||||||
class PasswordResetRequestFormTest extends DbTestCase
|
class PasswordResetRequestFormTest extends DbTestCase
|
||||||
@ -54,7 +54,7 @@ class PasswordResetRequestFormTest extends DbTestCase
|
|||||||
{
|
{
|
||||||
$model = new PasswordResetRequestForm();
|
$model = new PasswordResetRequestForm();
|
||||||
$model->email = $this->user[0]['email'];
|
$model->email = $this->user[0]['email'];
|
||||||
$user = User::findOne(['password_reset_token' => $this->user[0]['password_reset_token']]);
|
$user = Account::findOne(['password_reset_token' => $this->user[0]['password_reset_token']]);
|
||||||
|
|
||||||
expect('email sent', $model->sendEmail())->true();
|
expect('email sent', $model->sendEmail())->true();
|
||||||
expect('user has valid token', $user->password_reset_token)->notNull();
|
expect('user has valid token', $user->password_reset_token)->notNull();
|
||||||
|
@ -24,7 +24,6 @@ class SignupFormTest extends DbTestCase
|
|||||||
|
|
||||||
$this->assertInstanceOf('common\models\User', $user, 'user should be valid');
|
$this->assertInstanceOf('common\models\User', $user, 'user should be valid');
|
||||||
|
|
||||||
expect('username should be correct', $user->username)->equals('some_username');
|
|
||||||
expect('email should be correct', $user->email)->equals('some_email@example.com');
|
expect('email should be correct', $user->email)->equals('some_email@example.com');
|
||||||
expect('password should be correct', $user->validatePassword('some_password'))->true();
|
expect('password should be correct', $user->validatePassword('some_password'))->true();
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,124 @@
|
|||||||
|
<?php
|
||||||
|
namespace tests\codeception\api\modules\login\models;
|
||||||
|
|
||||||
|
use api\modules\login\models\AuthenticationForm;
|
||||||
|
use Codeception\Specify;
|
||||||
|
use tests\codeception\api\unit\DbTestCase;
|
||||||
|
use tests\codeception\common\fixtures\AccountFixture;
|
||||||
|
use Yii;
|
||||||
|
|
||||||
|
class AuthenticationFormTest extends DbTestCase {
|
||||||
|
|
||||||
|
use Specify;
|
||||||
|
|
||||||
|
protected function tearDown() {
|
||||||
|
Yii::$app->user->logout();
|
||||||
|
parent::tearDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testValidateEmail() {
|
||||||
|
$model = new AuthenticationForm();
|
||||||
|
$this->specify('error.email_required expected if email is not set', function() use ($model) {
|
||||||
|
$model->validate(['email']);
|
||||||
|
expect($model->getErrors('email'))->equals(['error.email_required']);
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->specify('error.email_invalid expected if email not correct', function() use ($model) {
|
||||||
|
$model->email = 'wrong-email-string';
|
||||||
|
$model->validate(['email']);
|
||||||
|
expect($model->getErrors('email'))->equals(['error.email_invalid']);
|
||||||
|
|
||||||
|
$model->email = 'wrong@email';
|
||||||
|
$model->validate(['email']);
|
||||||
|
expect($model->getErrors('email'))->equals(['error.email_invalid']);
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->specify('error.email_not_exist expected if email not exists in database', function() use ($model) {
|
||||||
|
$model->email = 'not-exist@user.com';
|
||||||
|
$model->validate(['email']);
|
||||||
|
expect($model->getErrors('email'))->equals(['error.email_not_exist']);
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->specify('no errors if email is correct and exists in database', function() use ($model) {
|
||||||
|
$model->email = 'admin@ely.by';
|
||||||
|
$model->validate(['email']);
|
||||||
|
expect($model->getErrors('email'))->isEmpty();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testValidatePassword() {
|
||||||
|
$model = new AuthenticationForm();
|
||||||
|
$this->specify('error.password_required expected if password is not set', function() use ($model) {
|
||||||
|
$model->validate(['password']);
|
||||||
|
expect($model->getErrors('password'))->equals(['error.password_required']);
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->specify('error.password_incorrect expected if password not correct for passed email', function() use ($model) {
|
||||||
|
$model->email = 'non-exist@valid.mail';
|
||||||
|
$model->password = 'wrong-password';
|
||||||
|
$model->validate(['password']);
|
||||||
|
expect('if email incorrect, the error should be displayed in any case,', $model->getErrors('password'))
|
||||||
|
->equals(['error.password_incorrect']);
|
||||||
|
|
||||||
|
$model->email = 'admin@ely.by';
|
||||||
|
$model->password = 'wrong-password';
|
||||||
|
$model->validate(['password']);
|
||||||
|
expect($model->getErrors('password'))->equals(['error.password_incorrect']);
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->specify('no errors if email and password is correct and exists in database', function() use ($model) {
|
||||||
|
$model->email = 'admin@ely.by';
|
||||||
|
$model->password = 'password_0';
|
||||||
|
$model->validate(['password']);
|
||||||
|
expect($model->getErrors('password'))->isEmpty();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testLoginNoUser() {
|
||||||
|
$model = new AuthenticationForm([
|
||||||
|
'email' => 'non-exist@valid.mail',
|
||||||
|
'password' => 'not_existing_password',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->specify('user should not be able to login, when there is no identity', function () use ($model) {
|
||||||
|
expect('model should not login user', $model->login())->false();
|
||||||
|
expect('user should not be logged in', Yii::$app->user->isGuest)->true();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testLoginWrongPassword() {
|
||||||
|
$model = new AuthenticationForm([
|
||||||
|
'email' => 'admin@ely.by',
|
||||||
|
'password' => 'wrong_password',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->specify('user should not be able to login with wrong password', function () use ($model) {
|
||||||
|
expect('model should not login user', $model->login())->false();
|
||||||
|
expect('error message should be set', $model->errors)->hasKey('password');
|
||||||
|
expect('user should not be logged in', Yii::$app->user->isGuest)->true();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testLoginCorrect() {
|
||||||
|
$model = new AuthenticationForm([
|
||||||
|
'email' => 'admin@ely.by',
|
||||||
|
'password' => 'password_0',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->specify('user should be able to login with correct credentials', function () use ($model) {
|
||||||
|
expect('model should login user', $model->login())->true();
|
||||||
|
expect('error message should not be set', $model->errors)->hasntKey('password');
|
||||||
|
expect('user should be logged in', Yii::$app->user->isGuest)->false();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function fixtures() {
|
||||||
|
return [
|
||||||
|
'user' => [
|
||||||
|
'class' => AccountFixture::className(),
|
||||||
|
'dataFile' => '@tests/codeception/api/unit/fixtures/data/models/accounts.php'
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,25 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace tests\codeception\common\_pages;
|
|
||||||
|
|
||||||
use yii\codeception\BasePage;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents loging page
|
|
||||||
* @property \codeception_api\AcceptanceTester|\codeception_api\FunctionalTester $actor
|
|
||||||
*/
|
|
||||||
class LoginPage extends BasePage
|
|
||||||
{
|
|
||||||
public $route = 'site/login';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $username
|
|
||||||
* @param string $password
|
|
||||||
*/
|
|
||||||
public function login($username, $password)
|
|
||||||
{
|
|
||||||
$this->actor->fillField('input[name="LoginForm[username]"]', $username);
|
|
||||||
$this->actor->fillField('input[name="LoginForm[password]"]', $password);
|
|
||||||
$this->actor->click('login-button');
|
|
||||||
}
|
|
||||||
}
|
|
@ -63,10 +63,10 @@ class FixtureHelper extends Module
|
|||||||
public function fixtures()
|
public function fixtures()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'user' => [
|
//'user' => [
|
||||||
'class' => UserFixture::className(),
|
// 'class' => UserFixture::className(),
|
||||||
'dataFile' => '@tests/codeception/common/fixtures/data/init_login.php',
|
// 'dataFile' => '@tests/codeception/common/fixtures/data/init_login.php',
|
||||||
],
|
//],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
12
tests/codeception/common/fixtures/AccountFixture.php
Normal file
12
tests/codeception/common/fixtures/AccountFixture.php
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace tests\codeception\common\fixtures;
|
||||||
|
|
||||||
|
use common\models\Account;
|
||||||
|
use yii\test\ActiveFixture;
|
||||||
|
|
||||||
|
class AccountFixture extends ActiveFixture {
|
||||||
|
|
||||||
|
public $modelClass = Account::class;
|
||||||
|
|
||||||
|
}
|
@ -2,11 +2,11 @@
|
|||||||
|
|
||||||
namespace tests\codeception\common\unit\models;
|
namespace tests\codeception\common\unit\models;
|
||||||
|
|
||||||
use Yii;
|
use api\models\LoginForm;
|
||||||
use tests\codeception\common\unit\DbTestCase;
|
|
||||||
use Codeception\Specify;
|
use Codeception\Specify;
|
||||||
use common\models\LoginForm;
|
|
||||||
use tests\codeception\common\fixtures\UserFixture;
|
use tests\codeception\common\fixtures\UserFixture;
|
||||||
|
use tests\codeception\common\unit\DbTestCase;
|
||||||
|
use Yii;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Login form test
|
* Login form test
|
||||||
|
@ -14,7 +14,7 @@ return [
|
|||||||
],
|
],
|
||||||
'components' => [
|
'components' => [
|
||||||
'db' => [
|
'db' => [
|
||||||
'dsn' => 'mysql:host=localhost;dbname=yii2_advanced_tests',
|
'dsn' => 'mysql:host=localhost;dbname=ely_accounts_test',
|
||||||
],
|
],
|
||||||
'mailer' => [
|
'mailer' => [
|
||||||
'useFileTransport' => true,
|
'useFileTransport' => true,
|
||||||
|
Loading…
Reference in New Issue
Block a user