├── .bowerrc ├── .env.dist ├── .gitignore ├── .php_cs ├── LICENSE.md ├── README.md ├── assets ├── AdminAsset.php └── AppAsset.php ├── bin └── .gitignore ├── codeception.yml ├── commands ├── AppController.php └── BaseController.php ├── composer.json ├── config ├── .gitignore ├── common.php ├── console.php ├── main.php ├── params.php └── schedule.php ├── controllers └── SiteController.php ├── data ├── docker │ ├── db │ │ └── Dockerfile │ ├── redis │ │ └── Dockerfile │ └── web │ │ ├── .bashrc │ │ ├── apache.conf │ │ ├── crontab │ │ ├── dev │ │ └── Dockerfile │ │ ├── php.ini │ │ ├── prod │ │ └── Dockerfile │ │ └── supervisord.conf └── volumes │ ├── db │ └── .gitignore │ └── redis │ └── .gitignore ├── docker-compose.override.yml.dist ├── docker-compose.yml ├── environments ├── dev │ ├── config │ │ ├── common-local.php │ │ ├── console-local.php │ │ ├── main-local.php │ │ ├── params-local.php │ │ ├── test.php │ │ └── test_db.php │ ├── web │ │ ├── index-test.php │ │ └── index.php │ ├── yii │ ├── yii_test │ └── yii_test.bat ├── index.php └── prod │ ├── config │ ├── common-local.php │ ├── console-local.php │ ├── main-local.php │ └── params-local.php │ ├── web │ └── index.php │ └── yii ├── init ├── init.bat ├── mail ├── layouts │ └── html.php └── passwordResetToken.php ├── messages └── config.php ├── migrations └── m161109_121736_create_session_table.php ├── models ├── UserModel.php └── forms │ ├── ContactForm.php │ └── ResetPasswordForm.php ├── modules └── admin │ ├── Module.php │ ├── controllers │ ├── SettingsController.php │ └── UserController.php │ ├── models │ └── search │ │ └── UserSearch.php │ └── views │ ├── layouts │ └── column2.php │ └── user │ ├── _form.php │ ├── create.php │ ├── index.php │ └── update.php ├── rbac └── migrations │ └── m160722_085418_init.php ├── requirements.php ├── runtime └── .gitignore ├── tests ├── _bootstrap.php ├── _data │ ├── cms.php │ ├── user.php │ └── user_assignment.php ├── _output │ └── .gitignore ├── _support │ ├── AcceptanceTester.php │ ├── FunctionalTester.php │ └── UnitTester.php ├── acceptance.suite.example.yml ├── acceptance │ └── _bootstrap.php ├── fixtures │ ├── CmsFixture.php │ ├── UserAssignmentFixture.php │ └── UserFixture.php ├── functional.suite.yml ├── functional │ ├── AboutCest.php │ ├── AdminLoginCest.php │ ├── ChangePasswordViaAccountPageCest.php │ ├── ContactFormCest.php │ ├── CreateUserCest.php │ ├── HomeCest.php │ ├── LoginCest.php │ ├── SignupCest.php │ └── _bootstrap.php ├── unit.suite.yml └── unit │ ├── _bootstrap.php │ └── models │ ├── ContactFormTest.php │ ├── LoginFormTest.php │ ├── ResetPasswordFormTest.php │ └── SignupFormTest.php ├── traits ├── AjaxValidationTrait.php └── FindModelTrait.php ├── views ├── layouts │ └── main.php └── site │ ├── account.php │ ├── contact.php │ ├── error.php │ └── index.php ├── web ├── .gitignore ├── .htaccess ├── assets │ └── .gitignore ├── css │ ├── admin.css │ └── site.css ├── favicon.ico └── robots.txt └── yii.bat /.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory" : "vendor/bower" 3 | } -------------------------------------------------------------------------------- /.env.dist: -------------------------------------------------------------------------------- 1 | HOST_UID=1000 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # yii console commands 2 | /yii 3 | /yii_test 4 | /yii_test.bat 5 | 6 | # phpstorm project files 7 | .idea 8 | 9 | # netbeans project files 10 | nbproject 11 | 12 | # zend studio for eclipse project files 13 | .buildpath 14 | .project 15 | .settings 16 | 17 | # windows thumbnail cache 18 | Thumbs.db 19 | 20 | # composer vendor dir 21 | /vendor 22 | 23 | # runtime dirs 24 | runtime/debug 25 | runtime/logs 26 | 27 | # composer itself is not needed 28 | composer.phar 29 | 30 | # Mac DS_Store Files 31 | .DS_Store 32 | 33 | # phpunit itself is not needed 34 | phpunit.phar 35 | # local phpunit config 36 | /phpunit.xml 37 | 38 | tests/_output/* 39 | tests/_support/_generated 40 | 41 | /.env 42 | /docker-compose.override.yml 43 | /.php_cs.cache 44 | -------------------------------------------------------------------------------- /.php_cs: -------------------------------------------------------------------------------- 1 | exclude([ 5 | 'vendor', 6 | 'runtime', 7 | 'tests/_output', 8 | 'tests/_support', 9 | ]) 10 | ->in([__DIR__]); 11 | 12 | $config = PhpCsFixer\Config::create() 13 | ->setRules([ 14 | '@Symfony' => true, 15 | 'phpdoc_order' => true, 16 | 'phpdoc_align' => false, 17 | 'phpdoc_summary' => false, 18 | 'phpdoc_inline_tag' => false, 19 | 'pre_increment' => false, 20 | 'heredoc_to_nowdoc' => false, 21 | 'cast_spaces' => false, 22 | 'include' => false, 23 | 'phpdoc_no_package' => false, 24 | 'concat_space' => ['spacing' => 'one'], 25 | 'ordered_imports' => true, 26 | 'ordered_class_elements' => true, 27 | 'phpdoc_add_missing_param_annotation' => true, 28 | 'array_syntax' => ['syntax' => 'short'], 29 | 'visibility_required' => true, 30 | 'yoda_style' => false, 31 | ]) 32 | ->setFinder($finder); 33 | 34 | return $config; 35 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 yii2mod 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |
21 | 'btn btn-success']); ?> 22 |
23 | 10000]); ?> 24 | $dataProvider, 26 | 'filterModel' => $searchModel, 27 | 'columns' => [ 28 | 'id', 29 | [ 30 | 'class' => EditableColumn::class, 31 | 'attribute' => 'username', 32 | 'url' => ['edit-user'], 33 | ], 34 | 'email:email', 35 | [ 36 | 'class' => EditableColumn::class, 37 | 'attribute' => 'status', 38 | 'url' => ['edit-user'], 39 | 'value' => function ($model) { 40 | return UserStatus::getLabel($model->status); 41 | }, 42 | 'type' => 'select', 43 | 'editableOptions' => function ($model) { 44 | return [ 45 | 'source' => UserStatus::listData(), 46 | 'value' => $model->status, 47 | ]; 48 | }, 49 | 'filter' => UserStatus::listData(), 50 | 'filterInputOptions' => ['prompt' => Yii::t('app', 'Select Status'), 'class' => 'form-control'], 51 | ], 52 | [ 53 | 'attribute' => 'created_at', 54 | 'format' => 'date', 55 | 'filter' => false, 56 | ], 57 | [ 58 | 'header' => Yii::t('app', 'Action'), 59 | 'class' => 'yii\grid\ActionColumn', 60 | 'template' => '{switch} {update} {delete}', 61 | 'buttons' => [ 62 | 'switch' => function ($url, $model) { 63 | $options = [ 64 | 'title' => Yii::t('app', 'Become this user'), 65 | 'aria-label' => Yii::t('app', 'Become this user'), 66 | 'data-pjax' => '0', 67 | 'data-confirm' => Yii::t('app', 'Are you sure you want to switch to this user for the rest of this Session?'), 68 | 'data-method' => 'POST', 69 | ]; 70 | 71 | $url = ['switch', 'id' => $model->id]; 72 | $icon = ''; 73 | 74 | return Html::a($icon, $url, $options); 75 | }, 76 | ], 77 | ], 78 | ], 79 | ]); 80 | ?> 81 | 82 | 83 |The path to yii framework seems to be incorrect.
'; 19 | echo 'You need to install Yii framework via composer or adjust the framework path in file ' . basename(__FILE__) . '.
'; 20 | echo 'Please refer to the README on how to install Yii.
'; 21 | } 22 | 23 | require_once($frameworkPath . '/requirements/YiiRequirementChecker.php'); 24 | $requirementsChecker = new YiiRequirementChecker(); 25 | 26 | $gdMemo = $imagickMemo = 'Either GD PHP extension with FreeType support or ImageMagick PHP extension with PNG support is required for image CAPTCHA.'; 27 | $gdOK = $imagickOK = false; 28 | 29 | if (extension_loaded('imagick')) { 30 | $imagick = new Imagick(); 31 | $imagickFormats = $imagick->queryFormats('PNG'); 32 | if (in_array('PNG', $imagickFormats)) { 33 | $imagickOK = true; 34 | } else { 35 | $imagickMemo = 'Imagick extension should be installed with PNG support in order to be used for image CAPTCHA.'; 36 | } 37 | } 38 | 39 | if (extension_loaded('gd')) { 40 | $gdInfo = gd_info(); 41 | if (!empty($gdInfo['FreeType Support'])) { 42 | $gdOK = true; 43 | } else { 44 | $gdMemo = 'GD extension should be installed with FreeType support in order to be used for image CAPTCHA.'; 45 | } 46 | } 47 | 48 | /** 49 | * Adjust requirements according to your application specifics. 50 | */ 51 | $requirements = [ 52 | // Database : 53 | [ 54 | 'name' => 'PDO extension', 55 | 'mandatory' => true, 56 | 'condition' => extension_loaded('pdo'), 57 | 'by' => 'All DB-related classes', 58 | ], 59 | [ 60 | 'name' => 'PDO SQLite extension', 61 | 'mandatory' => false, 62 | 'condition' => extension_loaded('pdo_sqlite'), 63 | 'by' => 'All DB-related classes', 64 | 'memo' => 'Required for SQLite database.', 65 | ], 66 | [ 67 | 'name' => 'PDO MySQL extension', 68 | 'mandatory' => false, 69 | 'condition' => extension_loaded('pdo_mysql'), 70 | 'by' => 'All DB-related classes', 71 | 'memo' => 'Required for MySQL database.', 72 | ], 73 | [ 74 | 'name' => 'PDO PostgreSQL extension', 75 | 'mandatory' => false, 76 | 'condition' => extension_loaded('pdo_pgsql'), 77 | 'by' => 'All DB-related classes', 78 | 'memo' => 'Required for PostgreSQL database.', 79 | ], 80 | // Cache : 81 | [ 82 | 'name' => 'Memcache extension', 83 | 'mandatory' => false, 84 | 'condition' => extension_loaded('memcache') || extension_loaded('memcached'), 85 | 'by' => 'MemCache', 86 | 'memo' => extension_loaded('memcached') ? 'To use memcached set MemCache::useMemcached totrue
.' : '',
87 | ],
88 | // CAPTCHA:
89 | [
90 | 'name' => 'GD PHP extension with FreeType support',
91 | 'mandatory' => false,
92 | 'condition' => $gdOK,
93 | 'by' => 'Captcha',
94 | 'memo' => $gdMemo,
95 | ],
96 | [
97 | 'name' => 'ImageMagick PHP extension with PNG support',
98 | 'mandatory' => false,
99 | 'condition' => $imagickOK,
100 | 'by' => 'Captcha',
101 | 'memo' => $imagickMemo,
102 | ],
103 | // PHP ini :
104 | 'phpExposePhp' => [
105 | 'name' => 'Expose PHP',
106 | 'mandatory' => false,
107 | 'condition' => $requirementsChecker->checkPhpIniOff('expose_php'),
108 | 'by' => 'Security reasons',
109 | 'memo' => '"expose_php" should be disabled at php.ini',
110 | ],
111 | 'phpAllowUrlInclude' => [
112 | 'name' => 'PHP allow url include',
113 | 'mandatory' => false,
114 | 'condition' => $requirementsChecker->checkPhpIniOff('allow_url_include'),
115 | 'by' => 'Security reasons',
116 | 'memo' => '"allow_url_include" should be disabled at php.ini',
117 | ],
118 | 'phpSmtp' => [
119 | 'name' => 'PHP mail SMTP',
120 | 'mandatory' => false,
121 | 'condition' => strlen(ini_get('SMTP')) > 0,
122 | 'by' => 'Email sending',
123 | 'memo' => 'PHP mail SMTP server required',
124 | ],
125 | ];
126 |
127 | // OPcache check
128 | if (!version_compare(phpversion(), '5.5', '>=')) {
129 | $requirements[] = [
130 | 'name' => 'APC extension',
131 | 'mandatory' => false,
132 | 'condition' => extension_loaded('apc'),
133 | 'by' => 'ApcCache',
134 | ];
135 | }
136 |
137 | $requirementsChecker->checkYii()->check($requirements)->render();
138 |
--------------------------------------------------------------------------------
/runtime/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/tests/_bootstrap.php:
--------------------------------------------------------------------------------
1 | 'about-us',
6 | 'title' => 'About us',
7 | 'content' => 'About us content',
8 | 'meta_title' => 'About us',
9 | 'meta_description' => 'About us description',
10 | 'meta_keywords' => 'About us keywords',
11 | 'created_at' => time(),
12 | 'updated_at' => time(),
13 | ],
14 | [
15 | 'url' => 'terms-and-conditions',
16 | 'title' => 'Terms & Conditions',
17 | 'content' => 'Content',
18 | 'meta_title' => 'Terms & Conditions',
19 | 'meta_description' => 'Terms & Conditions description',
20 | 'meta_keywords' => 'Terms & Conditions keywords',
21 | 'created_at' => time(),
22 | 'updated_at' => time(),
23 | ],
24 | [
25 | 'url' => 'privacy-policy',
26 | 'title' => 'Privacy Policy',
27 | 'content' => 'Content',
28 | 'meta_title' => 'Privacy Policy',
29 | 'meta_description' => 'Privacy Policy description',
30 | 'meta_keywords' => 'Privacy Policy keywords',
31 | 'created_at' => time(),
32 | 'updated_at' => time(),
33 | ],
34 | ];
35 |
--------------------------------------------------------------------------------
/tests/_data/user.php:
--------------------------------------------------------------------------------
1 | 'admin',
6 | 'auth_key' => Yii::$app->getSecurity()->generateRandomString(),
7 | 'password_hash' => Yii::$app->getSecurity()->generatePasswordHash(123123),
8 | 'email' => 'admin@example.org',
9 | 'status' => 1,
10 | 'created_at' => time(),
11 | 'updated_at' => time(),
12 | ],
13 | [
14 | 'username' => 'test-user',
15 | 'auth_key' => Yii::$app->getSecurity()->generateRandomString(),
16 | 'password_hash' => Yii::$app->getSecurity()->generatePasswordHash(123123),
17 | 'email' => 'test-user@example.com',
18 | 'status' => 1,
19 | 'created_at' => time(),
20 | 'updated_at' => time(),
21 | ],
22 | ];
23 |
--------------------------------------------------------------------------------
/tests/_data/user_assignment.php:
--------------------------------------------------------------------------------
1 | 'admin',
6 | 'user_id' => 1,
7 | 'created_at' => time(),
8 | ],
9 | [
10 | 'item_name' => 'user',
11 | 'user_id' => 2,
12 | 'created_at' => time(),
13 | ],
14 | ];
15 |
--------------------------------------------------------------------------------
/tests/_output/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
--------------------------------------------------------------------------------
/tests/_support/AcceptanceTester.php:
--------------------------------------------------------------------------------
1 | see($message, '.help-block');
26 | }
27 |
28 | public function dontSeeValidationError($message)
29 | {
30 | $this->dontSee($message, '.help-block');
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/tests/_support/UnitTester.php:
--------------------------------------------------------------------------------
1 | tableName = Yii::$app->authManager->assignmentTable;
26 |
27 | parent::init();
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/tests/fixtures/UserFixture.php:
--------------------------------------------------------------------------------
1 | haveFixtures([
13 | 'cms' => [
14 | 'class' => CmsFixture::class,
15 | ],
16 | ]);
17 | }
18 |
19 | public function checkAbout(FunctionalTester $I)
20 | {
21 | $I->amOnRoute('/about-us');
22 | $I->see('About us', 'h1');
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/tests/functional/AdminLoginCest.php:
--------------------------------------------------------------------------------
1 | haveFixtures([
18 | 'user' => [
19 | 'class' => UserAssignmentFixture::class,
20 | ],
21 | ]);
22 |
23 | $I->amOnRoute('site/login');
24 | }
25 |
26 | public function checkLogin(FunctionalTester $I)
27 | {
28 | $I->submitForm($this->formId, $this->formParams('admin@example.org', '123123'));
29 | $I->see('Logout (admin)', 'form button[type=submit]');
30 | $I->seeLink('Administration');
31 | }
32 |
33 | public function checkAdminPanel(FunctionalTester $I)
34 | {
35 | $I->submitForm($this->formId, $this->formParams('admin@example.org', '123123'));
36 | $I->see('Logout (admin)', 'form button[type=submit]');
37 | $I->seeLink('Administration');
38 | $I->click('Administration');
39 | $I->see('Users');
40 | $I->seeLink('CMS');
41 | $I->seeLink('RBAC');
42 | $I->seeLink('Settings Storage');
43 | $I->seeLink('Cron Schedule Log');
44 | }
45 |
46 | protected function formParams($login, $password)
47 | {
48 | return [
49 | 'LoginForm[email]' => $login,
50 | 'LoginForm[password]' => $password,
51 | ];
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/tests/functional/ChangePasswordViaAccountPageCest.php:
--------------------------------------------------------------------------------
1 | haveFixtures([
13 | 'user' => [
14 | 'class' => UserAssignmentFixture::class,
15 | ],
16 | ]);
17 | $I->amOnRoute('site/login');
18 | }
19 |
20 | public function checkEmpty(FunctionalTester $I)
21 | {
22 | $I->submitForm('#login-form', $this->loginFormParams('test-user@example.com', '123123'));
23 | $I->click('My Account');
24 | $I->submitForm('#change-password-form', $this->resetPasswordFormParams('', ''));
25 | $I->see('New Password cannot be blank.');
26 | $I->see('Confirm New Password cannot be blank.');
27 | }
28 |
29 | public function checkNotEqual(FunctionalTester $I)
30 | {
31 | $I->submitForm('#login-form', $this->loginFormParams('test-user@example.com', '123123'));
32 | $I->click('My Account');
33 | $I->submitForm('#change-password-form', $this->resetPasswordFormParams('123123', '123456'));
34 | $I->see('Confirm New Password must be equal to "New Password".');
35 | }
36 |
37 | public function checkCorrectChangePassword(FunctionalTester $I)
38 | {
39 | $I->submitForm('#login-form', $this->loginFormParams('test-user@example.com', '123123'));
40 | $I->click('My Account');
41 | $I->submitForm('#change-password-form', $this->resetPasswordFormParams('123456', '123456'));
42 | $I->canSeeInSource('Password has been updated.');
43 | }
44 |
45 | protected function loginFormParams($login, $password)
46 | {
47 | return [
48 | 'LoginForm[email]' => $login,
49 | 'LoginForm[password]' => $password,
50 | ];
51 | }
52 |
53 | protected function resetPasswordFormParams($newPassword, $confirmPassword)
54 | {
55 | return [
56 | 'ResetPasswordForm[password]' => $newPassword,
57 | 'ResetPasswordForm[confirmPassword]' => $confirmPassword,
58 | ];
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/tests/functional/ContactFormCest.php:
--------------------------------------------------------------------------------
1 | amOnPage(['site/contact']);
15 | }
16 |
17 | /**
18 | * @param FunctionalTester $I
19 | */
20 | public function checkContact(FunctionalTester $I)
21 | {
22 | $I->see('Contact', 'h1');
23 | }
24 |
25 | /**
26 | * @param FunctionalTester $I
27 | */
28 | public function checkContactSubmitNoData(FunctionalTester $I)
29 | {
30 | $I->submitForm('#contact-form', []);
31 |
32 | $I->see('Contact', 'h1');
33 | $I->seeValidationError('Name cannot be blank');
34 | $I->seeValidationError('Email cannot be blank');
35 | $I->seeValidationError('Subject cannot be blank');
36 | $I->seeValidationError('Body cannot be blank');
37 | $I->seeValidationError('The verification code is incorrect');
38 | }
39 |
40 | /**
41 | * @param FunctionalTester $I
42 | */
43 | public function checkContactSubmitNotCorrectEmail(FunctionalTester $I)
44 | {
45 | $I->submitForm('#contact-form', [
46 | 'ContactForm[name]' => 'tester',
47 | 'ContactForm[email]' => 'tester.email',
48 | 'ContactForm[subject]' => 'test subject',
49 | 'ContactForm[body]' => 'test content',
50 | 'ContactForm[verifyCode]' => 'testme',
51 | ]);
52 |
53 | $I->seeValidationError('Email is not a valid email address.');
54 | $I->dontSeeValidationError('Name cannot be blank');
55 | $I->dontSeeValidationError('Subject cannot be blank');
56 | $I->dontSeeValidationError('Body cannot be blank');
57 | $I->dontSeeValidationError('The verification code is incorrect');
58 | }
59 |
60 | /**
61 | * @param FunctionalTester $I
62 | */
63 | public function checkContactSubmitCorrectData(FunctionalTester $I)
64 | {
65 | $I->submitForm('#contact-form', [
66 | 'ContactForm[name]' => 'tester',
67 | 'ContactForm[email]' => 'tester@example.com',
68 | 'ContactForm[subject]' => 'test subject',
69 | 'ContactForm[body]' => 'test content',
70 | 'ContactForm[verifyCode]' => 'testme',
71 | ]);
72 |
73 | $I->seeEmailIsSent();
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/tests/functional/CreateUserCest.php:
--------------------------------------------------------------------------------
1 | haveFixtures([
23 | 'user' => [
24 | 'class' => UserAssignmentFixture::class,
25 | ],
26 | ]);
27 | }
28 |
29 | public function createUser(FunctionalTester $I)
30 | {
31 | $I->amOnRoute('site/login');
32 | $I->submitForm($this->loginFormId, $this->loginFormParams('admin@example.org', '123123'));
33 | $I->amOnRoute('/admin/user/create');
34 | $I->see('Create User');
35 | $I->submitForm($this->createUserFormId, $this->createUserFormParams('created-user', 'created-user@example.com', '123123'));
36 | $I->see('Users', 'h1');
37 | $I->seeRecord('app\models\UserModel', [
38 | 'username' => 'created-user',
39 | 'email' => 'created-user@example.com',
40 | ]);
41 | }
42 |
43 | protected function loginFormParams($login, $password)
44 | {
45 | return [
46 | 'LoginForm[email]' => $login,
47 | 'LoginForm[password]' => $password,
48 | ];
49 | }
50 |
51 | protected function createUserFormParams($username, $email, $password)
52 | {
53 | return [
54 | 'UserModel[username]' => $username,
55 | 'UserModel[email]' => $email,
56 | 'UserModel[plainPassword]' => $password,
57 | ];
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/tests/functional/HomeCest.php:
--------------------------------------------------------------------------------
1 | amOnPage(\Yii::$app->homeUrl);
12 | $I->seeLink('About Us');
13 | $I->seeLink('Contact');
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/tests/functional/LoginCest.php:
--------------------------------------------------------------------------------
1 | haveFixtures([
13 | 'user' => [
14 | 'class' => UserAssignmentFixture::class,
15 | ],
16 | ]);
17 | $I->amOnRoute('site/login');
18 | }
19 |
20 | public function checkEmpty(FunctionalTester $I)
21 | {
22 | $I->submitForm('#login-form', $this->formParams('', ''));
23 | $I->see('Email cannot be blank.');
24 | $I->see('Password cannot be blank.');
25 | }
26 |
27 | public function checkWrongEmail(FunctionalTester $I)
28 | {
29 | $I->submitForm('#login-form', $this->formParams('admin', 'wrong'));
30 | $I->see('Email is not a valid email address.');
31 | }
32 |
33 | public function checkWrongPassword(FunctionalTester $I)
34 | {
35 | $I->submitForm('#login-form', $this->formParams('admin@example.org', 'wrong'));
36 | $I->see('Incorrect email or password.');
37 | }
38 |
39 | public function checkValidLogin(FunctionalTester $I)
40 | {
41 | $I->submitForm('#login-form', $this->formParams('admin@example.org', '123123'));
42 | $I->see('Logout (admin)', 'form button[type=submit]');
43 | $I->dontSeeLink('Login');
44 | $I->dontSeeLink('Signup');
45 | }
46 |
47 | protected function formParams($login, $password)
48 | {
49 | return [
50 | 'LoginForm[email]' => $login,
51 | 'LoginForm[password]' => $password,
52 | ];
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/tests/functional/SignupCest.php:
--------------------------------------------------------------------------------
1 | amOnRoute('site/signup');
17 | }
18 |
19 | public function signupWithEmptyFields(FunctionalTester $I)
20 | {
21 | $I->see('Signup', 'h1');
22 | $I->see('Please fill out the following fields to signup:');
23 | $I->submitForm($this->formId, []);
24 | $I->see('Username cannot be blank.');
25 | $I->see('Email cannot be blank.');
26 | $I->see('Password cannot be blank.');
27 | }
28 |
29 | public function signupWithWrongEmail(FunctionalTester $I)
30 | {
31 | $I->submitForm(
32 | $this->formId, [
33 | 'SignupForm[username]' => 'tester',
34 | 'SignupForm[email]' => 'ttttt',
35 | 'SignupForm[password]' => 'tester_password',
36 | ]
37 | );
38 | $I->dontSee('Username cannot be blank.', '.help-block');
39 | $I->dontSee('Password cannot be blank.', '.help-block');
40 | $I->see('Email is not a valid email address.', '.help-block');
41 | }
42 |
43 | public function signupSuccessfully(FunctionalTester $I)
44 | {
45 | $I->submitForm($this->formId, [
46 | 'SignupForm[username]' => 'tester',
47 | 'SignupForm[email]' => 'tester.email@example.com',
48 | 'SignupForm[password]' => 'tester_password',
49 | ]);
50 | $I->seeRecord('app\models\UserModel', [
51 | 'username' => 'tester',
52 | 'email' => 'tester.email@example.com',
53 | ]);
54 | $I->see('Logout (tester)', 'form button[type=submit]');
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/tests/functional/_bootstrap.php:
--------------------------------------------------------------------------------
1 | _model = $this->getMockBuilder('app\models\forms\ContactForm')
23 | ->setMethods(['validate'])
24 | ->getMock();
25 |
26 | $this->_model->expects($this->once())
27 | ->method('validate')
28 | ->will($this->returnValue(true));
29 |
30 | $this->_model->attributes = [
31 | 'name' => 'Tester',
32 | 'email' => 'tester@example.com',
33 | 'subject' => 'very important letter subject',
34 | 'body' => 'body of current message',
35 | ];
36 |
37 | expect_that($this->_model->contact('admin@example.com'));
38 |
39 | // using Yii2 module actions to check email was sent
40 | $this->tester->seeEmailIsSent();
41 |
42 | $emailMessage = $this->tester->grabLastSentEmail();
43 | expect('valid email is sent', $emailMessage)->isInstanceOf('yii\mail\MessageInterface');
44 | expect($emailMessage->getTo())->hasKey('admin@example.com');
45 | expect($emailMessage->getFrom())->hasKey('tester@example.com');
46 | expect($emailMessage->getSubject())->equals('very important letter subject');
47 | expect($emailMessage->toString())->contains('body of current message');
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/tests/unit/models/LoginFormTest.php:
--------------------------------------------------------------------------------
1 | _model = new LoginForm([
24 | 'email' => 'not_existing_username',
25 | 'password' => 'not_existing_password',
26 | ]);
27 |
28 | expect_not($this->_model->login());
29 | expect_that(Yii::$app->user->isGuest);
30 | }
31 |
32 | public function testLoginWrongPassword()
33 | {
34 | $this->_model = new LoginForm([
35 | 'email' => 'demo@example.com',
36 | 'password' => 'wrong_password',
37 | ]);
38 |
39 | expect_not($this->_model->login());
40 | expect_that(Yii::$app->user->isGuest);
41 | expect($this->_model->errors)->hasKey('password');
42 | }
43 |
44 | public function testLoginCorrect()
45 | {
46 | $this->_model = new LoginForm([
47 | 'email' => 'admin@example.org',
48 | 'password' => '123123',
49 | ]);
50 |
51 | expect_that($this->_model->login());
52 | expect_not(Yii::$app->user->isGuest);
53 | expect($this->_model->errors)->hasntKey('password');
54 | }
55 |
56 | /**
57 | * @inheritdoc
58 | */
59 | protected function _before()
60 | {
61 | $this->tester->haveFixtures([
62 | 'user' => [
63 | 'class' => UserAssignmentFixture::class,
64 | ],
65 | ]);
66 | }
67 |
68 | /**
69 | * @inheritdoc
70 | */
71 | protected function _after()
72 | {
73 | Yii::$app->user->logout();
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/tests/unit/models/ResetPasswordFormTest.php:
--------------------------------------------------------------------------------
1 | 'test-user@example.com']);
25 | $this->_model = new ResetPasswordForm($user);
26 |
27 | expect($this->_model->resetPassword())->false();
28 | expect($this->_model->errors)->hasKey('password');
29 | expect($this->_model->errors)->hasKey('confirmPassword');
30 | }
31 |
32 | public function testCheckInvalidConfirmPassword()
33 | {
34 | $user = UserModel::findOne(['email' => 'test-user@example.com']);
35 | $this->_model = new ResetPasswordForm($user, [
36 | 'password' => '123123',
37 | 'confirmPassword' => '123456',
38 | ]);
39 |
40 | expect($this->_model->resetPassword())->false();
41 | expect($this->_model->errors)->hasKey('confirmPassword');
42 | }
43 |
44 | public function testCorrectResetPassword()
45 | {
46 | $user = UserModel::findOne(['email' => 'test-user@example.com']);
47 | $this->_model = new ResetPasswordForm($user, [
48 | 'password' => '123456',
49 | 'confirmPassword' => '123456',
50 | ]);
51 |
52 | expect($this->_model->resetPassword())->true();
53 | expect($this->_model->errors)->isEmpty();
54 | }
55 |
56 | /**
57 | * @inheritdoc
58 | */
59 | protected function _before()
60 | {
61 | $this->tester->haveFixtures([
62 | 'user' => [
63 | 'class' => UserAssignmentFixture::class,
64 | ],
65 | ]);
66 | }
67 |
68 | /**
69 | * @inheritdoc
70 | */
71 | protected function _after()
72 | {
73 | Yii::$app->user->logout();
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/tests/unit/models/SignupFormTest.php:
--------------------------------------------------------------------------------
1 | 'some_username',
19 | 'email' => 'some_email@example.com',
20 | 'password' => 'some_password',
21 | ]);
22 |
23 | $user = $model->signup();
24 |
25 | expect($user)->isInstanceOf('yii2mod\user\models\UserModel');
26 |
27 | expect($user->username)->equals('some_username');
28 | expect($user->email)->equals('some_email@example.com');
29 | expect($user->validatePassword('some_password'))->true();
30 | }
31 |
32 | public function testNotCorrectSignup()
33 | {
34 | $model = new SignupForm([
35 | 'username' => 'test-user',
36 | 'email' => 'test-user@example.com',
37 | 'password' => 'some_password',
38 | ]);
39 |
40 | expect_not($model->signup());
41 | expect_that($model->getErrors('username'));
42 | expect_that($model->getErrors('email'));
43 |
44 | expect($model->getFirstError('username'))
45 | ->equals('This username has already been taken.');
46 | expect($model->getFirstError('email'))
47 | ->equals('This email address has already been taken.');
48 | }
49 |
50 | /**
51 | * @inheritdoc
52 | */
53 | protected function _before()
54 | {
55 | $this->tester->haveFixtures([
56 | 'user' => [
57 | 'class' => UserAssignmentFixture::class,
58 | ],
59 | ]);
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/traits/AjaxValidationTrait.php:
--------------------------------------------------------------------------------
1 |
15 | *
16 | * @since 1.0
17 | */
18 | trait AjaxValidationTrait
19 | {
20 | /**
21 | * Performs ajax validation.
22 | *
23 | * @param Model $model
24 | *
25 | * @throws \yii\base\ExitException
26 | */
27 | protected function performAjaxValidation(Model $model)
28 | {
29 | if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
30 | Yii::$app->response->format = Response::FORMAT_JSON;
31 | echo Json::encode(ActiveForm::validate($model));
32 | Yii::$app->end();
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/traits/FindModelTrait.php:
--------------------------------------------------------------------------------
1 |
12 | *
13 | * @since 1.0
14 | */
15 | trait FindModelTrait
16 | {
17 | /**
18 | * Finds model
19 | *
20 | * @param mixed $modelClass
21 | * @param mixed $condition primary key value or a set of column values
22 | * @param string $notFoundMessage
23 | *
24 | * @throws NotFoundHttpException
25 | *
26 | * @return ActiveRecord
27 | */
28 | protected function findModel($modelClass, $condition, string $notFoundMessage = 'The requested page does not exist.')
29 | {
30 | if (($model = $modelClass::findOne($condition)) !== null) {
31 | return $model;
32 | } else {
33 | throw new NotFoundHttpException($notFoundMessage);
34 | }
35 | }
36 |
37 | /**
38 | * @param mixed $modelClass
39 | * @param mixed $condition primary key value or a set of column values
40 | *
41 | * @return ActiveRecord
42 | */
43 | protected function findModelOrCreate($modelClass, $condition)
44 | {
45 | if (($model = $modelClass::findOne($condition)) !== null) {
46 | return $model;
47 | } else {
48 | return new $modelClass($condition);
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/views/layouts/main.php:
--------------------------------------------------------------------------------
1 |
16 | beginPage(); ?>
17 |
18 |
19 |
20 | registerMetaTag(['charset' => Yii::$app->charset]); ?>
21 | registerMetaTag(['name' => 'viewport', 'content' => 'width=device-width, initial-scale=1']); ?>
22 |
23 | 17 | 18 |
19 |21 | The above error occurred while the Web server was processing your request. 22 |
23 |24 | Please contact us if you think this is a server error. Thank you. 25 |
26 | 27 |You have successfully created your Yii-powered application.
9 |