mirror of
https://github.com/elyby/accounts.git
synced 2024-12-23 05:39:54 +05:30
Инициализировано Yii2 приложение, выпилены лишние части, накинуты чуточку нужных
This commit is contained in:
commit
841303b8ab
31
.gitignore
vendored
Normal file
31
.gitignore
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
# yii console command
|
||||
/yii
|
||||
|
||||
# phpstorm project files
|
||||
.idea
|
||||
|
||||
# netbeans project files
|
||||
nbproject
|
||||
|
||||
# zend studio for eclipse project files
|
||||
.buildpath
|
||||
.project
|
||||
.settings
|
||||
|
||||
# windows thumbnail cache
|
||||
Thumbs.db
|
||||
|
||||
# composer vendor dir
|
||||
/vendor
|
||||
|
||||
# composer itself is not needed
|
||||
composer.phar
|
||||
composer.lock
|
||||
|
||||
# Mac DS_Store Files
|
||||
.DS_Store
|
||||
|
||||
# phpunit itself is not needed
|
||||
phpunit.phar
|
||||
# local phpunit config
|
||||
/phpunit.xml
|
54
README.md
Normal file
54
README.md
Normal file
@ -0,0 +1,54 @@
|
||||
Yii 2 Advanced Project Template
|
||||
===============================
|
||||
|
||||
Yii 2 Advanced Project Template is a skeleton [Yii 2](http://www.yiiframework.com/) application best for
|
||||
developing complex Web applications with multiple tiers.
|
||||
|
||||
The template includes three tiers: front end, back end, and console, each of which
|
||||
is a separate Yii application.
|
||||
|
||||
The template is designed to work in a team development environment. It supports
|
||||
deploying the application in different environments.
|
||||
|
||||
Documentation is at [docs/guide/README.md](docs/guide/README.md).
|
||||
|
||||
[![Latest Stable Version](https://poser.pugx.org/yiisoft/yii2-app-advanced/v/stable.png)](https://packagist.org/packages/yiisoft/yii2-app-advanced)
|
||||
[![Total Downloads](https://poser.pugx.org/yiisoft/yii2-app-advanced/downloads.png)](https://packagist.org/packages/yiisoft/yii2-app-advanced)
|
||||
[![Build Status](https://travis-ci.org/yiisoft/yii2-app-advanced.svg?branch=master)](https://travis-ci.org/yiisoft/yii2-app-advanced)
|
||||
|
||||
DIRECTORY STRUCTURE
|
||||
-------------------
|
||||
|
||||
```
|
||||
common
|
||||
config/ contains shared configurations
|
||||
mail/ contains view files for e-mails
|
||||
models/ contains model classes used in both backend and frontend
|
||||
console
|
||||
config/ contains console configurations
|
||||
controllers/ contains console controllers (commands)
|
||||
migrations/ contains database migrations
|
||||
models/ contains console-specific model classes
|
||||
runtime/ contains files generated during runtime
|
||||
backend
|
||||
assets/ contains application assets such as JavaScript and CSS
|
||||
config/ contains backend configurations
|
||||
controllers/ contains Web controller classes
|
||||
models/ contains backend-specific model classes
|
||||
runtime/ contains files generated during runtime
|
||||
views/ contains view files for the Web application
|
||||
web/ contains the entry script and Web resources
|
||||
frontend
|
||||
assets/ contains application assets such as JavaScript and CSS
|
||||
config/ contains frontend configurations
|
||||
controllers/ contains Web controller classes
|
||||
models/ contains frontend-specific model classes
|
||||
runtime/ contains files generated during runtime
|
||||
views/ contains view files for the Web application
|
||||
web/ contains the entry script and Web resources
|
||||
widgets/ contains frontend widgets
|
||||
vendor/ contains dependent 3rd-party packages
|
||||
environments/ contains environment-based overrides
|
||||
tests contains various tests for the advanced application
|
||||
codeception/ contains tests developed with Codeception PHP Testing Framework
|
||||
```
|
29
api/assets/AppAsset.php
Normal file
29
api/assets/AppAsset.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace api\assets;
|
||||
|
||||
use yii\web\AssetBundle;
|
||||
|
||||
/**
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class AppAsset extends AssetBundle
|
||||
{
|
||||
public $basePath = '@webroot';
|
||||
public $baseUrl = '@web';
|
||||
public $css = [
|
||||
'css/site.css',
|
||||
];
|
||||
public $js = [
|
||||
];
|
||||
public $depends = [
|
||||
'yii\web\YiiAsset',
|
||||
'yii\bootstrap\BootstrapAsset',
|
||||
];
|
||||
}
|
2
api/config/.gitignore
vendored
Normal file
2
api/config/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
main-local.php
|
||||
params-local.php
|
1
api/config/bootstrap.php
Normal file
1
api/config/bootstrap.php
Normal file
@ -0,0 +1 @@
|
||||
<?php
|
33
api/config/main.php
Normal file
33
api/config/main.php
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
$params = array_merge(
|
||||
require(__DIR__ . '/../../common/config/params.php'),
|
||||
require(__DIR__ . '/../../common/config/params-local.php'),
|
||||
require(__DIR__ . '/params.php'),
|
||||
require(__DIR__ . '/params-local.php')
|
||||
);
|
||||
|
||||
return [
|
||||
'id' => 'accounts-site-api',
|
||||
'basePath' => dirname(__DIR__),
|
||||
'bootstrap' => ['log'],
|
||||
'controllerNamespace' => 'api\controllers',
|
||||
'components' => [
|
||||
'user' => [
|
||||
'identityClass' => 'common\models\User',
|
||||
'enableAutoLogin' => true,
|
||||
],
|
||||
'log' => [
|
||||
'traceLevel' => YII_DEBUG ? 3 : 0,
|
||||
'targets' => [
|
||||
[
|
||||
'class' => 'yii\log\FileTarget',
|
||||
'levels' => ['error', 'warning'],
|
||||
],
|
||||
],
|
||||
],
|
||||
'errorHandler' => [
|
||||
'errorAction' => 'site/error',
|
||||
],
|
||||
],
|
||||
'params' => $params,
|
||||
];
|
4
api/config/params.php
Normal file
4
api/config/params.php
Normal file
@ -0,0 +1,4 @@
|
||||
<?php
|
||||
return [
|
||||
'adminEmail' => 'admin@example.com',
|
||||
];
|
213
api/controllers/SiteController.php
Normal file
213
api/controllers/SiteController.php
Normal file
@ -0,0 +1,213 @@
|
||||
<?php
|
||||
namespace api\controllers;
|
||||
|
||||
use Yii;
|
||||
use common\models\LoginForm;
|
||||
use api\models\PasswordResetRequestForm;
|
||||
use api\models\ResetPasswordForm;
|
||||
use api\models\SignupForm;
|
||||
use api\models\ContactForm;
|
||||
use yii\base\InvalidParamException;
|
||||
use yii\web\BadRequestHttpException;
|
||||
use yii\web\Controller;
|
||||
use yii\filters\VerbFilter;
|
||||
use yii\filters\AccessControl;
|
||||
|
||||
/**
|
||||
* Site controller
|
||||
*/
|
||||
class SiteController extends Controller
|
||||
{
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function behaviors()
|
||||
{
|
||||
return [
|
||||
'access' => [
|
||||
'class' => AccessControl::className(),
|
||||
'only' => ['logout', 'signup'],
|
||||
'rules' => [
|
||||
[
|
||||
'actions' => ['signup'],
|
||||
'allow' => true,
|
||||
'roles' => ['?'],
|
||||
],
|
||||
[
|
||||
'actions' => ['logout'],
|
||||
'allow' => true,
|
||||
'roles' => ['@'],
|
||||
],
|
||||
],
|
||||
],
|
||||
'verbs' => [
|
||||
'class' => VerbFilter::className(),
|
||||
'actions' => [
|
||||
'logout' => ['post'],
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function actions()
|
||||
{
|
||||
return [
|
||||
'error' => [
|
||||
'class' => 'yii\web\ErrorAction',
|
||||
],
|
||||
'captcha' => [
|
||||
'class' => 'yii\captcha\CaptchaAction',
|
||||
'fixedVerifyCode' => YII_ENV_TEST ? 'testme' : null,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays homepage.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function actionIndex()
|
||||
{
|
||||
return $this->render('index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs in a user.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function actionLogin()
|
||||
{
|
||||
if (!\Yii::$app->user->isGuest) {
|
||||
return $this->goHome();
|
||||
}
|
||||
|
||||
$model = new LoginForm();
|
||||
if ($model->load(Yii::$app->request->post()) && $model->login()) {
|
||||
return $this->goBack();
|
||||
} else {
|
||||
return $this->render('login', [
|
||||
'model' => $model,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs out the current user.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function actionLogout()
|
||||
{
|
||||
Yii::$app->user->logout();
|
||||
|
||||
return $this->goHome();
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays contact page.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function actionContact()
|
||||
{
|
||||
$model = new ContactForm();
|
||||
if ($model->load(Yii::$app->request->post()) && $model->validate()) {
|
||||
if ($model->sendEmail(Yii::$app->params['adminEmail'])) {
|
||||
Yii::$app->session->setFlash('success', 'Thank you for contacting us. We will respond to you as soon as possible.');
|
||||
} else {
|
||||
Yii::$app->session->setFlash('error', 'There was an error sending email.');
|
||||
}
|
||||
|
||||
return $this->refresh();
|
||||
} else {
|
||||
return $this->render('contact', [
|
||||
'model' => $model,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays about page.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function actionAbout()
|
||||
{
|
||||
return $this->render('about');
|
||||
}
|
||||
|
||||
/**
|
||||
* Signs user up.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function actionSignup()
|
||||
{
|
||||
$model = new SignupForm();
|
||||
if ($model->load(Yii::$app->request->post())) {
|
||||
if ($user = $model->signup()) {
|
||||
if (Yii::$app->getUser()->login($user)) {
|
||||
return $this->goHome();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->render('signup', [
|
||||
'model' => $model,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests password reset.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function actionRequestPasswordReset()
|
||||
{
|
||||
$model = new PasswordResetRequestForm();
|
||||
if ($model->load(Yii::$app->request->post()) && $model->validate()) {
|
||||
if ($model->sendEmail()) {
|
||||
Yii::$app->session->setFlash('success', 'Check your email for further instructions.');
|
||||
|
||||
return $this->goHome();
|
||||
} else {
|
||||
Yii::$app->session->setFlash('error', 'Sorry, we are unable to reset password for email provided.');
|
||||
}
|
||||
}
|
||||
|
||||
return $this->render('requestPasswordResetToken', [
|
||||
'model' => $model,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets password.
|
||||
*
|
||||
* @param string $token
|
||||
* @return mixed
|
||||
* @throws BadRequestHttpException
|
||||
*/
|
||||
public function actionResetPassword($token)
|
||||
{
|
||||
try {
|
||||
$model = new ResetPasswordForm($token);
|
||||
} catch (InvalidParamException $e) {
|
||||
throw new BadRequestHttpException($e->getMessage());
|
||||
}
|
||||
|
||||
if ($model->load(Yii::$app->request->post()) && $model->validate() && $model->resetPassword()) {
|
||||
Yii::$app->session->setFlash('success', 'New password was saved.');
|
||||
|
||||
return $this->goHome();
|
||||
}
|
||||
|
||||
return $this->render('resetPassword', [
|
||||
'model' => $model,
|
||||
]);
|
||||
}
|
||||
}
|
59
api/models/ContactForm.php
Normal file
59
api/models/ContactForm.php
Normal file
@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
namespace api\models;
|
||||
|
||||
use Yii;
|
||||
use yii\base\Model;
|
||||
|
||||
/**
|
||||
* ContactForm is the model behind the contact form.
|
||||
*/
|
||||
class ContactForm extends Model
|
||||
{
|
||||
public $name;
|
||||
public $email;
|
||||
public $subject;
|
||||
public $body;
|
||||
public $verifyCode;
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
// name, email, subject and body are required
|
||||
[['name', 'email', 'subject', 'body'], 'required'],
|
||||
// email has to be a valid email address
|
||||
['email', 'email'],
|
||||
// verifyCode needs to be entered correctly
|
||||
['verifyCode', 'captcha'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function attributeLabels()
|
||||
{
|
||||
return [
|
||||
'verifyCode' => 'Verification Code',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends an email to the specified email address using the information collected by this model.
|
||||
*
|
||||
* @param string $email the target email address
|
||||
* @return boolean whether the email was sent
|
||||
*/
|
||||
public function sendEmail($email)
|
||||
{
|
||||
return Yii::$app->mailer->compose()
|
||||
->setTo($email)
|
||||
->setFrom([$this->email => $this->name])
|
||||
->setSubject($this->subject)
|
||||
->setTextBody($this->body)
|
||||
->send();
|
||||
}
|
||||
}
|
60
api/models/PasswordResetRequestForm.php
Normal file
60
api/models/PasswordResetRequestForm.php
Normal file
@ -0,0 +1,60 @@
|
||||
<?php
|
||||
namespace api\models;
|
||||
|
||||
use common\models\User;
|
||||
use yii\base\Model;
|
||||
|
||||
/**
|
||||
* Password reset request form
|
||||
*/
|
||||
class PasswordResetRequestForm extends Model
|
||||
{
|
||||
public $email;
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
['email', 'filter', 'filter' => 'trim'],
|
||||
['email', 'required'],
|
||||
['email', 'email'],
|
||||
['email', 'exist',
|
||||
'targetClass' => '\common\models\User',
|
||||
'filter' => ['status' => User::STATUS_ACTIVE],
|
||||
'message' => 'There is no user with such email.'
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends an email with a link, for resetting the password.
|
||||
*
|
||||
* @return boolean whether the email was send
|
||||
*/
|
||||
public function sendEmail()
|
||||
{
|
||||
/* @var $user User */
|
||||
$user = User::findOne([
|
||||
'status' => User::STATUS_ACTIVE,
|
||||
'email' => $this->email,
|
||||
]);
|
||||
|
||||
if ($user) {
|
||||
if (!User::isPasswordResetTokenValid($user->password_reset_token)) {
|
||||
$user->generatePasswordResetToken();
|
||||
}
|
||||
|
||||
if ($user->save()) {
|
||||
return \Yii::$app->mailer->compose(['html' => 'passwordResetToken-html', 'text' => 'passwordResetToken-text'], ['user' => $user])
|
||||
->setFrom([\Yii::$app->params['supportEmail'] => \Yii::$app->name . ' robot'])
|
||||
->setTo($this->email)
|
||||
->setSubject('Password reset for ' . \Yii::$app->name)
|
||||
->send();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
65
api/models/ResetPasswordForm.php
Normal file
65
api/models/ResetPasswordForm.php
Normal file
@ -0,0 +1,65 @@
|
||||
<?php
|
||||
namespace api\models;
|
||||
|
||||
use common\models\User;
|
||||
use yii\base\InvalidParamException;
|
||||
use yii\base\Model;
|
||||
use Yii;
|
||||
|
||||
/**
|
||||
* Password reset form
|
||||
*/
|
||||
class ResetPasswordForm extends Model
|
||||
{
|
||||
public $password;
|
||||
|
||||
/**
|
||||
* @var \common\models\User
|
||||
*/
|
||||
private $_user;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a form model given a token.
|
||||
*
|
||||
* @param string $token
|
||||
* @param array $config name-value pairs that will be used to initialize the object properties
|
||||
* @throws \yii\base\InvalidParamException if token is empty or not valid
|
||||
*/
|
||||
public function __construct($token, $config = [])
|
||||
{
|
||||
if (empty($token) || !is_string($token)) {
|
||||
throw new InvalidParamException('Password reset token cannot be blank.');
|
||||
}
|
||||
$this->_user = User::findByPasswordResetToken($token);
|
||||
if (!$this->_user) {
|
||||
throw new InvalidParamException('Wrong password reset token.');
|
||||
}
|
||||
parent::__construct($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
['password', 'required'],
|
||||
['password', 'string', 'min' => 6],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets password.
|
||||
*
|
||||
* @return boolean if password was reset.
|
||||
*/
|
||||
public function resetPassword()
|
||||
{
|
||||
$user = $this->_user;
|
||||
$user->setPassword($this->password);
|
||||
$user->removePasswordResetToken();
|
||||
|
||||
return $user->save(false);
|
||||
}
|
||||
}
|
59
api/models/SignupForm.php
Normal file
59
api/models/SignupForm.php
Normal file
@ -0,0 +1,59 @@
|
||||
<?php
|
||||
namespace api\models;
|
||||
|
||||
use common\models\User;
|
||||
use yii\base\Model;
|
||||
use Yii;
|
||||
|
||||
/**
|
||||
* Signup form
|
||||
*/
|
||||
class SignupForm extends Model
|
||||
{
|
||||
public $username;
|
||||
public $email;
|
||||
public $password;
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
['username', 'filter', 'filter' => 'trim'],
|
||||
['username', 'required'],
|
||||
['username', 'unique', 'targetClass' => '\common\models\User', 'message' => 'This username has already been taken.'],
|
||||
['username', 'string', 'min' => 2, 'max' => 255],
|
||||
|
||||
['email', 'filter', 'filter' => 'trim'],
|
||||
['email', 'required'],
|
||||
['email', 'email'],
|
||||
['email', 'string', 'max' => 255],
|
||||
['email', 'unique', 'targetClass' => '\common\models\User', 'message' => 'This email address has already been taken.'],
|
||||
|
||||
['password', 'required'],
|
||||
['password', 'string', 'min' => 6],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Signs user up.
|
||||
*
|
||||
* @return User|null the saved model or null if saving fails
|
||||
*/
|
||||
public function signup()
|
||||
{
|
||||
if ($this->validate()) {
|
||||
$user = new User();
|
||||
$user->username = $this->username;
|
||||
$user->email = $this->email;
|
||||
$user->setPassword($this->password);
|
||||
$user->generateAuthKey();
|
||||
if ($user->save()) {
|
||||
return $user;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
2
api/runtime/.gitignore
vendored
Normal file
2
api/runtime/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
*
|
||||
!.gitignore
|
77
api/views/layouts/main.php
Normal file
77
api/views/layouts/main.php
Normal file
@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
/* @var $this \yii\web\View */
|
||||
/* @var $content string */
|
||||
|
||||
use yii\helpers\Html;
|
||||
use yii\bootstrap\Nav;
|
||||
use yii\bootstrap\NavBar;
|
||||
use yii\widgets\Breadcrumbs;
|
||||
use api\assets\AppAsset;
|
||||
|
||||
AppAsset::register($this);
|
||||
?>
|
||||
<?php $this->beginPage() ?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="<?= Yii::$app->language ?>">
|
||||
<head>
|
||||
<meta charset="<?= Yii::$app->charset ?>">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<?= Html::csrfMetaTags() ?>
|
||||
<title><?= Html::encode($this->title) ?></title>
|
||||
<?php $this->head() ?>
|
||||
</head>
|
||||
<body>
|
||||
<?php $this->beginBody() ?>
|
||||
|
||||
<div class="wrap">
|
||||
<?php
|
||||
NavBar::begin([
|
||||
'brandLabel' => 'My Company',
|
||||
'brandUrl' => Yii::$app->homeUrl,
|
||||
'options' => [
|
||||
'class' => 'navbar-inverse navbar-fixed-top',
|
||||
],
|
||||
]);
|
||||
$menuItems = [
|
||||
['label' => 'Home', 'url' => ['/site/index']],
|
||||
['label' => 'About', 'url' => ['/site/about']],
|
||||
['label' => 'Contact', 'url' => ['/site/contact']],
|
||||
];
|
||||
if (Yii::$app->user->isGuest) {
|
||||
$menuItems[] = ['label' => 'Signup', 'url' => ['/site/signup']];
|
||||
$menuItems[] = ['label' => 'Login', 'url' => ['/site/login']];
|
||||
} else {
|
||||
$menuItems[] = [
|
||||
'label' => 'Logout (' . Yii::$app->user->identity->username . ')',
|
||||
'url' => ['/site/logout'],
|
||||
'linkOptions' => ['data-method' => 'post']
|
||||
];
|
||||
}
|
||||
echo Nav::widget([
|
||||
'options' => ['class' => 'navbar-nav navbar-right'],
|
||||
'items' => $menuItems,
|
||||
]);
|
||||
NavBar::end();
|
||||
?>
|
||||
|
||||
<div class="container">
|
||||
<?= Breadcrumbs::widget([
|
||||
'links' => isset($this->params['breadcrumbs']) ? $this->params['breadcrumbs'] : [],
|
||||
]) ?>
|
||||
<?= $content ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer class="footer">
|
||||
<div class="container">
|
||||
<p class="pull-left">© My Company <?= date('Y') ?></p>
|
||||
|
||||
<p class="pull-right"><?= Yii::powered() ?></p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<?php $this->endBody() ?>
|
||||
</body>
|
||||
</html>
|
||||
<?php $this->endPage() ?>
|
16
api/views/site/about.php
Normal file
16
api/views/site/about.php
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
/* @var $this yii\web\View */
|
||||
|
||||
use yii\helpers\Html;
|
||||
|
||||
$this->title = 'About';
|
||||
$this->params['breadcrumbs'][] = $this->title;
|
||||
?>
|
||||
<div class="site-about">
|
||||
<h1><?= Html::encode($this->title) ?></h1>
|
||||
|
||||
<p>This is the About page. You may modify the following file to customize its content:</p>
|
||||
|
||||
<code><?= __FILE__ ?></code>
|
||||
</div>
|
45
api/views/site/contact.php
Normal file
45
api/views/site/contact.php
Normal file
@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
/* @var $this yii\web\View */
|
||||
/* @var $form yii\bootstrap\ActiveForm */
|
||||
/* @var $model \api\models\ContactForm */
|
||||
|
||||
use yii\helpers\Html;
|
||||
use yii\bootstrap\ActiveForm;
|
||||
use yii\captcha\Captcha;
|
||||
|
||||
$this->title = 'Contact';
|
||||
$this->params['breadcrumbs'][] = $this->title;
|
||||
?>
|
||||
<div class="site-contact">
|
||||
<h1><?= Html::encode($this->title) ?></h1>
|
||||
|
||||
<p>
|
||||
If you have business inquiries or other questions, please fill out the following form to contact us. Thank you.
|
||||
</p>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-5">
|
||||
<?php $form = ActiveForm::begin(['id' => 'contact-form']); ?>
|
||||
|
||||
<?= $form->field($model, 'name') ?>
|
||||
|
||||
<?= $form->field($model, 'email') ?>
|
||||
|
||||
<?= $form->field($model, 'subject') ?>
|
||||
|
||||
<?= $form->field($model, 'body')->textArea(['rows' => 6]) ?>
|
||||
|
||||
<?= $form->field($model, 'verifyCode')->widget(Captcha::className(), [
|
||||
'template' => '<div class="row"><div class="col-lg-3">{image}</div><div class="col-lg-6">{input}</div></div>',
|
||||
]) ?>
|
||||
|
||||
<div class="form-group">
|
||||
<?= Html::submitButton('Submit', ['class' => 'btn btn-primary', 'name' => 'contact-button']) ?>
|
||||
</div>
|
||||
|
||||
<?php ActiveForm::end(); ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
27
api/views/site/error.php
Normal file
27
api/views/site/error.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
/* @var $this yii\web\View */
|
||||
/* @var $name string */
|
||||
/* @var $message string */
|
||||
/* @var $exception Exception */
|
||||
|
||||
use yii\helpers\Html;
|
||||
|
||||
$this->title = $name;
|
||||
?>
|
||||
<div class="site-error">
|
||||
|
||||
<h1><?= Html::encode($this->title) ?></h1>
|
||||
|
||||
<div class="alert alert-danger">
|
||||
<?= nl2br(Html::encode($message)) ?>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
The above error occurred while the Web server was processing your request.
|
||||
</p>
|
||||
<p>
|
||||
Please contact us if you think this is a server error. Thank you.
|
||||
</p>
|
||||
|
||||
</div>
|
53
api/views/site/index.php
Normal file
53
api/views/site/index.php
Normal file
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
/* @var $this yii\web\View */
|
||||
|
||||
$this->title = 'My Yii Application';
|
||||
?>
|
||||
<div class="site-index">
|
||||
|
||||
<div class="jumbotron">
|
||||
<h1>Congratulations!</h1>
|
||||
|
||||
<p class="lead">You have successfully created your Yii-powered application.</p>
|
||||
|
||||
<p><a class="btn btn-lg btn-success" href="http://www.yiiframework.com">Get started with Yii</a></p>
|
||||
</div>
|
||||
|
||||
<div class="body-content">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-4">
|
||||
<h2>Heading</h2>
|
||||
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et
|
||||
dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip
|
||||
ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu
|
||||
fugiat nulla pariatur.</p>
|
||||
|
||||
<p><a class="btn btn-default" href="http://www.yiiframework.com/doc/">Yii Documentation »</a></p>
|
||||
</div>
|
||||
<div class="col-lg-4">
|
||||
<h2>Heading</h2>
|
||||
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et
|
||||
dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip
|
||||
ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu
|
||||
fugiat nulla pariatur.</p>
|
||||
|
||||
<p><a class="btn btn-default" href="http://www.yiiframework.com/forum/">Yii Forum »</a></p>
|
||||
</div>
|
||||
<div class="col-lg-4">
|
||||
<h2>Heading</h2>
|
||||
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et
|
||||
dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip
|
||||
ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu
|
||||
fugiat nulla pariatur.</p>
|
||||
|
||||
<p><a class="btn btn-default" href="http://www.yiiframework.com/extensions/">Yii Extensions »</a></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
39
api/views/site/login.php
Normal file
39
api/views/site/login.php
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
/* @var $this yii\web\View */
|
||||
/* @var $form yii\bootstrap\ActiveForm */
|
||||
/* @var $model \common\models\LoginForm */
|
||||
|
||||
use yii\helpers\Html;
|
||||
use yii\bootstrap\ActiveForm;
|
||||
|
||||
$this->title = 'Login';
|
||||
$this->params['breadcrumbs'][] = $this->title;
|
||||
?>
|
||||
<div class="site-login">
|
||||
<h1><?= Html::encode($this->title) ?></h1>
|
||||
|
||||
<p>Please fill out the following fields to login:</p>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-5">
|
||||
<?php $form = ActiveForm::begin(['id' => 'login-form']); ?>
|
||||
|
||||
<?= $form->field($model, 'username') ?>
|
||||
|
||||
<?= $form->field($model, 'password')->passwordInput() ?>
|
||||
|
||||
<?= $form->field($model, 'rememberMe')->checkbox() ?>
|
||||
|
||||
<div style="color:#999;margin:1em 0">
|
||||
If you forgot your password you can <?= Html::a('reset it', ['site/request-password-reset']) ?>.
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<?= Html::submitButton('Login', ['class' => 'btn btn-primary', 'name' => 'login-button']) ?>
|
||||
</div>
|
||||
|
||||
<?php ActiveForm::end(); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
31
api/views/site/requestPasswordResetToken.php
Normal file
31
api/views/site/requestPasswordResetToken.php
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
/* @var $this yii\web\View */
|
||||
/* @var $form yii\bootstrap\ActiveForm */
|
||||
/* @var $model \api\models\PasswordResetRequestForm */
|
||||
|
||||
use yii\helpers\Html;
|
||||
use yii\bootstrap\ActiveForm;
|
||||
|
||||
$this->title = 'Request password reset';
|
||||
$this->params['breadcrumbs'][] = $this->title;
|
||||
?>
|
||||
<div class="site-request-password-reset">
|
||||
<h1><?= Html::encode($this->title) ?></h1>
|
||||
|
||||
<p>Please fill out your email. A link to reset password will be sent there.</p>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-5">
|
||||
<?php $form = ActiveForm::begin(['id' => 'request-password-reset-form']); ?>
|
||||
|
||||
<?= $form->field($model, 'email') ?>
|
||||
|
||||
<div class="form-group">
|
||||
<?= Html::submitButton('Send', ['class' => 'btn btn-primary']) ?>
|
||||
</div>
|
||||
|
||||
<?php ActiveForm::end(); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
31
api/views/site/resetPassword.php
Normal file
31
api/views/site/resetPassword.php
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
/* @var $this yii\web\View */
|
||||
/* @var $form yii\bootstrap\ActiveForm */
|
||||
/* @var $model \api\models\ResetPasswordForm */
|
||||
|
||||
use yii\helpers\Html;
|
||||
use yii\bootstrap\ActiveForm;
|
||||
|
||||
$this->title = 'Reset password';
|
||||
$this->params['breadcrumbs'][] = $this->title;
|
||||
?>
|
||||
<div class="site-reset-password">
|
||||
<h1><?= Html::encode($this->title) ?></h1>
|
||||
|
||||
<p>Please choose your new password:</p>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-5">
|
||||
<?php $form = ActiveForm::begin(['id' => 'reset-password-form']); ?>
|
||||
|
||||
<?= $form->field($model, 'password')->passwordInput() ?>
|
||||
|
||||
<div class="form-group">
|
||||
<?= Html::submitButton('Save', ['class' => 'btn btn-primary']) ?>
|
||||
</div>
|
||||
|
||||
<?php ActiveForm::end(); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
35
api/views/site/signup.php
Normal file
35
api/views/site/signup.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
/* @var $this yii\web\View */
|
||||
/* @var $form yii\bootstrap\ActiveForm */
|
||||
/* @var $model \api\models\SignupForm */
|
||||
|
||||
use yii\helpers\Html;
|
||||
use yii\bootstrap\ActiveForm;
|
||||
|
||||
$this->title = 'Signup';
|
||||
$this->params['breadcrumbs'][] = $this->title;
|
||||
?>
|
||||
<div class="site-signup">
|
||||
<h1><?= Html::encode($this->title) ?></h1>
|
||||
|
||||
<p>Please fill out the following fields to signup:</p>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-5">
|
||||
<?php $form = ActiveForm::begin(['id' => 'form-signup']); ?>
|
||||
|
||||
<?= $form->field($model, 'username') ?>
|
||||
|
||||
<?= $form->field($model, 'email') ?>
|
||||
|
||||
<?= $form->field($model, 'password')->passwordInput() ?>
|
||||
|
||||
<div class="form-group">
|
||||
<?= Html::submitButton('Signup', ['class' => 'btn btn-primary', 'name' => 'signup-button']) ?>
|
||||
</div>
|
||||
|
||||
<?php ActiveForm::end(); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
2
api/web/.gitignore
vendored
Normal file
2
api/web/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/index.php
|
||||
/index-test.php
|
2
api/web/assets/.gitignore
vendored
Normal file
2
api/web/assets/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
*
|
||||
!.gitignore
|
BIN
api/web/favicon.ico
Normal file
BIN
api/web/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 318 B |
2
api/web/robots.txt
Normal file
2
api/web/robots.txt
Normal file
@ -0,0 +1,2 @@
|
||||
User-agent: *
|
||||
Disallow:
|
2
common/config/.gitignore
vendored
Normal file
2
common/config/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
main-local.php
|
||||
params-local.php
|
4
common/config/bootstrap.php
Normal file
4
common/config/bootstrap.php
Normal file
@ -0,0 +1,4 @@
|
||||
<?php
|
||||
Yii::setAlias('common', dirname(__DIR__));
|
||||
Yii::setAlias('api', dirname(dirname(__DIR__)) . '/api');
|
||||
Yii::setAlias('console', dirname(dirname(__DIR__)) . '/console');
|
17
common/config/main.php
Normal file
17
common/config/main.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
return [
|
||||
'vendorPath' => dirname(dirname(__DIR__)) . '/vendor',
|
||||
'components' => [
|
||||
'cache' => [
|
||||
'class' => 'yii\caching\FileCache',
|
||||
],
|
||||
'db' => [
|
||||
'class' => 'yii\db\Connection',
|
||||
'charset' => 'utf8',
|
||||
],
|
||||
'mailer' => [
|
||||
'class' => 'yii\swiftmailer\Mailer',
|
||||
'viewPath' => '@common/mail',
|
||||
],
|
||||
],
|
||||
];
|
6
common/config/params.php
Normal file
6
common/config/params.php
Normal file
@ -0,0 +1,6 @@
|
||||
<?php
|
||||
return [
|
||||
'adminEmail' => 'admin@example.com',
|
||||
'supportEmail' => 'support@example.com',
|
||||
'user.passwordResetTokenExpire' => 3600,
|
||||
];
|
22
common/mail/layouts/html.php
Normal file
22
common/mail/layouts/html.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
use yii\helpers\Html;
|
||||
|
||||
/* @var $this \yii\web\View view component instance */
|
||||
/* @var $message \yii\mail\MessageInterface the message being composed */
|
||||
/* @var $content string main view render result */
|
||||
?>
|
||||
<?php $this->beginPage() ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=<?= Yii::$app->charset ?>" />
|
||||
<title><?= Html::encode($this->title) ?></title>
|
||||
<?php $this->head() ?>
|
||||
</head>
|
||||
<body>
|
||||
<?php $this->beginBody() ?>
|
||||
<?= $content ?>
|
||||
<?php $this->endBody() ?>
|
||||
</body>
|
||||
</html>
|
||||
<?php $this->endPage() ?>
|
12
common/mail/layouts/text.php
Normal file
12
common/mail/layouts/text.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
use yii\helpers\Html;
|
||||
|
||||
/* @var $this \yii\web\View view component instance */
|
||||
/* @var $message \yii\mail\MessageInterface the message being composed */
|
||||
/* @var $content string main view render result */
|
||||
?>
|
||||
<?php $this->beginPage() ?>
|
||||
<?php $this->beginBody() ?>
|
||||
<?= $content ?>
|
||||
<?php $this->endBody() ?>
|
||||
<?php $this->endPage() ?>
|
15
common/mail/passwordResetToken-html.php
Normal file
15
common/mail/passwordResetToken-html.php
Normal file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
use yii\helpers\Html;
|
||||
|
||||
/* @var $this yii\web\View */
|
||||
/* @var $user common\models\User */
|
||||
|
||||
$resetLink = Yii::$app->urlManager->createAbsoluteUrl(['site/reset-password', 'token' => $user->password_reset_token]);
|
||||
?>
|
||||
<div class="password-reset">
|
||||
<p>Hello <?= Html::encode($user->username) ?>,</p>
|
||||
|
||||
<p>Follow the link below to reset your password:</p>
|
||||
|
||||
<p><?= Html::a(Html::encode($resetLink), $resetLink) ?></p>
|
||||
</div>
|
12
common/mail/passwordResetToken-text.php
Normal file
12
common/mail/passwordResetToken-text.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
/* @var $this yii\web\View */
|
||||
/* @var $user common\models\User */
|
||||
|
||||
$resetLink = Yii::$app->urlManager->createAbsoluteUrl(['site/reset-password', 'token' => $user->password_reset_token]);
|
||||
?>
|
||||
Hello <?= $user->username ?>,
|
||||
|
||||
Follow the link below to reset your password:
|
||||
|
||||
<?= $resetLink ?>
|
78
common/models/LoginForm.php
Normal file
78
common/models/LoginForm.php
Normal file
@ -0,0 +1,78 @@
|
||||
<?php
|
||||
namespace common\models;
|
||||
|
||||
use Yii;
|
||||
use yii\base\Model;
|
||||
|
||||
/**
|
||||
* Login form
|
||||
*/
|
||||
class LoginForm extends Model
|
||||
{
|
||||
public $username;
|
||||
public $password;
|
||||
public $rememberMe = true;
|
||||
|
||||
private $_user;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
// username and password are both required
|
||||
[['username', 'password'], 'required'],
|
||||
// rememberMe must be a boolean value
|
||||
['rememberMe', 'boolean'],
|
||||
// password is validated by validatePassword()
|
||||
['password', 'validatePassword'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the password.
|
||||
* This method serves as the inline validation for password.
|
||||
*
|
||||
* @param string $attribute the attribute currently being validated
|
||||
* @param array $params the additional name-value pairs given in the rule
|
||||
*/
|
||||
public function validatePassword($attribute, $params)
|
||||
{
|
||||
if (!$this->hasErrors()) {
|
||||
$user = $this->getUser();
|
||||
if (!$user || !$user->validatePassword($this->password)) {
|
||||
$this->addError($attribute, 'Incorrect username or password.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600 * 24 * 30 : 0);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds user by [[username]]
|
||||
*
|
||||
* @return User|null
|
||||
*/
|
||||
protected function getUser()
|
||||
{
|
||||
if ($this->_user === null) {
|
||||
$this->_user = User::findByUsername($this->username);
|
||||
}
|
||||
|
||||
return $this->_user;
|
||||
}
|
||||
}
|
188
common/models/User.php
Normal file
188
common/models/User.php
Normal file
@ -0,0 +1,188 @@
|
||||
<?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;
|
||||
}
|
||||
}
|
37
composer.json
Normal file
37
composer.json
Normal file
@ -0,0 +1,37 @@
|
||||
{
|
||||
"name": "yiisoft/yii2-app-advanced",
|
||||
"description": "Yii 2 Advanced Project Template",
|
||||
"keywords": ["yii2", "framework", "advanced", "project template"],
|
||||
"homepage": "http://www.yiiframework.com/",
|
||||
"type": "project",
|
||||
"license": "BSD-3-Clause",
|
||||
"support": {
|
||||
"issues": "https://github.com/yiisoft/yii2/issues?state=open",
|
||||
"forum": "http://www.yiiframework.com/forum/",
|
||||
"wiki": "http://www.yiiframework.com/wiki/",
|
||||
"irc": "irc://irc.freenode.net/yii",
|
||||
"source": "https://github.com/yiisoft/yii2"
|
||||
},
|
||||
"minimum-stability": "stable",
|
||||
"require": {
|
||||
"php": ">=5.4.0",
|
||||
"yiisoft/yii2": ">=2.0.6",
|
||||
"yiisoft/yii2-bootstrap": "*",
|
||||
"yiisoft/yii2-swiftmailer": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"yiisoft/yii2-codeception": "*",
|
||||
"yiisoft/yii2-debug": "*",
|
||||
"yiisoft/yii2-gii": "*",
|
||||
"yiisoft/yii2-faker": "*"
|
||||
},
|
||||
"config": {
|
||||
"process-timeout": 1800
|
||||
},
|
||||
"extra": {
|
||||
"asset-installer-paths": {
|
||||
"npm-asset-library": "vendor/npm",
|
||||
"bower-asset-library": "vendor/bower"
|
||||
}
|
||||
}
|
||||
}
|
2
console/config/.gitignore
vendored
Normal file
2
console/config/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
main-local.php
|
||||
params-local.php
|
1
console/config/bootstrap.php
Normal file
1
console/config/bootstrap.php
Normal file
@ -0,0 +1 @@
|
||||
<?php
|
25
console/config/main.php
Normal file
25
console/config/main.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
$params = array_merge(
|
||||
require(__DIR__ . '/../../common/config/params.php'),
|
||||
require(__DIR__ . '/../../common/config/params-local.php'),
|
||||
require(__DIR__ . '/params.php'),
|
||||
require(__DIR__ . '/params-local.php')
|
||||
);
|
||||
|
||||
return [
|
||||
'id' => 'app-console',
|
||||
'basePath' => dirname(__DIR__),
|
||||
'bootstrap' => ['log'],
|
||||
'controllerNamespace' => 'console\controllers',
|
||||
'components' => [
|
||||
'log' => [
|
||||
'targets' => [
|
||||
[
|
||||
'class' => 'yii\log\FileTarget',
|
||||
'levels' => ['error', 'warning'],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
'params' => $params,
|
||||
];
|
4
console/config/params.php
Normal file
4
console/config/params.php
Normal file
@ -0,0 +1,4 @@
|
||||
<?php
|
||||
return [
|
||||
'adminEmail' => 'admin@example.com',
|
||||
];
|
0
console/controllers/.gitkeep
Normal file
0
console/controllers/.gitkeep
Normal file
34
console/migrations/m130524_201442_init.php
Normal file
34
console/migrations/m130524_201442_init.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
use yii\db\Schema;
|
||||
use yii\db\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}}', [
|
||||
'id' => $this->primaryKey(),
|
||||
'username' => $this->string()->notNull()->unique(),
|
||||
'auth_key' => $this->string(32)->notNull(),
|
||||
'password_hash' => $this->string()->notNull(),
|
||||
'password_reset_token' => $this->string()->unique(),
|
||||
'email' => $this->string()->notNull()->unique(),
|
||||
|
||||
'status' => $this->smallInteger()->notNull()->defaultValue(10),
|
||||
'created_at' => $this->integer()->notNull(),
|
||||
'updated_at' => $this->integer()->notNull(),
|
||||
], $tableOptions);
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
$this->dropTable('{{%user}}');
|
||||
}
|
||||
}
|
1
console/models/.gitkeep
Normal file
1
console/models/.gitkeep
Normal file
@ -0,0 +1 @@
|
||||
*
|
2
console/runtime/.gitignore
vendored
Normal file
2
console/runtime/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
*
|
||||
!.gitignore
|
21
environments/dev/api/config/main-local.php
Normal file
21
environments/dev/api/config/main-local.php
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
$config = [
|
||||
'components' => [
|
||||
'request' => [
|
||||
// !!! insert a secret key in the following (if it is empty) - this is required by cookie validation
|
||||
'cookieValidationKey' => '',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
if (!YII_ENV_TEST) {
|
||||
// configuration adjustments for 'dev' environment
|
||||
$config['bootstrap'][] = 'debug';
|
||||
$config['modules']['debug'] = 'yii\debug\Module';
|
||||
|
||||
$config['bootstrap'][] = 'gii';
|
||||
$config['modules']['gii'] = 'yii\gii\Module';
|
||||
}
|
||||
|
||||
return $config;
|
3
environments/dev/api/config/params-local.php
Normal file
3
environments/dev/api/config/params-local.php
Normal file
@ -0,0 +1,3 @@
|
||||
<?php
|
||||
return [
|
||||
];
|
18
environments/dev/api/web/index-test.php
Normal file
18
environments/dev/api/web/index-test.php
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
// NOTE: Make sure this file is not accessible when deployed to production
|
||||
if (!in_array(@$_SERVER['REMOTE_ADDR'], ['127.0.0.1', '::1'])) {
|
||||
die('You are not allowed to access this file.');
|
||||
}
|
||||
|
||||
defined('YII_DEBUG') or define('YII_DEBUG', true);
|
||||
defined('YII_ENV') or define('YII_ENV', 'test');
|
||||
|
||||
require(__DIR__ . '/../../vendor/autoload.php');
|
||||
require(__DIR__ . '/../../vendor/yiisoft/yii2/Yii.php');
|
||||
require(__DIR__ . '/../../common/config/bootstrap.php');
|
||||
require(__DIR__ . '/../config/bootstrap.php');
|
||||
|
||||
$config = require(__DIR__ . '/../../tests/codeception/config/api/acceptance.php');
|
||||
|
||||
(new yii\web\Application($config))->run();
|
18
environments/dev/api/web/index.php
Normal file
18
environments/dev/api/web/index.php
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
defined('YII_DEBUG') or define('YII_DEBUG', true);
|
||||
defined('YII_ENV') or define('YII_ENV', 'dev');
|
||||
|
||||
require(__DIR__ . '/../../vendor/autoload.php');
|
||||
require(__DIR__ . '/../../vendor/yiisoft/yii2/Yii.php');
|
||||
require(__DIR__ . '/../../common/config/bootstrap.php');
|
||||
require(__DIR__ . '/../config/bootstrap.php');
|
||||
|
||||
$config = yii\helpers\ArrayHelper::merge(
|
||||
require(__DIR__ . '/../../common/config/main.php'),
|
||||
require(__DIR__ . '/../../common/config/main-local.php'),
|
||||
require(__DIR__ . '/../config/main.php'),
|
||||
require(__DIR__ . '/../config/main-local.php')
|
||||
);
|
||||
|
||||
$application = new yii\web\Application($config);
|
||||
$application->run();
|
16
environments/dev/common/config/main-local.php
Normal file
16
environments/dev/common/config/main-local.php
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
return [
|
||||
'components' => [
|
||||
'db' => [
|
||||
'dsn' => 'mysql:host=localhost;dbname=ely_accounts',
|
||||
'username' => 'root',
|
||||
'password' => '',
|
||||
],
|
||||
'mailer' => [
|
||||
// send all mails to a file by default. You have to set
|
||||
// 'useFileTransport' to false and configure a transport
|
||||
// for the mailer to send real emails.
|
||||
'useFileTransport' => true,
|
||||
],
|
||||
],
|
||||
];
|
3
environments/dev/common/config/params-local.php
Normal file
3
environments/dev/common/config/params-local.php
Normal file
@ -0,0 +1,3 @@
|
||||
<?php
|
||||
return [
|
||||
];
|
7
environments/dev/console/config/main-local.php
Normal file
7
environments/dev/console/config/main-local.php
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
return [
|
||||
'bootstrap' => ['gii'],
|
||||
'modules' => [
|
||||
'gii' => 'yii\gii\Module',
|
||||
],
|
||||
];
|
3
environments/dev/console/config/params-local.php
Normal file
3
environments/dev/console/config/params-local.php
Normal file
@ -0,0 +1,3 @@
|
||||
<?php
|
||||
return [
|
||||
];
|
28
environments/dev/yii
Normal file
28
environments/dev/yii
Normal file
@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
/**
|
||||
* Yii console bootstrap file.
|
||||
*
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
defined('YII_DEBUG') or define('YII_DEBUG', true);
|
||||
defined('YII_ENV') or define('YII_ENV', 'dev');
|
||||
|
||||
require(__DIR__ . '/vendor/autoload.php');
|
||||
require(__DIR__ . '/vendor/yiisoft/yii2/Yii.php');
|
||||
require(__DIR__ . '/common/config/bootstrap.php');
|
||||
require(__DIR__ . '/console/config/bootstrap.php');
|
||||
|
||||
$config = yii\helpers\ArrayHelper::merge(
|
||||
require(__DIR__ . '/common/config/main.php'),
|
||||
require(__DIR__ . '/common/config/main-local.php'),
|
||||
require(__DIR__ . '/console/config/main.php'),
|
||||
require(__DIR__ . '/console/config/main-local.php')
|
||||
);
|
||||
|
||||
$application = new yii\console\Application($config);
|
||||
$exitCode = $application->run();
|
||||
exit($exitCode);
|
59
environments/index.php
Normal file
59
environments/index.php
Normal file
@ -0,0 +1,59 @@
|
||||
<?php
|
||||
/**
|
||||
* The manifest of files that are local to specific environment.
|
||||
* This file returns a list of environments that the application
|
||||
* may be installed under. The returned data must be in the following
|
||||
* format:
|
||||
*
|
||||
* ```php
|
||||
* return [
|
||||
* 'environment name' => [
|
||||
* 'path' => 'directory storing the local files',
|
||||
* 'skipFiles' => [
|
||||
* // list of files that should only copied once and skipped if they already exist
|
||||
* ],
|
||||
* 'setWritable' => [
|
||||
* // list of directories that should be set writable
|
||||
* ],
|
||||
* 'setExecutable' => [
|
||||
* // list of files that should be set executable
|
||||
* ],
|
||||
* 'setCookieValidationKey' => [
|
||||
* // list of config files that need to be inserted with automatically generated cookie validation keys
|
||||
* ],
|
||||
* 'createSymlink' => [
|
||||
* // list of symlinks to be created. Keys are symlinks, and values are the targets.
|
||||
* ],
|
||||
* ],
|
||||
* ];
|
||||
* ```
|
||||
*/
|
||||
return [
|
||||
'Development' => [
|
||||
'path' => 'dev',
|
||||
'setWritable' => [
|
||||
'api/runtime',
|
||||
'api/web/assets',
|
||||
],
|
||||
'setExecutable' => [
|
||||
'yii',
|
||||
'tests/codeception/bin/yii',
|
||||
],
|
||||
'setCookieValidationKey' => [
|
||||
'api/config/main-local.php',
|
||||
],
|
||||
],
|
||||
'Production' => [
|
||||
'path' => 'prod',
|
||||
'setWritable' => [
|
||||
'api/runtime',
|
||||
'api/web/assets',
|
||||
],
|
||||
'setExecutable' => [
|
||||
'yii',
|
||||
],
|
||||
'setCookieValidationKey' => [
|
||||
'api/config/main-local.php',
|
||||
],
|
||||
],
|
||||
];
|
10
environments/prod/common/config/main-local.php
Normal file
10
environments/prod/common/config/main-local.php
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
return [
|
||||
'components' => [
|
||||
'db' => [
|
||||
'dsn' => 'mysql:host=localhost;dbname=ely_accounts',
|
||||
'username' => 'root',
|
||||
'password' => '',
|
||||
],
|
||||
],
|
||||
];
|
3
environments/prod/common/config/params-local.php
Normal file
3
environments/prod/common/config/params-local.php
Normal file
@ -0,0 +1,3 @@
|
||||
<?php
|
||||
return [
|
||||
];
|
3
environments/prod/console/config/main-local.php
Normal file
3
environments/prod/console/config/main-local.php
Normal file
@ -0,0 +1,3 @@
|
||||
<?php
|
||||
return [
|
||||
];
|
3
environments/prod/console/config/params-local.php
Normal file
3
environments/prod/console/config/params-local.php
Normal file
@ -0,0 +1,3 @@
|
||||
<?php
|
||||
return [
|
||||
];
|
28
environments/prod/yii
Normal file
28
environments/prod/yii
Normal file
@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
/**
|
||||
* Yii console bootstrap file.
|
||||
*
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
defined('YII_DEBUG') or define('YII_DEBUG', false);
|
||||
defined('YII_ENV') or define('YII_ENV', 'prod');
|
||||
|
||||
require(__DIR__ . '/vendor/autoload.php');
|
||||
require(__DIR__ . '/vendor/yiisoft/yii2/Yii.php');
|
||||
require(__DIR__ . '/common/config/bootstrap.php');
|
||||
require(__DIR__ . '/console/config/bootstrap.php');
|
||||
|
||||
$config = yii\helpers\ArrayHelper::merge(
|
||||
require(__DIR__ . '/common/config/main.php'),
|
||||
require(__DIR__ . '/common/config/main-local.php'),
|
||||
require(__DIR__ . '/console/config/main.php'),
|
||||
require(__DIR__ . '/console/config/main-local.php')
|
||||
);
|
||||
|
||||
$application = new yii\console\Application($config);
|
||||
$exitCode = $application->run();
|
||||
exit($exitCode);
|
209
init
Normal file
209
init
Normal file
@ -0,0 +1,209 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
/**
|
||||
* Yii Application Initialization Tool
|
||||
*
|
||||
* In order to run in non-interactive mode:
|
||||
*
|
||||
* init --env=Development --overwrite=n
|
||||
*
|
||||
* @author Alexander Makarov <sam@rmcreative.ru>
|
||||
*
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
if (!extension_loaded('openssl')) {
|
||||
die('The OpenSSL PHP extension is required by Yii2.');
|
||||
}
|
||||
|
||||
$params = getParams();
|
||||
$root = str_replace('\\', '/', __DIR__);
|
||||
$envs = require("$root/environments/index.php");
|
||||
$envNames = array_keys($envs);
|
||||
|
||||
echo "Yii Application Initialization Tool v1.0\n\n";
|
||||
|
||||
$envName = null;
|
||||
if (empty($params['env']) || $params['env'] === '1') {
|
||||
echo "Which environment do you want the application to be initialized in?\n\n";
|
||||
foreach ($envNames as $i => $name) {
|
||||
echo " [$i] $name\n";
|
||||
}
|
||||
echo "\n Your choice [0-" . (count($envs) - 1) . ', or "q" to quit] ';
|
||||
$answer = trim(fgets(STDIN));
|
||||
|
||||
if (!ctype_digit($answer) || !in_array($answer, range(0, count($envs) - 1))) {
|
||||
echo "\n Quit initialization.\n";
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (isset($envNames[$answer])) {
|
||||
$envName = $envNames[$answer];
|
||||
}
|
||||
} else {
|
||||
$envName = $params['env'];
|
||||
}
|
||||
|
||||
if (!in_array($envName, $envNames)) {
|
||||
$envsList = implode(', ', $envNames);
|
||||
echo "\n $envName is not a valid environment. Try one of the following: $envsList. \n";
|
||||
exit(2);
|
||||
}
|
||||
|
||||
$env = $envs[$envName];
|
||||
|
||||
if (empty($params['env'])) {
|
||||
echo "\n Initialize the application under '{$envNames[$answer]}' environment? [yes|no] ";
|
||||
$answer = trim(fgets(STDIN));
|
||||
if (strncasecmp($answer, 'y', 1)) {
|
||||
echo "\n Quit initialization.\n";
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
echo "\n Start initialization ...\n\n";
|
||||
$files = getFileList("$root/environments/{$env['path']}");
|
||||
if (isset($env['skipFiles'])) {
|
||||
$skipFiles = $env['skipFiles'];
|
||||
array_walk($skipFiles, function(&$value) use($env, $root) { $value = "$root/$value"; });
|
||||
$files = array_diff($files, array_intersect_key($env['skipFiles'], array_filter($skipFiles, 'file_exists')));
|
||||
}
|
||||
$all = false;
|
||||
foreach ($files as $file) {
|
||||
if (!copyFile($root, "environments/{$env['path']}/$file", $file, $all, $params)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$callbacks = ['setCookieValidationKey', 'setWritable', 'setExecutable', 'createSymlink'];
|
||||
foreach ($callbacks as $callback) {
|
||||
if (!empty($env[$callback])) {
|
||||
$callback($root, $env[$callback]);
|
||||
}
|
||||
}
|
||||
|
||||
echo "\n ... initialization completed.\n\n";
|
||||
|
||||
function getFileList($root, $basePath = '')
|
||||
{
|
||||
$files = [];
|
||||
$handle = opendir($root);
|
||||
while (($path = readdir($handle)) !== false) {
|
||||
if ($path === '.git' || $path === '.svn' || $path === '.' || $path === '..') {
|
||||
continue;
|
||||
}
|
||||
$fullPath = "$root/$path";
|
||||
$relativePath = $basePath === '' ? $path : "$basePath/$path";
|
||||
if (is_dir($fullPath)) {
|
||||
$files = array_merge($files, getFileList($fullPath, $relativePath));
|
||||
} else {
|
||||
$files[] = $relativePath;
|
||||
}
|
||||
}
|
||||
closedir($handle);
|
||||
return $files;
|
||||
}
|
||||
|
||||
function copyFile($root, $source, $target, &$all, $params)
|
||||
{
|
||||
if (!is_file($root . '/' . $source)) {
|
||||
echo " skip $target ($source not exist)\n";
|
||||
return true;
|
||||
}
|
||||
if (is_file($root . '/' . $target)) {
|
||||
if (file_get_contents($root . '/' . $source) === file_get_contents($root . '/' . $target)) {
|
||||
echo " unchanged $target\n";
|
||||
return true;
|
||||
}
|
||||
if ($all) {
|
||||
echo " overwrite $target\n";
|
||||
} else {
|
||||
echo " exist $target\n";
|
||||
echo " ...overwrite? [Yes|No|All|Quit] ";
|
||||
|
||||
|
||||
$answer = !empty($params['overwrite']) ? $params['overwrite'] : trim(fgets(STDIN));
|
||||
if (!strncasecmp($answer, 'q', 1)) {
|
||||
return false;
|
||||
} else {
|
||||
if (!strncasecmp($answer, 'y', 1)) {
|
||||
echo " overwrite $target\n";
|
||||
} else {
|
||||
if (!strncasecmp($answer, 'a', 1)) {
|
||||
echo " overwrite $target\n";
|
||||
$all = true;
|
||||
} else {
|
||||
echo " skip $target\n";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
file_put_contents($root . '/' . $target, file_get_contents($root . '/' . $source));
|
||||
return true;
|
||||
}
|
||||
echo " generate $target\n";
|
||||
@mkdir(dirname($root . '/' . $target), 0777, true);
|
||||
file_put_contents($root . '/' . $target, file_get_contents($root . '/' . $source));
|
||||
return true;
|
||||
}
|
||||
|
||||
function getParams()
|
||||
{
|
||||
$rawParams = [];
|
||||
if (isset($_SERVER['argv'])) {
|
||||
$rawParams = $_SERVER['argv'];
|
||||
array_shift($rawParams);
|
||||
}
|
||||
|
||||
$params = [];
|
||||
foreach ($rawParams as $param) {
|
||||
if (preg_match('/^--(\w+)(=(.*))?$/', $param, $matches)) {
|
||||
$name = $matches[1];
|
||||
$params[$name] = isset($matches[3]) ? $matches[3] : true;
|
||||
} else {
|
||||
$params[] = $param;
|
||||
}
|
||||
}
|
||||
return $params;
|
||||
}
|
||||
|
||||
function setWritable($root, $paths)
|
||||
{
|
||||
foreach ($paths as $writable) {
|
||||
echo " chmod 0777 $writable\n";
|
||||
@chmod("$root/$writable", 0777);
|
||||
}
|
||||
}
|
||||
|
||||
function setExecutable($root, $paths)
|
||||
{
|
||||
foreach ($paths as $executable) {
|
||||
echo " chmod 0755 $executable\n";
|
||||
@chmod("$root/$executable", 0755);
|
||||
}
|
||||
}
|
||||
|
||||
function setCookieValidationKey($root, $paths)
|
||||
{
|
||||
foreach ($paths as $file) {
|
||||
echo " generate cookie validation key in $file\n";
|
||||
$file = $root . '/' . $file;
|
||||
$length = 32;
|
||||
$bytes = openssl_random_pseudo_bytes($length);
|
||||
$key = strtr(substr(base64_encode($bytes), 0, $length), '+/=', '_-.');
|
||||
$content = preg_replace('/(("|\')cookieValidationKey("|\')\s*=>\s*)(""|\'\')/', "\\1'$key'", file_get_contents($file));
|
||||
file_put_contents($file, $content);
|
||||
}
|
||||
}
|
||||
|
||||
function createSymlink($root, $links) {
|
||||
foreach ($links as $link => $target) {
|
||||
echo " symlink " . $root . "/" . $target . " " . $root . "/" . $link . "\n";
|
||||
//first removing folders to avoid errors if the folder already exists
|
||||
@rmdir($root . "/" . $link);
|
||||
@symlink($root . "/" . $target, $root . "/" . $link);
|
||||
}
|
||||
}
|
20
init.bat
Normal file
20
init.bat
Normal file
@ -0,0 +1,20 @@
|
||||
@echo off
|
||||
|
||||
rem -------------------------------------------------------------
|
||||
rem Yii command line init script for Windows.
|
||||
rem
|
||||
rem @author Qiang Xue <qiang.xue@gmail.com>
|
||||
rem @link http://www.yiiframework.com/
|
||||
rem @copyright Copyright (c) 2008 Yii Software LLC
|
||||
rem @license http://www.yiiframework.com/license/
|
||||
rem -------------------------------------------------------------
|
||||
|
||||
@setlocal
|
||||
|
||||
set YII_PATH=%~dp0
|
||||
|
||||
if "%PHP_COMMAND%" == "" set PHP_COMMAND=php.exe
|
||||
|
||||
"%PHP_COMMAND%" "%YII_PATH%init" %*
|
||||
|
||||
@endlocal
|
58
tests/README.md
Normal file
58
tests/README.md
Normal file
@ -0,0 +1,58 @@
|
||||
This directory contains various tests for the advanced applications.
|
||||
|
||||
Tests in `codeception` directory are developed with [Codeception PHP Testing Framework](http://codeception.com/).
|
||||
|
||||
After creating and setting up the advanced application, follow these steps to prepare for the tests:
|
||||
|
||||
1. Install Codeception if it's not yet installed:
|
||||
|
||||
```
|
||||
composer global require "codeception/codeception=2.0.*" "codeception/specify=*" "codeception/verify=*"
|
||||
```
|
||||
|
||||
If you've never used Composer for global packages run `composer global status`. It should output:
|
||||
|
||||
```
|
||||
Changed current directory to <directory>
|
||||
```
|
||||
|
||||
Then add `<directory>/vendor/bin` to you `PATH` environment variable. Now you're able to use `codecept` from command
|
||||
line globally.
|
||||
|
||||
2. Install faker extension by running the following from template root directory where `composer.json` is:
|
||||
|
||||
```
|
||||
composer require --dev yiisoft/yii2-faker:*
|
||||
```
|
||||
|
||||
3. Create `yii2_advanced_tests` database then update it by applying migrations:
|
||||
|
||||
```
|
||||
codeception/bin/yii migrate
|
||||
```
|
||||
|
||||
4. In order to be able to run acceptance tests you need to start a webserver. The simplest way is to use PHP built in
|
||||
webserver. In the root directory where `common`, `frontend` etc. are execute the following:
|
||||
|
||||
```
|
||||
php -S localhost:8080
|
||||
```
|
||||
|
||||
5. Now you can run the tests with the following commands, assuming you are in the `tests/codeception` directory:
|
||||
|
||||
```
|
||||
# frontend tests
|
||||
cd frontend
|
||||
codecept build
|
||||
codecept run
|
||||
|
||||
# backend tests
|
||||
|
||||
cd backend
|
||||
codecept build
|
||||
codecept run
|
||||
|
||||
# etc.
|
||||
```
|
||||
|
||||
If you already have run `codecept build` for each application, you can skip that step and run all tests by a single `codecept run`.
|
10
tests/codeception.yml
Normal file
10
tests/codeception.yml
Normal file
@ -0,0 +1,10 @@
|
||||
include:
|
||||
- codeception/common
|
||||
- codeception/console
|
||||
- codeception/api
|
||||
|
||||
paths:
|
||||
log: codeception/_output
|
||||
|
||||
settings:
|
||||
colors: true
|
2
tests/codeception/_output/.gitignore
vendored
Normal file
2
tests/codeception/_output/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
*
|
||||
!.gitignore
|
4
tests/codeception/api/.gitignore
vendored
Normal file
4
tests/codeception/api/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
# these files are auto generated by codeception build
|
||||
/unit/UnitTester.php
|
||||
/functional/FunctionalTester.php
|
||||
/acceptance/AcceptanceTester.php
|
23
tests/codeception/api/_bootstrap.php
Normal file
23
tests/codeception/api/_bootstrap.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
defined('YII_DEBUG') or define('YII_DEBUG', true);
|
||||
defined('YII_ENV') or define('YII_ENV', 'test');
|
||||
|
||||
defined('YII_APP_BASE_PATH') or define('YII_APP_BASE_PATH', dirname(dirname(dirname(__DIR__))));
|
||||
|
||||
defined('API_ENTRY_URL') or define('API_ENTRY_URL', parse_url(\Codeception\Configuration::config()['config']['test_entry_url'], PHP_URL_PATH));
|
||||
defined('API_ENTRY_FILE') or define('API_ENTRY_FILE', YII_APP_BASE_PATH . '/api/web/index-test.php');
|
||||
|
||||
require_once(YII_APP_BASE_PATH . '/vendor/autoload.php');
|
||||
require_once(YII_APP_BASE_PATH . '/vendor/yiisoft/yii2/Yii.php');
|
||||
require_once(YII_APP_BASE_PATH . '/common/config/bootstrap.php');
|
||||
require_once(YII_APP_BASE_PATH . '/api/config/bootstrap.php');
|
||||
|
||||
// set correct script paths
|
||||
|
||||
// the entry script file path for functional and acceptance tests
|
||||
$_SERVER['SCRIPT_FILENAME'] = API_ENTRY_FILE;
|
||||
$_SERVER['SCRIPT_NAME'] = API_ENTRY_URL;
|
||||
$_SERVER['SERVER_NAME'] = parse_url(\Codeception\Configuration::config()['config']['test_entry_url'], PHP_URL_HOST);
|
||||
$_SERVER['SERVER_PORT'] = parse_url(\Codeception\Configuration::config()['config']['test_entry_url'], PHP_URL_PORT) ?: '80';
|
||||
|
||||
Yii::setAlias('@tests', dirname(dirname(__DIR__)));
|
2
tests/codeception/api/_output/.gitignore
vendored
Normal file
2
tests/codeception/api/_output/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
*
|
||||
!.gitignore
|
14
tests/codeception/api/_pages/AboutPage.php
Normal file
14
tests/codeception/api/_pages/AboutPage.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace tests\codeception\api\_pages;
|
||||
|
||||
use yii\codeception\BasePage;
|
||||
|
||||
/**
|
||||
* Represents about page
|
||||
* @property \codeception_api\AcceptanceTester|\codeception_api\FunctionalTester $actor
|
||||
*/
|
||||
class AboutPage extends BasePage
|
||||
{
|
||||
public $route = 'site/about';
|
||||
}
|
26
tests/codeception/api/_pages/ContactPage.php
Normal file
26
tests/codeception/api/_pages/ContactPage.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace tests\codeception\api\_pages;
|
||||
|
||||
use yii\codeception\BasePage;
|
||||
|
||||
/**
|
||||
* Represents contact page
|
||||
* @property \codeception_api\AcceptanceTester|\codeception_api\FunctionalTester $actor
|
||||
*/
|
||||
class ContactPage extends BasePage
|
||||
{
|
||||
public $route = 'site/contact';
|
||||
|
||||
/**
|
||||
* @param array $contactData
|
||||
*/
|
||||
public function submit(array $contactData)
|
||||
{
|
||||
foreach ($contactData as $field => $value) {
|
||||
$inputType = $field === 'body' ? 'textarea' : 'input';
|
||||
$this->actor->fillField($inputType . '[name="ContactForm[' . $field . ']"]', $value);
|
||||
}
|
||||
$this->actor->click('contact-button');
|
||||
}
|
||||
}
|
27
tests/codeception/api/_pages/SignupPage.php
Normal file
27
tests/codeception/api/_pages/SignupPage.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace tests\codeception\api\_pages;
|
||||
|
||||
use \yii\codeception\BasePage;
|
||||
|
||||
/**
|
||||
* Represents signup page
|
||||
* @property \codeception_api\AcceptanceTester|\codeception_api\FunctionalTester $actor
|
||||
*/
|
||||
class SignupPage extends BasePage
|
||||
{
|
||||
|
||||
public $route = 'site/signup';
|
||||
|
||||
/**
|
||||
* @param array $signupData
|
||||
*/
|
||||
public function submit(array $signupData)
|
||||
{
|
||||
foreach ($signupData as $field => $value) {
|
||||
$inputType = $field === 'body' ? 'textarea' : 'input';
|
||||
$this->actor->fillField($inputType . '[name="SignupForm[' . $field . ']"]', $value);
|
||||
}
|
||||
$this->actor->click('signup-button');
|
||||
}
|
||||
}
|
28
tests/codeception/api/acceptance.suite.yml
Normal file
28
tests/codeception/api/acceptance.suite.yml
Normal file
@ -0,0 +1,28 @@
|
||||
# Codeception Test Suite Configuration
|
||||
|
||||
# suite for acceptance tests.
|
||||
# perform tests in browser using the Selenium-like tools.
|
||||
# powered by Mink (http://mink.behat.org).
|
||||
# (tip: that's what your customer will see).
|
||||
# (tip: test your ajax and javascript by one of Mink drivers).
|
||||
|
||||
# RUN `build` COMMAND AFTER ADDING/REMOVING MODULES.
|
||||
|
||||
class_name: AcceptanceTester
|
||||
modules:
|
||||
enabled:
|
||||
- PhpBrowser
|
||||
- tests\codeception\common\_support\FixtureHelper
|
||||
# you can use WebDriver instead of PhpBrowser to test javascript and ajax.
|
||||
# This will require you to install selenium. See http://codeception.com/docs/04-AcceptanceTests#Selenium
|
||||
# "restart" option is used by the WebDriver to start each time per test-file new session and cookies,
|
||||
# it is useful if you want to login in your app in each test.
|
||||
# - WebDriver
|
||||
config:
|
||||
PhpBrowser:
|
||||
# PLEASE ADJUST IT TO THE ACTUAL ENTRY POINT WITHOUT PATH INFO
|
||||
url: http://localhost:8080
|
||||
# WebDriver:
|
||||
# url: http://localhost:8080
|
||||
# browser: firefox
|
||||
# restart: true
|
10
tests/codeception/api/acceptance/AboutCept.php
Normal file
10
tests/codeception/api/acceptance/AboutCept.php
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
use tests\codeception\api\AcceptanceTester;
|
||||
use tests\codeception\api\_pages\AboutPage;
|
||||
|
||||
/* @var $scenario Codeception\Scenario */
|
||||
|
||||
$I = new AcceptanceTester($scenario);
|
||||
$I->wantTo('ensure that about works');
|
||||
AboutPage::openBy($I);
|
||||
$I->see('About', 'h1');
|
56
tests/codeception/api/acceptance/ContactCept.php
Normal file
56
tests/codeception/api/acceptance/ContactCept.php
Normal file
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
use tests\codeception\api\AcceptanceTester;
|
||||
use tests\codeception\api\_pages\ContactPage;
|
||||
|
||||
/* @var $scenario Codeception\Scenario */
|
||||
|
||||
$I = new AcceptanceTester($scenario);
|
||||
$I->wantTo('ensure that contact works');
|
||||
|
||||
$contactPage = ContactPage::openBy($I);
|
||||
|
||||
$I->see('Contact', 'h1');
|
||||
|
||||
$I->amGoingTo('submit contact form with no data');
|
||||
$contactPage->submit([]);
|
||||
if (method_exists($I, 'wait')) {
|
||||
$I->wait(3); // only for selenium
|
||||
}
|
||||
$I->expectTo('see validations errors');
|
||||
$I->see('Contact', 'h1');
|
||||
$I->see('Name cannot be blank', '.help-block');
|
||||
$I->see('Email cannot be blank', '.help-block');
|
||||
$I->see('Subject cannot be blank', '.help-block');
|
||||
$I->see('Body cannot be blank', '.help-block');
|
||||
$I->see('The verification code is incorrect', '.help-block');
|
||||
|
||||
$I->amGoingTo('submit contact form with not correct email');
|
||||
$contactPage->submit([
|
||||
'name' => 'tester',
|
||||
'email' => 'tester.email',
|
||||
'subject' => 'test subject',
|
||||
'body' => 'test content',
|
||||
'verifyCode' => 'testme',
|
||||
]);
|
||||
if (method_exists($I, 'wait')) {
|
||||
$I->wait(3); // only for selenium
|
||||
}
|
||||
$I->expectTo('see that email adress is wrong');
|
||||
$I->dontSee('Name cannot be blank', '.help-block');
|
||||
$I->see('Email is not a valid email address.', '.help-block');
|
||||
$I->dontSee('Subject cannot be blank', '.help-block');
|
||||
$I->dontSee('Body cannot be blank', '.help-block');
|
||||
$I->dontSee('The verification code is incorrect', '.help-block');
|
||||
|
||||
$I->amGoingTo('submit contact form with correct data');
|
||||
$contactPage->submit([
|
||||
'name' => 'tester',
|
||||
'email' => 'tester@example.com',
|
||||
'subject' => 'test subject',
|
||||
'body' => 'test content',
|
||||
'verifyCode' => 'testme',
|
||||
]);
|
||||
if (method_exists($I, 'wait')) {
|
||||
$I->wait(3); // only for selenium
|
||||
}
|
||||
$I->see('Thank you for contacting us. We will respond to you as soon as possible.');
|
12
tests/codeception/api/acceptance/HomeCept.php
Normal file
12
tests/codeception/api/acceptance/HomeCept.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
use tests\codeception\api\AcceptanceTester;
|
||||
|
||||
/* @var $scenario Codeception\Scenario */
|
||||
|
||||
$I = new AcceptanceTester($scenario);
|
||||
$I->wantTo('ensure that home page works');
|
||||
$I->amOnPage(Yii::$app->homeUrl);
|
||||
$I->see('My Company');
|
||||
$I->seeLink('About');
|
||||
$I->click('About');
|
||||
$I->see('This is the About page.');
|
34
tests/codeception/api/acceptance/LoginCept.php
Normal file
34
tests/codeception/api/acceptance/LoginCept.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
use tests\codeception\api\AcceptanceTester;
|
||||
use tests\codeception\common\_pages\LoginPage;
|
||||
|
||||
/* @var $scenario Codeception\Scenario */
|
||||
|
||||
$I = new AcceptanceTester($scenario);
|
||||
$I->wantTo('ensure login page works');
|
||||
|
||||
$loginPage = LoginPage::openBy($I);
|
||||
|
||||
$I->amGoingTo('submit login form with no data');
|
||||
$loginPage->login('', '');
|
||||
$I->expectTo('see validations errors');
|
||||
$I->see('Username cannot be blank.', '.help-block');
|
||||
$I->see('Password cannot be blank.', '.help-block');
|
||||
|
||||
$I->amGoingTo('try to login with wrong credentials');
|
||||
$I->expectTo('see validations errors');
|
||||
$loginPage->login('admin', 'wrong');
|
||||
$I->expectTo('see validations errors');
|
||||
$I->see('Incorrect username or password.', '.help-block');
|
||||
|
||||
$I->amGoingTo('try to login with correct credentials');
|
||||
$loginPage->login('erau', 'password_0');
|
||||
$I->expectTo('see that user is logged');
|
||||
$I->seeLink('Logout (erau)');
|
||||
$I->dontSeeLink('Login');
|
||||
$I->dontSeeLink('Signup');
|
||||
/** Uncomment if using WebDriver
|
||||
* $I->click('Logout (erau)');
|
||||
* $I->dontSeeLink('Logout (erau)');
|
||||
* $I->seeLink('Login');
|
||||
*/
|
82
tests/codeception/api/acceptance/SignupCest.php
Normal file
82
tests/codeception/api/acceptance/SignupCest.php
Normal file
@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
namespace tests\codeception\api\acceptance;
|
||||
|
||||
use tests\codeception\api\_pages\SignupPage;
|
||||
use common\models\User;
|
||||
|
||||
class SignupCest
|
||||
{
|
||||
|
||||
/**
|
||||
* This method is called before each cest class test method
|
||||
* @param \Codeception\Event\TestEvent $event
|
||||
*/
|
||||
public function _before($event)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called after each cest class test method, even if test failed.
|
||||
* @param \Codeception\Event\TestEvent $event
|
||||
*/
|
||||
public function _after($event)
|
||||
{
|
||||
User::deleteAll([
|
||||
'email' => 'tester.email@example.com',
|
||||
'username' => 'tester',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called when test fails.
|
||||
* @param \Codeception\Event\FailEvent $event
|
||||
*/
|
||||
public function _fail($event)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \codeception_api\AcceptanceTester $I
|
||||
* @param \Codeception\Scenario $scenario
|
||||
*/
|
||||
public function testUserSignup($I, $scenario)
|
||||
{
|
||||
$I->wantTo('ensure that signup works');
|
||||
|
||||
$signupPage = SignupPage::openBy($I);
|
||||
$I->see('Signup', 'h1');
|
||||
$I->see('Please fill out the following fields to signup:');
|
||||
|
||||
$I->amGoingTo('submit signup form with no data');
|
||||
|
||||
$signupPage->submit([]);
|
||||
|
||||
$I->expectTo('see validation errors');
|
||||
$I->see('Username cannot be blank.', '.help-block');
|
||||
$I->see('Email cannot be blank.', '.help-block');
|
||||
$I->see('Password cannot be blank.', '.help-block');
|
||||
|
||||
$I->amGoingTo('submit signup form with not correct email');
|
||||
$signupPage->submit([
|
||||
'username' => 'tester',
|
||||
'email' => 'tester.email',
|
||||
'password' => 'tester_password',
|
||||
]);
|
||||
|
||||
$I->expectTo('see that email address is wrong');
|
||||
$I->dontSee('Username cannot be blank.', '.help-block');
|
||||
$I->dontSee('Password cannot be blank.', '.help-block');
|
||||
$I->see('Email is not a valid email address.', '.help-block');
|
||||
|
||||
$I->amGoingTo('submit signup form with correct email');
|
||||
$signupPage->submit([
|
||||
'username' => 'tester',
|
||||
'email' => 'tester.email@example.com',
|
||||
'password' => 'tester_password',
|
||||
]);
|
||||
|
||||
$I->expectTo('see that user logged in');
|
||||
$I->seeLink('Logout (tester)');
|
||||
}
|
||||
}
|
2
tests/codeception/api/acceptance/_bootstrap.php
Normal file
2
tests/codeception/api/acceptance/_bootstrap.php
Normal file
@ -0,0 +1,2 @@
|
||||
<?php
|
||||
new yii\web\Application(require(dirname(dirname(__DIR__)) . '/config/api/acceptance.php'));
|
17
tests/codeception/api/codeception.yml
Normal file
17
tests/codeception/api/codeception.yml
Normal file
@ -0,0 +1,17 @@
|
||||
namespace: tests\codeception\api
|
||||
actor: Tester
|
||||
paths:
|
||||
tests: .
|
||||
log: _output
|
||||
data: _data
|
||||
helpers: _support
|
||||
settings:
|
||||
bootstrap: _bootstrap.php
|
||||
suite_class: \PHPUnit_Framework_TestSuite
|
||||
colors: true
|
||||
memory_limit: 1024M
|
||||
log: true
|
||||
config:
|
||||
# the entry script URL (with host info) for functional and acceptance tests
|
||||
# PLEASE ADJUST IT TO THE ACTUAL ENTRY SCRIPT URL
|
||||
test_entry_url: http://localhost:8080/api/web/index-test.php
|
17
tests/codeception/api/functional.suite.yml
Normal file
17
tests/codeception/api/functional.suite.yml
Normal file
@ -0,0 +1,17 @@
|
||||
# Codeception Test Suite Configuration
|
||||
|
||||
# suite for functional (integration) tests.
|
||||
# emulate web requests and make application process them.
|
||||
# (tip: better to use with frameworks).
|
||||
|
||||
# RUN `build` COMMAND AFTER ADDING/REMOVING MODULES.
|
||||
#basic/web/index.php
|
||||
class_name: FunctionalTester
|
||||
modules:
|
||||
enabled:
|
||||
- Filesystem
|
||||
- Yii2
|
||||
- tests\codeception\common\_support\FixtureHelper
|
||||
config:
|
||||
Yii2:
|
||||
configFile: '../config/api/functional.php'
|
10
tests/codeception/api/functional/AboutCept.php
Normal file
10
tests/codeception/api/functional/AboutCept.php
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
use tests\codeception\api\FunctionalTester;
|
||||
use tests\codeception\api\_pages\AboutPage;
|
||||
|
||||
/* @var $scenario Codeception\Scenario */
|
||||
|
||||
$I = new FunctionalTester($scenario);
|
||||
$I->wantTo('ensure that about works');
|
||||
AboutPage::openBy($I);
|
||||
$I->see('About', 'h1');
|
47
tests/codeception/api/functional/ContactCept.php
Normal file
47
tests/codeception/api/functional/ContactCept.php
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
use tests\codeception\api\FunctionalTester;
|
||||
use tests\codeception\api\_pages\ContactPage;
|
||||
|
||||
/* @var $scenario Codeception\Scenario */
|
||||
|
||||
$I = new FunctionalTester($scenario);
|
||||
$I->wantTo('ensure that contact works');
|
||||
|
||||
$contactPage = ContactPage::openBy($I);
|
||||
|
||||
$I->see('Contact', 'h1');
|
||||
|
||||
$I->amGoingTo('submit contact form with no data');
|
||||
$contactPage->submit([]);
|
||||
$I->expectTo('see validations errors');
|
||||
$I->see('Contact', 'h1');
|
||||
$I->see('Name cannot be blank', '.help-block');
|
||||
$I->see('Email cannot be blank', '.help-block');
|
||||
$I->see('Subject cannot be blank', '.help-block');
|
||||
$I->see('Body cannot be blank', '.help-block');
|
||||
$I->see('The verification code is incorrect', '.help-block');
|
||||
|
||||
$I->amGoingTo('submit contact form with not correct email');
|
||||
$contactPage->submit([
|
||||
'name' => 'tester',
|
||||
'email' => 'tester.email',
|
||||
'subject' => 'test subject',
|
||||
'body' => 'test content',
|
||||
'verifyCode' => 'testme',
|
||||
]);
|
||||
$I->expectTo('see that email adress is wrong');
|
||||
$I->dontSee('Name cannot be blank', '.help-block');
|
||||
$I->see('Email is not a valid email address.', '.help-block');
|
||||
$I->dontSee('Subject cannot be blank', '.help-block');
|
||||
$I->dontSee('Body cannot be blank', '.help-block');
|
||||
$I->dontSee('The verification code is incorrect', '.help-block');
|
||||
|
||||
$I->amGoingTo('submit contact form with correct data');
|
||||
$contactPage->submit([
|
||||
'name' => 'tester',
|
||||
'email' => 'tester@example.com',
|
||||
'subject' => 'test subject',
|
||||
'body' => 'test content',
|
||||
'verifyCode' => 'testme',
|
||||
]);
|
||||
$I->see('Thank you for contacting us. We will respond to you as soon as possible.');
|
12
tests/codeception/api/functional/HomeCept.php
Normal file
12
tests/codeception/api/functional/HomeCept.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
use tests\codeception\api\FunctionalTester;
|
||||
|
||||
/* @var $scenario Codeception\Scenario */
|
||||
|
||||
$I = new FunctionalTester($scenario);
|
||||
$I->wantTo('ensure that home page works');
|
||||
$I->amOnPage(Yii::$app->homeUrl);
|
||||
$I->see('My Company');
|
||||
$I->seeLink('About');
|
||||
$I->click('About');
|
||||
$I->see('This is the About page.');
|
29
tests/codeception/api/functional/LoginCept.php
Normal file
29
tests/codeception/api/functional/LoginCept.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
use tests\codeception\api\FunctionalTester;
|
||||
use tests\codeception\common\_pages\LoginPage;
|
||||
|
||||
/* @var $scenario Codeception\Scenario */
|
||||
|
||||
$I = new FunctionalTester($scenario);
|
||||
$I->wantTo('ensure login page works');
|
||||
|
||||
$loginPage = LoginPage::openBy($I);
|
||||
|
||||
$I->amGoingTo('submit login form with no data');
|
||||
$loginPage->login('', '');
|
||||
$I->expectTo('see validations errors');
|
||||
$I->see('Username cannot be blank.', '.help-block');
|
||||
$I->see('Password cannot be blank.', '.help-block');
|
||||
|
||||
$I->amGoingTo('try to login with wrong credentials');
|
||||
$I->expectTo('see validations errors');
|
||||
$loginPage->login('admin', 'wrong');
|
||||
$I->expectTo('see validations errors');
|
||||
$I->see('Incorrect username or password.', '.help-block');
|
||||
|
||||
$I->amGoingTo('try to login with correct credentials');
|
||||
$loginPage->login('erau', 'password_0');
|
||||
$I->expectTo('see that user is logged');
|
||||
$I->seeLink('Logout (erau)');
|
||||
$I->dontSeeLink('Login');
|
||||
$I->dontSeeLink('Signup');
|
90
tests/codeception/api/functional/SignupCest.php
Normal file
90
tests/codeception/api/functional/SignupCest.php
Normal file
@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
namespace tests\codeception\api\functional;
|
||||
|
||||
use tests\codeception\api\_pages\SignupPage;
|
||||
use common\models\User;
|
||||
|
||||
class SignupCest
|
||||
{
|
||||
|
||||
/**
|
||||
* This method is called before each cest class test method
|
||||
* @param \Codeception\Event\TestEvent $event
|
||||
*/
|
||||
public function _before($event)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called after each cest class test method, even if test failed.
|
||||
* @param \Codeception\Event\TestEvent $event
|
||||
*/
|
||||
public function _after($event)
|
||||
{
|
||||
User::deleteAll([
|
||||
'email' => 'tester.email@example.com',
|
||||
'username' => 'tester',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called when test fails.
|
||||
* @param \Codeception\Event\FailEvent $event
|
||||
*/
|
||||
public function _fail($event)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param \codeception_api\FunctionalTester $I
|
||||
* @param \Codeception\Scenario $scenario
|
||||
*/
|
||||
public function testUserSignup($I, $scenario)
|
||||
{
|
||||
$I->wantTo('ensure that signup works');
|
||||
|
||||
$signupPage = SignupPage::openBy($I);
|
||||
$I->see('Signup', 'h1');
|
||||
$I->see('Please fill out the following fields to signup:');
|
||||
|
||||
$I->amGoingTo('submit signup form with no data');
|
||||
|
||||
$signupPage->submit([]);
|
||||
|
||||
$I->expectTo('see validation errors');
|
||||
$I->see('Username cannot be blank.', '.help-block');
|
||||
$I->see('Email cannot be blank.', '.help-block');
|
||||
$I->see('Password cannot be blank.', '.help-block');
|
||||
|
||||
$I->amGoingTo('submit signup form with not correct email');
|
||||
$signupPage->submit([
|
||||
'username' => 'tester',
|
||||
'email' => 'tester.email',
|
||||
'password' => 'tester_password',
|
||||
]);
|
||||
|
||||
$I->expectTo('see that email address is wrong');
|
||||
$I->dontSee('Username cannot be blank.', '.help-block');
|
||||
$I->dontSee('Password cannot be blank.', '.help-block');
|
||||
$I->see('Email is not a valid email address.', '.help-block');
|
||||
|
||||
$I->amGoingTo('submit signup form with correct email');
|
||||
$signupPage->submit([
|
||||
'username' => 'tester',
|
||||
'email' => 'tester.email@example.com',
|
||||
'password' => 'tester_password',
|
||||
]);
|
||||
|
||||
$I->expectTo('see that user is created');
|
||||
$I->seeRecord('common\models\User', [
|
||||
'username' => 'tester',
|
||||
'email' => 'tester.email@example.com',
|
||||
]);
|
||||
|
||||
$I->expectTo('see that user logged in');
|
||||
$I->seeLink('Logout (tester)');
|
||||
}
|
||||
}
|
3
tests/codeception/api/functional/_bootstrap.php
Normal file
3
tests/codeception/api/functional/_bootstrap.php
Normal file
@ -0,0 +1,3 @@
|
||||
<?php
|
||||
|
||||
new yii\web\Application(require(dirname(dirname(__DIR__)) . '/config/api/functional.php'));
|
6
tests/codeception/api/unit.suite.yml
Normal file
6
tests/codeception/api/unit.suite.yml
Normal file
@ -0,0 +1,6 @@
|
||||
# Codeception Test Suite Configuration
|
||||
|
||||
# suite for unit (internal) tests.
|
||||
# RUN `build` COMMAND AFTER ADDING/REMOVING MODULES.
|
||||
|
||||
class_name: UnitTester
|
11
tests/codeception/api/unit/DbTestCase.php
Normal file
11
tests/codeception/api/unit/DbTestCase.php
Normal file
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace tests\codeception\api\unit;
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
class DbTestCase extends \yii\codeception\DbTestCase
|
||||
{
|
||||
public $appConfig = '@tests/codeception/config/api/unit.php';
|
||||
}
|
11
tests/codeception/api/unit/TestCase.php
Normal file
11
tests/codeception/api/unit/TestCase.php
Normal file
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace tests\codeception\api\unit;
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
class TestCase extends \yii\codeception\TestCase
|
||||
{
|
||||
public $appConfig = '@tests/codeception/config/api/unit.php';
|
||||
}
|
2
tests/codeception/api/unit/_bootstrap.php
Normal file
2
tests/codeception/api/unit/_bootstrap.php
Normal file
@ -0,0 +1,2 @@
|
||||
<?php
|
||||
// Here you can initialize variables that will for your tests
|
23
tests/codeception/api/unit/fixtures/data/models/user.php
Normal file
23
tests/codeception/api/unit/fixtures/data/models/user.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
[
|
||||
'username' => 'okirlin',
|
||||
'auth_key' => 'iwTNae9t34OmnK6l4vT4IeaTk-YWI2Rv',
|
||||
'password_hash' => '$2y$13$CXT0Rkle1EMJ/c1l5bylL.EylfmQ39O5JlHJVFpNn618OUS1HwaIi',
|
||||
'password_reset_token' => 't5GU9NwpuGYSfb7FEZMAxqtuz2PkEvv_' . time(),
|
||||
'created_at' => '1391885313',
|
||||
'updated_at' => '1391885313',
|
||||
'email' => 'brady.renner@rutherford.com',
|
||||
],
|
||||
[
|
||||
'username' => 'troy.becker',
|
||||
'auth_key' => 'EdKfXrx88weFMV0vIxuTMWKgfK2tS3Lp',
|
||||
'password_hash' => '$2y$13$g5nv41Px7VBqhS3hVsVN2.MKfgT3jFdkXEsMC4rQJLfaMa7VaJqL2',
|
||||
'password_reset_token' => '4BSNyiZNAuxjs5Mty990c47sVrgllIi_' . time(),
|
||||
'created_at' => '1391885313',
|
||||
'updated_at' => '1391885313',
|
||||
'email' => 'nicolas.dianna@hotmail.com',
|
||||
'status' => '0',
|
||||
],
|
||||
];
|
59
tests/codeception/api/unit/models/ContactFormTest.php
Normal file
59
tests/codeception/api/unit/models/ContactFormTest.php
Normal file
@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
namespace tests\codeception\api\unit\models;
|
||||
|
||||
use Yii;
|
||||
use tests\codeception\api\unit\TestCase;
|
||||
use api\models\ContactForm;
|
||||
|
||||
class ContactFormTest extends TestCase
|
||||
{
|
||||
|
||||
use \Codeception\Specify;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
Yii::$app->mailer->fileTransportCallback = function ($mailer, $message) {
|
||||
return 'testing_message.eml';
|
||||
};
|
||||
}
|
||||
|
||||
protected function tearDown()
|
||||
{
|
||||
unlink($this->getMessageFile());
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
public function testContact()
|
||||
{
|
||||
$model = new ContactForm();
|
||||
|
||||
$model->attributes = [
|
||||
'name' => 'Tester',
|
||||
'email' => 'tester@example.com',
|
||||
'subject' => 'very important letter subject',
|
||||
'body' => 'body of current message',
|
||||
];
|
||||
|
||||
$model->sendEmail('admin@example.com');
|
||||
|
||||
$this->specify('email should be send', function () {
|
||||
expect('email file should exist', file_exists($this->getMessageFile()))->true();
|
||||
});
|
||||
|
||||
$this->specify('message should contain correct data', function () use ($model) {
|
||||
$emailMessage = file_get_contents($this->getMessageFile());
|
||||
|
||||
expect('email should contain user name', $emailMessage)->contains($model->name);
|
||||
expect('email should contain sender email', $emailMessage)->contains($model->email);
|
||||
expect('email should contain subject', $emailMessage)->contains($model->subject);
|
||||
expect('email should contain body', $emailMessage)->contains($model->body);
|
||||
});
|
||||
}
|
||||
|
||||
private function getMessageFile()
|
||||
{
|
||||
return Yii::getAlias(Yii::$app->mailer->fileTransportPath) . '/testing_message.eml';
|
||||
}
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
namespace tests\codeception\api\models;
|
||||
|
||||
use Yii;
|
||||
use tests\codeception\api\unit\DbTestCase;
|
||||
use api\models\PasswordResetRequestForm;
|
||||
use tests\codeception\common\fixtures\UserFixture;
|
||||
use common\models\User;
|
||||
use Codeception\Specify;
|
||||
|
||||
class PasswordResetRequestFormTest extends DbTestCase
|
||||
{
|
||||
use Specify;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
Yii::$app->mailer->fileTransportCallback = function ($mailer, $message) {
|
||||
return 'testing_message.eml';
|
||||
};
|
||||
}
|
||||
|
||||
protected function tearDown()
|
||||
{
|
||||
@unlink($this->getMessageFile());
|
||||
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
public function testSendEmailWrongUser()
|
||||
{
|
||||
$this->specify('no user with such email, message should not be sent', function () {
|
||||
|
||||
$model = new PasswordResetRequestForm();
|
||||
$model->email = 'not-existing-email@example.com';
|
||||
|
||||
expect('email not sent', $model->sendEmail())->false();
|
||||
|
||||
});
|
||||
|
||||
$this->specify('user is not active, message should not be sent', function () {
|
||||
|
||||
$model = new PasswordResetRequestForm();
|
||||
$model->email = $this->user[1]['email'];
|
||||
|
||||
expect('email not sent', $model->sendEmail())->false();
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
public function testSendEmailCorrectUser()
|
||||
{
|
||||
$model = new PasswordResetRequestForm();
|
||||
$model->email = $this->user[0]['email'];
|
||||
$user = User::findOne(['password_reset_token' => $this->user[0]['password_reset_token']]);
|
||||
|
||||
expect('email sent', $model->sendEmail())->true();
|
||||
expect('user has valid token', $user->password_reset_token)->notNull();
|
||||
|
||||
$this->specify('message has correct format', function () use ($model) {
|
||||
|
||||
expect('message file exists', file_exists($this->getMessageFile()))->true();
|
||||
|
||||
$message = file_get_contents($this->getMessageFile());
|
||||
expect('message "from" is correct', $message)->contains(Yii::$app->params['supportEmail']);
|
||||
expect('message "to" is correct', $message)->contains($model->email);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
public function fixtures()
|
||||
{
|
||||
return [
|
||||
'user' => [
|
||||
'class' => UserFixture::className(),
|
||||
'dataFile' => '@tests/codeception/api/unit/fixtures/data/models/user.php'
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
private function getMessageFile()
|
||||
{
|
||||
return Yii::getAlias(Yii::$app->mailer->fileTransportPath) . '/testing_message.eml';
|
||||
}
|
||||
}
|
43
tests/codeception/api/unit/models/ResetPasswordFormTest.php
Normal file
43
tests/codeception/api/unit/models/ResetPasswordFormTest.php
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace tests\codeception\api\unit\models;
|
||||
|
||||
use tests\codeception\api\unit\DbTestCase;
|
||||
use tests\codeception\common\fixtures\UserFixture;
|
||||
use api\models\ResetPasswordForm;
|
||||
|
||||
class ResetPasswordFormTest extends DbTestCase
|
||||
{
|
||||
|
||||
/**
|
||||
* @expectedException \yii\base\InvalidParamException
|
||||
*/
|
||||
public function testResetWrongToken()
|
||||
{
|
||||
new ResetPasswordForm('notexistingtoken_1391882543');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \yii\base\InvalidParamException
|
||||
*/
|
||||
public function testResetEmptyToken()
|
||||
{
|
||||
new ResetPasswordForm('');
|
||||
}
|
||||
|
||||
public function testResetCorrectToken()
|
||||
{
|
||||
$form = new ResetPasswordForm($this->user[0]['password_reset_token']);
|
||||
expect('password should be resetted', $form->resetPassword())->true();
|
||||
}
|
||||
|
||||
public function fixtures()
|
||||
{
|
||||
return [
|
||||
'user' => [
|
||||
'class' => UserFixture::className(),
|
||||
'dataFile' => '@tests/codeception/api/unit/fixtures/data/models/user.php'
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
52
tests/codeception/api/unit/models/SignupFormTest.php
Normal file
52
tests/codeception/api/unit/models/SignupFormTest.php
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace tests\codeception\api\unit\models;
|
||||
|
||||
use tests\codeception\api\unit\DbTestCase;
|
||||
use tests\codeception\common\fixtures\UserFixture;
|
||||
use Codeception\Specify;
|
||||
use api\models\SignupForm;
|
||||
|
||||
class SignupFormTest extends DbTestCase
|
||||
{
|
||||
|
||||
use Specify;
|
||||
|
||||
public function testCorrectSignup()
|
||||
{
|
||||
$model = new SignupForm([
|
||||
'username' => 'some_username',
|
||||
'email' => 'some_email@example.com',
|
||||
'password' => 'some_password',
|
||||
]);
|
||||
|
||||
$user = $model->signup();
|
||||
|
||||
$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('password should be correct', $user->validatePassword('some_password'))->true();
|
||||
}
|
||||
|
||||
public function testNotCorrectSignup()
|
||||
{
|
||||
$model = new SignupForm([
|
||||
'username' => 'troy.becker',
|
||||
'email' => 'nicolas.dianna@hotmail.com',
|
||||
'password' => 'some_password',
|
||||
]);
|
||||
|
||||
expect('username and email are in use, user should not be created', $model->signup())->null();
|
||||
}
|
||||
|
||||
public function fixtures()
|
||||
{
|
||||
return [
|
||||
'user' => [
|
||||
'class' => UserFixture::className(),
|
||||
'dataFile' => '@tests/codeception/api/unit/fixtures/data/models/user.php',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
19
tests/codeception/bin/_bootstrap.php
Normal file
19
tests/codeception/bin/_bootstrap.php
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
/**
|
||||
* Yii console bootstrap file.
|
||||
*
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
defined('YII_DEBUG') or define('YII_DEBUG', true);
|
||||
defined('YII_ENV') or define('YII_ENV', 'test');
|
||||
|
||||
defined('YII_APP_BASE_PATH') or define('YII_APP_BASE_PATH', dirname(dirname(dirname(__DIR__))));
|
||||
|
||||
require_once(YII_APP_BASE_PATH . '/vendor/autoload.php');
|
||||
require_once(YII_APP_BASE_PATH . '/vendor/yiisoft/yii2/Yii.php');
|
||||
require_once(YII_APP_BASE_PATH . '/common/config/bootstrap.php');
|
||||
|
||||
Yii::setAlias('@tests', dirname(dirname(__DIR__)));
|
23
tests/codeception/bin/yii
Normal file
23
tests/codeception/bin/yii
Normal file
@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
/**
|
||||
* Yii console bootstrap file.
|
||||
*
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/_bootstrap.php';
|
||||
|
||||
$config = yii\helpers\ArrayHelper::merge(
|
||||
require(YII_APP_BASE_PATH . '/common/config/main.php'),
|
||||
require(YII_APP_BASE_PATH . '/common/config/main-local.php'),
|
||||
require(YII_APP_BASE_PATH . '/console/config/main.php'),
|
||||
require(YII_APP_BASE_PATH . '/console/config/main-local.php'),
|
||||
require(dirname(__DIR__) . '/config/config.php')
|
||||
);
|
||||
|
||||
$application = new yii\console\Application($config);
|
||||
$exitCode = $application->run();
|
||||
exit($exitCode);
|
20
tests/codeception/bin/yii.bat
Normal file
20
tests/codeception/bin/yii.bat
Normal file
@ -0,0 +1,20 @@
|
||||
@echo off
|
||||
|
||||
rem -------------------------------------------------------------
|
||||
rem Yii command line bootstrap script for Windows.
|
||||
rem
|
||||
rem @author Qiang Xue <qiang.xue@gmail.com>
|
||||
rem @link http://www.yiiframework.com/
|
||||
rem @copyright Copyright (c) 2008 Yii Software LLC
|
||||
rem @license http://www.yiiframework.com/license/
|
||||
rem -------------------------------------------------------------
|
||||
|
||||
@setlocal
|
||||
|
||||
set YII_PATH=%~dp0
|
||||
|
||||
if "%PHP_COMMAND%" == "" set PHP_COMMAND=php.exe
|
||||
|
||||
"%PHP_COMMAND%" "%YII_PATH%yii" %*
|
||||
|
||||
@endlocal
|
4
tests/codeception/common/.gitignore
vendored
Normal file
4
tests/codeception/common/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
# these files are auto generated by codeception build
|
||||
/unit/UnitTester.php
|
||||
/functional/FunctionalTester.php
|
||||
/acceptance/AcceptanceTester.php
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user