From 3281169b86ebcf3028b24d47c31c97760acee9ee Mon Sep 17 00:00:00 2001 From: Lorenzo Milesi Date: Sun, 26 Nov 2017 20:09:09 +0100 Subject: [PATCH 01/35] Password expiration feature #102 It's still missing an enforcement which redirects all actions to profile update until the password is changed --- src/User/Bootstrap.php | 18 +++++++++++ src/User/Controller/AdminController.php | 17 +++++++++++ ...0000_000007_enable_password_expiration.php | 27 +++++++++++++++++ src/User/Model/User.php | 19 ++++++++++++ src/User/Module.php | 4 +++ src/User/Service/PasswordExpireService.php | 30 +++++++++++++++++++ src/User/resources/views/admin/index.php | 22 ++++++++++++-- 7 files changed, 135 insertions(+), 2 deletions(-) create mode 100644 src/User/Migration/m000000_000007_enable_password_expiration.php create mode 100644 src/User/Service/PasswordExpireService.php diff --git a/src/User/Bootstrap.php b/src/User/Bootstrap.php index 0f36307..b1b69ac 100644 --- a/src/User/Bootstrap.php +++ b/src/User/Bootstrap.php @@ -24,6 +24,10 @@ use yii\console\Application as ConsoleApplication; use yii\i18n\PhpMessageSource; use yii\web\Application as WebApplication; +use yii\base\Event; +use Da\User\Event\FormEvent; +use Da\User\Controller\SecurityController; + /** * Bootstrap class of the yii2-usuario extension. Configures container services, initializes translations, * builds class map, and does the other setup actions participating in the application bootstrap process. @@ -88,6 +92,7 @@ class Bootstrap implements BootstrapInterface // services $di->set(Service\AccountConfirmationService::class); $di->set(Service\EmailChangeService::class); + $di->set(Service\PasswordExpireService::class); $di->set(Service\PasswordRecoveryService::class); $di->set(Service\ResendConfirmationService::class); $di->set(Service\ResetPasswordService::class); @@ -141,6 +146,19 @@ class Bootstrap implements BootstrapInterface $di->set(Search\RoleSearch::class); } + // Attach an event to check if the password has expired + Event::on(SecurityController::class, FormEvent::EVENT_AFTER_LOGIN, function (FormEvent $event) { + if (is_null(Yii::$app->getModule('user')->maxPasswordAge)) { + return; + } + $user = $event->form->user; + if ($user->password_age >= Yii::$app->getModule('user')->maxPasswordAge) { + // Force password change + Yii::$app->session->setFlash('warning', Yii::t('usuario', 'Your password has expired, you must change it now')); + Yii::$app->response->redirect(['/user/settings/account'])->send(); + } + }); + if ($app instanceof WebApplication) { // override Yii $di->set( diff --git a/src/User/Controller/AdminController.php b/src/User/Controller/AdminController.php index f0ddf23..9af1113 100644 --- a/src/User/Controller/AdminController.php +++ b/src/User/Controller/AdminController.php @@ -18,6 +18,7 @@ use Da\User\Model\Profile; use Da\User\Model\User; use Da\User\Query\UserQuery; use Da\User\Search\UserSearch; +use Da\User\Service\PasswordExpireService; use Da\User\Service\PasswordRecoveryService; use Da\User\Service\SwitchIdentityService; use Da\User\Service\UserBlockService; @@ -329,4 +330,20 @@ class AdminController extends Controller return $this->redirect(['index']); } + + /** + * Forces the user to change password at next login + * @param integer $id + */ + public function actionForcePasswordChange($id) + { + /** @var User $user */ + $user = $this->userQuery->where(['id' => $id])->one(); + if ($this->make(PasswordExpireService::class, [$user])->run()) { + Yii::$app->session->setFlash("success", Yii::t('usuario', 'User will be required to change password at next login')); + } else { + Yii::$app->session->setFlash("danger", Yii::t('usuario', 'There was an error in saving user')); + } + $this->redirect(['index']); + } } diff --git a/src/User/Migration/m000000_000007_enable_password_expiration.php b/src/User/Migration/m000000_000007_enable_password_expiration.php new file mode 100644 index 0000000..dcee448 --- /dev/null +++ b/src/User/Migration/m000000_000007_enable_password_expiration.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Da\User\Migration; + +use yii\db\Migration; + +class m000000_000007_enable_password_expiration extends Migration +{ + public function safeUp() + { + $this->addColumn('{{%user}}', 'last_password_change', $this->timestamp()->null()); + } + + public function safeDown() + { + $this->dropColumn('{{%user}}', 'last_password_change'); + } +} diff --git a/src/User/Model/User.php b/src/User/Model/User.php index 7fc3771..b85147c 100644 --- a/src/User/Model/User.php +++ b/src/User/Model/User.php @@ -19,6 +19,7 @@ use Yii; use yii\base\NotSupportedException; use yii\behaviors\TimestampBehavior; use yii\db\ActiveRecord; +use yii\db\Expression; use yii\helpers\ArrayHelper; use yii\web\Application; use yii\web\IdentityInterface; @@ -46,6 +47,8 @@ use yii\web\IdentityInterface; * @property int $created_at * @property int $updated_at * @property int $last_login_at + * @property int $last_password_change + * @property int $password_age * * Defined relations: * @property SocialNetworkAccount[] $socialNetworkAccounts @@ -88,6 +91,7 @@ class User extends ActiveRecord implements IdentityInterface 'password_hash', $security->generatePasswordHash($this->password, $this->getModule()->blowfishCost) ); + $this->last_password_change = new Expression("NOW()"); } return parent::beforeSave($insert); @@ -138,6 +142,8 @@ class User extends ActiveRecord implements IdentityInterface 'created_at' => Yii::t('usuario', 'Registration time'), 'confirmed_at' => Yii::t('usuario', 'Confirmation time'), 'last_login_at' => Yii::t('usuario', 'Last login'), + 'last_password_change' => Yii::t('usuario', 'Last password change'), + 'password_age' => Yii::t('usuario', 'Password age'), ]; } @@ -312,4 +318,17 @@ class User extends ActiveRecord implements IdentityInterface { throw new NotSupportedException('Method "' . __CLASS__ . '::' . __METHOD__ . '" is not implemented.'); } + + /** + * Returns password age in days + * @return integer + */ + public function getPassword_age() + { + if (is_null($this->last_password_change)) { + return $this->getModule()->maxPasswordAge; + } + $d = new \DateTime($this->last_password_change); + return $d->diff(new \DateTime(), true)->format("%a"); + } } diff --git a/src/User/Module.php b/src/User/Module.php index 53b54b5..f6ee68f 100644 --- a/src/User/Module.php +++ b/src/User/Module.php @@ -128,4 +128,8 @@ class Module extends BaseModule * @var string the session key name to impersonate users. Please, modify it for security reasons! */ public $switchIdentitySessionKey = 'yuik_usuario'; + /** + * @var integer If != NULL sets a max password age in days + */ + public $maxPasswordAge = null; } diff --git a/src/User/Service/PasswordExpireService.php b/src/User/Service/PasswordExpireService.php new file mode 100644 index 0000000..6a7e75f --- /dev/null +++ b/src/User/Service/PasswordExpireService.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Da\User\Service; + +use Da\User\Contracts\ServiceInterface; +use Da\User\Model\User; + +class PasswordExpireService implements ServiceInterface +{ + protected $model; + + public function __construct(User $model) + { + $this->model = $model; + } + + public function run() + { + return $this->model->updateAttributes(['last_login_at' => time()]); + } +} diff --git a/src/User/resources/views/admin/index.php b/src/User/resources/views/admin/index.php index cf2bf3c..8827ecc 100644 --- a/src/User/resources/views/admin/index.php +++ b/src/User/resources/views/admin/index.php @@ -92,6 +92,7 @@ $module = Yii::$app->getModule('user'); 'format' => 'raw', 'visible' => Yii::$app->getModule('user')->enableEmailConfirmation, ], + 'password_age', [ 'header' => Yii::t('usuario', 'Block status'), 'value' => function ($model) { @@ -121,7 +122,7 @@ $module = Yii::$app->getModule('user'); ], [ 'class' => 'yii\grid\ActionColumn', - 'template' => '{switch} {reset} {update} {delete}', + 'template' => '{switch} {reset} {force-password-change} {update} {delete}', 'buttons' => [ 'switch' => function ($url, $model) use ($module) { if ($model->id != Yii::$app->user->id && $module->enableSwitchIdentities) { @@ -158,7 +159,24 @@ $module = Yii::$app->getModule('user'); } return null; - } + }, + 'force-password-change' => function ($url, $model) use ($module) { + if (is_null($module->maxPasswordAge)) { + return null; + } + return Html::a( + '', + ['/user/admin/force-password-change', 'id' => $model->id], + [ + 'title' => Yii::t('usuario', 'Force password change at next login'), + 'data-confirm' => Yii::t( + 'usuario', + 'Are you sure you wish the user to change their password at next login?' + ), + 'data-method' => 'POST', + ] + ); + }, ] ], ], From 5484074d8e551327c12e8dbe1af50fb13222c397 Mon Sep 17 00:00:00 2001 From: Lorenzo Milesi Date: Tue, 23 Jan 2018 05:15:01 +0100 Subject: [PATCH 02/35] Enforce password change event only if set #102 --- src/User/Bootstrap.php | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/User/Bootstrap.php b/src/User/Bootstrap.php index b1b69ac..18fb8d2 100644 --- a/src/User/Bootstrap.php +++ b/src/User/Bootstrap.php @@ -147,17 +147,16 @@ class Bootstrap implements BootstrapInterface } // Attach an event to check if the password has expired - Event::on(SecurityController::class, FormEvent::EVENT_AFTER_LOGIN, function (FormEvent $event) { - if (is_null(Yii::$app->getModule('user')->maxPasswordAge)) { - return; - } - $user = $event->form->user; - if ($user->password_age >= Yii::$app->getModule('user')->maxPasswordAge) { - // Force password change - Yii::$app->session->setFlash('warning', Yii::t('usuario', 'Your password has expired, you must change it now')); - Yii::$app->response->redirect(['/user/settings/account'])->send(); - } - }); + if (!is_null(Yii::$app->getModule('user')->maxPasswordAge)) { + Event::on(SecurityController::class, FormEvent::EVENT_AFTER_LOGIN, function (FormEvent $event) { + $user = $event->form->user; + if ($user->password_age >= Yii::$app->getModule('user')->maxPasswordAge) { + // Force password change + Yii::$app->session->setFlash('warning', Yii::t('usuario', 'Your password has expired, you must change it now')); + Yii::$app->response->redirect(['/user/settings/account'])->send(); + } + }); + } if ($app instanceof WebApplication) { // override Yii From ad0c6c86ba52f297723e6012d66357eb1881fe72 Mon Sep 17 00:00:00 2001 From: Lorenzo Milesi Date: Tue, 23 Jan 2018 06:01:39 +0100 Subject: [PATCH 03/35] Password age check filter #102 --- src/User/Filter/PasswordAgeEnforceFilter.php | 39 ++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 src/User/Filter/PasswordAgeEnforceFilter.php diff --git a/src/User/Filter/PasswordAgeEnforceFilter.php b/src/User/Filter/PasswordAgeEnforceFilter.php new file mode 100644 index 0000000..2da75dc --- /dev/null +++ b/src/User/Filter/PasswordAgeEnforceFilter.php @@ -0,0 +1,39 @@ + + * @author Lorenzo Milesi + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Da\User\Filter; + +use Yii; +use yii\base\ActionFilter; + +class PasswordAgeEnforceFilter extends ActionFilter +{ + public function beforeAction($action) + { + $maxPasswordAge = Yii::$app->getModule('user')->maxPasswordAge; + // If feature is not set do nothing (or raise a configuration error?) + if (is_null($maxPasswordAge)) { + return parent::beforeAction($action); + } + if (Yii::$app->user->isGuest) { + // Not our business + return parent::beforeAction($action); + } + if (Yii::$app->user->identity->password_age >= $maxPasswordAge) { + // Force password change + Yii::$app->getSession()->setFlash('warning', Yii::t('usuario', 'Your password has expired, you must change it now')); + return Yii::$app->response->redirect(['/user/settings/account'])->send(); + } + + return parent::beforeAction($action); + } +} From 0362c9bc047add06e66b09dc7dc4e0d68176377f Mon Sep 17 00:00:00 2001 From: Lorenzo Milesi Date: Tue, 23 Jan 2018 06:01:43 +0100 Subject: [PATCH 04/35] Document the maxPasswordAge config parameter #102 --- docs/installation/configuration-options.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/docs/installation/configuration-options.md b/docs/installation/configuration-options.md index 2519ef2..673b1d2 100644 --- a/docs/installation/configuration-options.md +++ b/docs/installation/configuration-options.md @@ -48,6 +48,25 @@ If `true` it will enable password recovery process. If `true` and `allowPasswordRecovery` is false, it will enable administrator to send a password recovery email to a user. +#### maxPasswordAge (type: `integer`, default: `null`) + +If set to an integer value it will check user password age. If the days since last password change are greater than this configuration value +user will be forced to change it. This enforcement is done only at login stage. In order to perform the check in every action you must configure +a filter into your controller like this: +``` +use Da\User\Filter\PasswordAgeEnforceFilter; +class SiteController extends Controller +{ + public function behaviors() + { + return [ + [...] + 'enforcePasswordAge' => [ + 'class' => PasswordAgeEnforceFilter::className(), + ], +``` +This will redirect the user to their account page until the password has been updated. + #### allowAccountDelete (type: `boolean`, default: `true`) If `true` users will be able to remove their own accounts. From 9605f4fa6cfc510fb316ec0adcd5810dce49d990 Mon Sep 17 00:00:00 2001 From: Lorenzo Milesi Date: Tue, 30 Jan 2018 22:17:40 +0100 Subject: [PATCH 05/35] Updated CHANGELOG #102 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 41856fb..cf36194 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## 1.1.2 - Work in progress - Bug #125: Fix validation in non-ajax requests (faenir) - Bug #122: Fix wrong email message for email address change (liviuk2) +- Bug #102: Implemented password expiration feature (maxxer) ## 1.1.1 - November 27, 2017 - Bug #115: Convert client_id to string because pgsql fail with type convertion (Dezinger) From c004a7c4c117f76ccc0f529caffd50a727d09cc8 Mon Sep 17 00:00:00 2001 From: Lorenzo Milesi Date: Wed, 31 Jan 2018 15:05:15 +0100 Subject: [PATCH 06/35] Fix tests --- tests/_data/schema.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/_data/schema.sql b/tests/_data/schema.sql index a700996..0c25fa7 100644 --- a/tests/_data/schema.sql +++ b/tests/_data/schema.sql @@ -73,6 +73,7 @@ CREATE TABLE `user` ( `auth_tf_enabled` tinyint(1) DEFAULT '0', `flags` int(11) NOT NULL DEFAULT '0', `last_login_at` int(11) DEFAULT NULL, + `last_password_change` timestamp, PRIMARY KEY (`id`), UNIQUE KEY `user_unique_email` (`email`), From f61ddb0bf619a35eae6fc571f68b1eb6b1c81e6a Mon Sep 17 00:00:00 2001 From: Alec Pritchard Date: Mon, 5 Feb 2018 16:29:55 +0000 Subject: [PATCH 07/35] Corrected dead link/404 --- docs/installation/advanced-application-template.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installation/advanced-application-template.md b/docs/installation/advanced-application-template.md index 3586f75..68c44e5 100644 --- a/docs/installation/advanced-application-template.md +++ b/docs/installation/advanced-application-template.md @@ -12,7 +12,7 @@ packages, and everything you need to start project in no time with batteries inc > [Check this manual page](sidekit-application-template.md) if you decided to use it. If you want to use the default [Basic Application Template](https://github.com/yiisoft/yii2-app-basic) with our -extension, then check [Basic Application Template documentation page](basic-application-template.md). +extension, then check [Basic Application Template documentation page](yii2-application-template.md). Step 1 - Install Advanced Application template ---------------------------------------------- From bc027f100face86de4d9df64a0a0df60990075ae Mon Sep 17 00:00:00 2001 From: Alec Pritchard Date: Tue, 6 Feb 2018 17:42:45 +0000 Subject: [PATCH 08/35] Improved docs to clarify some grey areas with config for Yii2 Basic Hit some snags, helping out the next guy... --- docs/index.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/docs/index.md b/docs/index.md index 3547ea3..29667a6 100644 --- a/docs/index.md +++ b/docs/index.md @@ -110,10 +110,27 @@ Once we have it installed, we have to configure it on your `config.php` file. 'modules' => [ 'user' => [ 'class' => Da\User\Module::class, + // ...other configs from here: [Configuration Options](installation/configuration-options.md), e.g. + // 'generatePasswords' => true, + // 'switchIdentitySessionKey' => 'myown_usuario_admin_user_key', ] ] ``` +NOTE: If you are using the Yii2 Basic Template, make sure you remove this (default user model config) from your `config.php`, +i.e. `config/web.php` file: + +``` +'components' => [ + 'user' => [ + 'identityClass' => 'app\models\User', + 'enableAutoLogin' => true, + ], +], +``` + +This will ensure the proper functionality of login/guest user detection etc. + Configuration may differ from template to template, the following are some guidelines for sidekit app template and the official Yii2 advanced application template: From 4583f147ffa3f2f6ee2f3153ce5d8c3d583d5f1c Mon Sep 17 00:00:00 2001 From: Lorenzo Milesi Date: Tue, 6 Feb 2018 19:04:27 +0100 Subject: [PATCH 09/35] Renamed field to `password_changed_at` and type INT #102 --- .../m000000_000007_enable_password_expiration.php | 4 ++-- src/User/Model/User.php | 10 +++++----- tests/_data/schema.sql | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/User/Migration/m000000_000007_enable_password_expiration.php b/src/User/Migration/m000000_000007_enable_password_expiration.php index dcee448..f5d70e0 100644 --- a/src/User/Migration/m000000_000007_enable_password_expiration.php +++ b/src/User/Migration/m000000_000007_enable_password_expiration.php @@ -17,11 +17,11 @@ class m000000_000007_enable_password_expiration extends Migration { public function safeUp() { - $this->addColumn('{{%user}}', 'last_password_change', $this->timestamp()->null()); + $this->addColumn('{{%user}}', 'password_changed_at', $this->int()->null()); } public function safeDown() { - $this->dropColumn('{{%user}}', 'last_password_change'); + $this->dropColumn('{{%user}}', 'password_changed_at'); } } diff --git a/src/User/Model/User.php b/src/User/Model/User.php index b765171..4aacbea 100644 --- a/src/User/Model/User.php +++ b/src/User/Model/User.php @@ -50,7 +50,7 @@ use yii\web\IdentityInterface; * @property int $created_at * @property int $updated_at * @property int $last_login_at - * @property int $last_password_change + * @property int $password_changed_at * @property int $password_age * * Defined relations: @@ -98,7 +98,7 @@ class User extends ActiveRecord implements IdentityInterface 'password_hash', $security->generatePasswordHash($this->password, $this->getModule()->blowfishCost) ); - $this->last_password_change = new Expression("NOW()"); + $this->password_changed_at = time(); } return parent::beforeSave($insert); @@ -151,7 +151,7 @@ class User extends ActiveRecord implements IdentityInterface 'created_at' => Yii::t('usuario', 'Registration time'), 'confirmed_at' => Yii::t('usuario', 'Confirmation time'), 'last_login_at' => Yii::t('usuario', 'Last login'), - 'last_password_change' => Yii::t('usuario', 'Last password change'), + 'password_changed_at' => Yii::t('usuario', 'Last password change'), 'password_age' => Yii::t('usuario', 'Password age'), ]; } @@ -341,10 +341,10 @@ class User extends ActiveRecord implements IdentityInterface */ public function getPassword_age() { - if (is_null($this->last_password_change)) { + if (is_null($this->password_changed_at)) { return $this->getModule()->maxPasswordAge; } - $d = new \DateTime($this->last_password_change); + $d = new \DateTime($this->password_changed_at); return $d->diff(new \DateTime(), true)->format("%a"); } } diff --git a/tests/_data/schema.sql b/tests/_data/schema.sql index 0c25fa7..a282a51 100644 --- a/tests/_data/schema.sql +++ b/tests/_data/schema.sql @@ -73,7 +73,7 @@ CREATE TABLE `user` ( `auth_tf_enabled` tinyint(1) DEFAULT '0', `flags` int(11) NOT NULL DEFAULT '0', `last_login_at` int(11) DEFAULT NULL, - `last_password_change` timestamp, + `password_changed_at` int(11) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `user_unique_email` (`email`), From de543058a3b83b121d1f60fdb2ca04036f5dc13c Mon Sep 17 00:00:00 2001 From: Lorenzo Milesi Date: Tue, 6 Feb 2018 23:26:44 +0100 Subject: [PATCH 10/35] Fix typo in column add #102 --- .../Migration/m000000_000007_enable_password_expiration.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/User/Migration/m000000_000007_enable_password_expiration.php b/src/User/Migration/m000000_000007_enable_password_expiration.php index f5d70e0..2761688 100644 --- a/src/User/Migration/m000000_000007_enable_password_expiration.php +++ b/src/User/Migration/m000000_000007_enable_password_expiration.php @@ -17,7 +17,7 @@ class m000000_000007_enable_password_expiration extends Migration { public function safeUp() { - $this->addColumn('{{%user}}', 'password_changed_at', $this->int()->null()); + $this->addColumn('{{%user}}', 'password_changed_at', $this->integer()->null()); } public function safeDown() From e65f93ee717ecc350c953f9f5efb013422344e45 Mon Sep 17 00:00:00 2001 From: Alec Pritchard Date: Wed, 7 Feb 2018 09:25:16 +0000 Subject: [PATCH 11/35] Update index.md --- docs/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.md b/docs/index.md index 29667a6..53b50be 100644 --- a/docs/index.md +++ b/docs/index.md @@ -120,7 +120,7 @@ Once we have it installed, we have to configure it on your `config.php` file. NOTE: If you are using the Yii2 Basic Template, make sure you remove this (default user model config) from your `config.php`, i.e. `config/web.php` file: -``` +```php 'components' => [ 'user' => [ 'identityClass' => 'app\models\User', From b884a67da37a494ddd85227ddc2a8fd94a47595d Mon Sep 17 00:00:00 2001 From: Lorenzo Milesi Date: Wed, 7 Feb 2018 17:15:05 +0100 Subject: [PATCH 12/35] Add conflict configuration to composer.json --- composer.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/composer.json b/composer.json index 8280b34..ad582b5 100644 --- a/composer.json +++ b/composer.json @@ -89,6 +89,10 @@ "pattern-skip-version": "(-build|-patch)" } }, + "conflict": { + "dektrium/yii2-rbac": "*", + "dektrium/yii2-user": "*" + }, "extra": { "bootstrap": "Da\\User\\Bootstrap" } From e1618596fc4c96b896ef9cc79b93097080a15b68 Mon Sep 17 00:00:00 2001 From: Lorenzo Milesi Date: Wed, 7 Feb 2018 22:02:15 +0100 Subject: [PATCH 13/35] Added some documentation about migrating from Dektrium tools #9 --- .../migration-guide-from-dektrium-tools.md | 387 ++++++++++++++++++ 1 file changed, 387 insertions(+) create mode 100644 docs/installation/migration-guide-from-dektrium-tools.md diff --git a/docs/installation/migration-guide-from-dektrium-tools.md b/docs/installation/migration-guide-from-dektrium-tools.md new file mode 100644 index 0000000..8689567 --- /dev/null +++ b/docs/installation/migration-guide-from-dektrium-tools.md @@ -0,0 +1,387 @@ +# Migration guide from Dektrium tools + +yii2-usuario is 99% compatible with [dektrium](https://github.com/dektrium/) tools. + +## Package removal + +First of all you need to remove the old packages. Depending on your installation you +need to remove one or both: +``` +composer remove dektrium/yii2-user +composer remove dektrium/yii2-rbac +``` + +## Configuration + +Configure the `config/console.php` stuff: + +```php + 'authManager' => [ + 'class' => 'yii\rbac\DbManager', + ], +``` + +Configure the controller map for migrations + +```php + 'controllerMap' => [ + 'migrate' => [ + 'class' => 'yii\console\controllers\MigrateController', + 'migrationNamespaces' => [ + 'Da\User\Migration', + ], + ], + ], +``` + +Remove the *modules > rbac* configuration parameter, and replace the value of *modules > user* with: +```php + 'user' => Da\User\Module::class, +``` + +In `config/web.php` remove *module > rbac* configuration and change the *modules > user* with: +```php + ... + 'user' => [ + 'class' => Da\User\Module::class, + // Othe yii2-usuario configuration parameters + 'enableRegistration' => false, + ], + ... +``` + +* If you had `modelMap` customization you have to replace them with `classMap`. +* In your extended model replace the `BaseUser` inheritance from `dektrium\user\models\User` to `Da\User\Model\User` +* If you had controller remapping replace the inheritance from `dektrium\user\controllers\XX` to `Da\User\Controller\XX` + +## Rbac migrations + +[yii2-rbac](https://github.com/dektrium/yii2-rbac) had a nice tool which are rbac migrations, which helped writing new permissions and roles. +There's no such feature in yii2-usuario, but in case you need to still apply them you can: + +1. create a migration component which basically it's the same as the original [Migration](https://github.com/dektrium/yii2-rbac/blob/master/migrations/Migration.php) object, with some minor changes. Copy the content below and save it in your `@app/components/RbacMigration.php`: + ```php + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + + namespace app\components; + + use yii\rbac\DbManager; + use yii\db\Migration; + use yii\di\Instance; + use yii\rbac\Item; + use yii\rbac\Permission; + use yii\rbac\Role; + use yii\rbac\Rule; + + /** + * Migration for applying new RBAC items. + * + * @author Dmitry Erofeev + */ + class RbacMigration extends Migration + { + /** + * @var string|DbManager The auth manager component ID that this migration should work with. + */ + public $authManager = 'authManager'; + + /** + * Initializes the migration. + * This method will set [[authManager]] to be the 'authManager' application component, if it is `null`. + */ + public function init() + { + parent::init(); + + $this->authManager = Instance::ensure($this->authManager, DbManager::className()); + } + + /** + * Creates new permission. + * + * @param string $name The name of the permission + * @param string $description The description of the permission + * @param string|null $ruleName The rule associated with the permission + * @param mixed|null $data The additional data associated with the permission + * @return Permission + */ + protected function createPermission($name, $description = '', $ruleName = null, $data = null) + { + echo " > create permission $name ..."; + $time = microtime(true); + $permission = $this->authManager->createPermission($name); + + $permission->description = $description; + $permission->ruleName = $ruleName; + $permission->data = $data; + + $this->authManager->add($permission); + echo ' done (time: ' . sprintf('%.3f', microtime(true) - $time) . "s)\n"; + + return $permission; + } + + /** + * Creates new role. + * + * @param string $name The name of the role + * @param string $description The description of the role + * @param string|null $ruleName The rule associated with the role + * @param mixed|null $data The additional data associated with the role + * @return Role + */ + protected function createRole($name, $description = '', $ruleName = null, $data = null) + { + echo " > create role $name ..."; + $time = microtime(true); + $role = $this->authManager->createRole($name); + + $role->description = $description; + $role->ruleName = $ruleName; + $role->data = $data; + + $this->authManager->add($role); + echo ' done (time: ' . sprintf('%.3f', microtime(true) - $time) . "s)\n"; + + return $role; + } + + /** + * Creates new rule. + * + * @param string $ruleName The name of the rule + * @param string|array $definition The class of the rule + * @return Rule + */ + protected function createRule($ruleName, $definition) + { + echo " > create rule $ruleName ..."; + $time = microtime(true); + + if (is_array($definition)) { + $definition['name'] = $ruleName; + } else { + $definition = [ + 'class' => $definition, + 'name' => $ruleName, + ]; + } + + /** @var Rule $rule */ + $rule = \Yii::createObject($definition); + + $this->authManager->add($rule); + echo ' done (time: ' . sprintf('%.3f', microtime(true) - $time) . "s)\n"; + + return $rule; + } + + /** + * Finds either role or permission or throws an exception if it is not found. + * + * @param string $name + * @return Permission|Role|null + */ + protected function findItem($name) + { + $item = $this->authManager->getRole($name); + + if ($item instanceof Role) { + return $item; + } + + $item = $this->authManager->getPermission($name); + + if ($item instanceof Permission) { + return $item; + } + + return null; + } + + /** + * Finds the role or throws an exception if it is not found. + * + * @param string $name + * @return Role|null + */ + protected function findRole($name) + { + $role = $this->authManager->getRole($name); + + if ($role instanceof Role) { + return $role; + } + + return null; + } + + /** + * Finds the permission or throws an exception if it is not found. + * + * @param string $name + * @return Permission|null + */ + protected function findPermission($name) + { + $permission = $this->authManager->getPermission($name); + + if ($permission instanceof Permission) { + return $permission; + } + + return null; + } + + /** + * Removes auth item. + * + * @param string|Item $item Either item name or item instance to be removed. + */ + protected function removeItem($item) + { + if (is_string($item)) { + $item = $this->findItem($item); + } + + echo " > removing $item->name ..."; + $time = microtime(true); + $this->authManager->remove($item); + echo ' done (time: ' . sprintf('%.3f', microtime(true) - $time) . "s)\n"; + } + + /** + * Adds child. + * + * @param Item|string $parent Either name or Item instance which is parent + * @param Item|string $child Either name or Item instance which is child + */ + protected function addChild($parent, $child) + { + if (is_string($parent)) { + $parent = $this->findItem($parent); + } + + if (is_string($child)) { + $child = $this->findItem($child); + } + + echo " > adding $child->name as child to $parent->name ..."; + $time = microtime(true); + $this->authManager->addChild($parent, $child); + echo ' done (time: ' . sprintf('%.3f', microtime(true) - $time) . "s)\n"; + } + + /** + * Assigns a role to a user. + * + * @param string|Role $role + * @param string|int $userId + */ + protected function assign($role, $userId) + { + if (is_string($role)) { + $role = $this->findRole($role); + } + + echo " > assigning $role->name to user $userId ..."; + $time = microtime(true); + $this->authManager->assign($role, $userId); + echo ' done (time: ' . sprintf('%.3f', microtime(true) - $time) . "s)\n"; + } + + /** + * Updates role. + * + * @param string|Role $role + * @param string $description + * @param string $ruleName + * @param mixed $data + * @return Role + */ + protected function updateRole($role, $description = '', $ruleName = null, $data = null) + { + if (is_string($role)) { + $role = $this->findRole($role); + } + + echo " > update role $role->name ..."; + $time = microtime(true); + + $role->description = $description; + $role->ruleName = $ruleName; + $role->data = $data; + + $this->authManager->update($role->name, $role); + echo ' done (time: ' . sprintf('%.3f', microtime(true) - $time) . "s)\n"; + + return $role; + } + + /** + * Updates permission. + * + * @param string|Permission $permission + * @param string $description + * @param string $ruleName + * @param mixed $data + * @return Permission + */ + protected function updatePermission($permission, $description = '', $ruleName = null, $data = null) + { + if (is_string($permission)) { + $permission = $this->findPermission($permission); + } + + echo " > update permission $permission->name ..."; + $time = microtime(true); + + $permission->description = $description; + $permission->ruleName = $ruleName; + $permission->data = $data; + + $this->authManager->update($permission->name, $permission); + echo ' done (time: ' . sprintf('%.3f', microtime(true) - $time) . "s)\n"; + + return $permission; + } + + /** + * Updates rule. + * + * @param string $ruleName + * @param string $className + * @return Rule + */ + protected function updateRule($ruleName, $className) + { + echo " > update rule $ruleName ..."; + $time = microtime(true); + + /** @var Rule $rule */ + $rule = \Yii::createObject([ + 'class' => $className, + 'name' => $ruleName, + ]); + + $this->authManager->update($ruleName, $rule); + echo ' done (time: ' . sprintf('%.3f', microtime(true) - $time) . "s)\n"; + + return $rule; + } + } + + ``` + +2. change the inheritance of the `@app/rbac/migrations` files to `app\components\RbacMigration as Migration` + +... and you're done! You can still apply your rbac migrations with `./yii migrate/up --migrationPath=@yii/rbac/migrations`. From b9dc39b3a6cf158057f21994e80edf3f9baab49a Mon Sep 17 00:00:00 2001 From: Lorenzo Milesi Date: Wed, 7 Feb 2018 22:17:49 +0100 Subject: [PATCH 14/35] Allow + sign in username --- src/User/Model/User.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/User/Model/User.php b/src/User/Model/User.php index f6340ad..567bf9e 100644 --- a/src/User/Model/User.php +++ b/src/User/Model/User.php @@ -175,7 +175,7 @@ class User extends ActiveRecord implements IdentityInterface return [ // username rules 'usernameRequired' => ['username', 'required', 'on' => ['register', 'create', 'connect', 'update']], - 'usernameMatch' => ['username', 'match', 'pattern' => '/^[-a-zA-Z0-9_\.@]+$/'], + 'usernameMatch' => ['username', 'match', 'pattern' => '/^[-a-zA-Z0-9_\.@\+]+$/'], 'usernameLength' => ['username', 'string', 'min' => 3, 'max' => 255], 'usernameTrim' => ['username', 'trim'], 'usernameUnique' => [ From 9acc5d47d98c236f10f04b20340a54d950765f8d Mon Sep 17 00:00:00 2001 From: Lorenzo Milesi Date: Thu, 8 Feb 2018 07:12:59 +0100 Subject: [PATCH 15/35] Added changelog for composer and + --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 39497a0..770507a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ - Bug #125: Fix validation in non-ajax requests (faenir) - Bug #122: Fix wrong email message for email address change (liviuk2) - Bug #102: Implemented password expiration feature (maxxer) +- Introduced "conflict" configuration in composer.json (maxxer) +- Allowed the `+` sign in username (maxxer) ## 1.1.1 - November 27, 2017 - Bug #115: Convert client_id to string because pgsql fail with type convertion (Dezinger) From a134574bb5aaba4dff2c594d6388da93ade882bd Mon Sep 17 00:00:00 2001 From: Lorenzo Milesi Date: Thu, 8 Feb 2018 07:23:55 +0100 Subject: [PATCH 16/35] Added link to migration document in index.php and changelog --- CHANGELOG.md | 1 + docs/index.md | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 39497a0..a046ecf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - Bug #125: Fix validation in non-ajax requests (faenir) - Bug #122: Fix wrong email message for email address change (liviuk2) - Bug #102: Implemented password expiration feature (maxxer) +- Bug #9: Documentation about migration from Dektrium tools (maxxer) ## 1.1.1 - November 27, 2017 - Bug #115: Convert client_id to string because pgsql fail with type convertion (Dezinger) diff --git a/docs/index.md b/docs/index.md index 53b50be..dff4e43 100644 --- a/docs/index.md +++ b/docs/index.md @@ -144,6 +144,7 @@ See also all the possible configuration options available: - [Console Commands](installation/console-commands.md) - [Mailer](installation/mailer.md) - [Available Actions](installation/available-actions.md) +- [Migration guide from Dektrium tools](installation/migration-guide-from-dektrium-tools.md) Enhancing and Overriding ------------------------ @@ -188,4 +189,4 @@ Contributing - [How to Contribute](contributing/how-to.md) - [Clean Code](contributing/clean-code.md) -© [2amigos](http://www.2amigos.us/) 2013-2017 +© [2amigos](http://www.2amigos.us/) 2013-2018 From d5b7c4ac5a2f0d2f4ab0b3cfe3d46094b20f4d46 Mon Sep 17 00:00:00 2001 From: Antonio Ramirez Date: Thu, 8 Feb 2018 08:23:21 +0100 Subject: [PATCH 17/35] Fix #139 --- src/User/Widget/ReCaptchaWidget.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/User/Widget/ReCaptchaWidget.php b/src/User/Widget/ReCaptchaWidget.php index aa7e8d6..dfae5ce 100644 --- a/src/User/Widget/ReCaptchaWidget.php +++ b/src/User/Widget/ReCaptchaWidget.php @@ -54,7 +54,7 @@ class ReCaptchaWidget extends InputWidget */ public function init() { - if (Yii::$app->get('recaptcha')) { + if (!Yii::$app->get('recaptcha')) { throw new InvalidConfigException(Yii::t('usuario', 'The "recaptcha" component must be configured.')); } From 5f77b242544b1321b7d3f1ccc39e8b906386a4d9 Mon Sep 17 00:00:00 2001 From: Alec Pritchard Date: Thu, 8 Feb 2018 17:11:32 +0000 Subject: [PATCH 18/35] Bugfix for Model events UserEvent::EVENT_BEFORE_CREATE and UserEvent::EVENT_AFTER_CREATE Feed instance of Da\User\Event\UserEvent to resolve error in event handlers: TypeError Argument 1 passed to {closure}() must be an instance of Da\User\Event\UserEvent, instance of yii\base\Event given --- src/User/Service/UserCreateService.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/User/Service/UserCreateService.php b/src/User/Service/UserCreateService.php index 2463ef2..3705b33 100644 --- a/src/User/Service/UserCreateService.php +++ b/src/User/Service/UserCreateService.php @@ -57,14 +57,15 @@ class UserCreateService implements ServiceInterface ? $model->password : $this->securityHelper->generatePassword(8); - $model->trigger(UserEvent::EVENT_BEFORE_CREATE); + $event = $this->make(UserEvent::class, [$model]); + $model->trigger(UserEvent::EVENT_BEFORE_CREATE, $event); if (!$model->save()) { $transaction->rollBack(); return false; } - $model->trigger(UserEvent::EVENT_AFTER_CREATE); + $model->trigger(UserEvent::EVENT_AFTER_CREATE, $event); if (!$this->sendMail($model)) { Yii::$app->session->setFlash( 'warning', From 4341d2173ba472642ea64f94e764a18d02dc35e4 Mon Sep 17 00:00:00 2001 From: Alec Pritchard Date: Thu, 8 Feb 2018 17:17:16 +0000 Subject: [PATCH 19/35] Bugfix for Model events UserEvent::EVENT_BEFORE_CONFIRMATION and UserEvent::EVENT_AFTER_CONFIRMATION MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bugfix for Model events UserEvent::EVENT_BEFORE_CREATE and UserEvent:… … …:EVENT_AFTER_CREATE Feed instance of Da\User\Event\UserEvent to resolve error in event handlers: TypeError Argument 1 passed to {closure}() must be an instance of Da\User\Event\UserEvent, instance of yii\base\Event given --- src/User/Service/UserConfirmationService.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/User/Service/UserConfirmationService.php b/src/User/Service/UserConfirmationService.php index f0715b8..5958080 100644 --- a/src/User/Service/UserConfirmationService.php +++ b/src/User/Service/UserConfirmationService.php @@ -26,9 +26,12 @@ class UserConfirmationService implements ServiceInterface public function run() { - $this->model->trigger(UserEvent::EVENT_BEFORE_CONFIRMATION); + $model = $this->model; + $event = $this->make(UserEvent::class, [$model]); + + $this->model->trigger(UserEvent::EVENT_BEFORE_CONFIRMATION, $event); if ((bool)$this->model->updateAttributes(['confirmed_at' => time()])) { - $this->model->trigger(UserEvent::EVENT_AFTER_CONFIRMATION); + $this->model->trigger(UserEvent::EVENT_AFTER_CONFIRMATION, $event); return true; } From 53209d2d78530c8ba0698cbcd170c1919fed0c41 Mon Sep 17 00:00:00 2001 From: Lorenzo Milesi Date: Fri, 9 Feb 2018 08:45:39 +0100 Subject: [PATCH 20/35] =?UTF-8?q?Honor=20`enableFlashMessages`=C2=A0config?= =?UTF-8?q?=20param=20in=20`PasswordRecoveryService`=20#110?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + src/User/Service/PasswordRecoveryService.php | 12 ++++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index efd711b..5925824 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ - Enh #143: Introduced "conflict" configuration in composer.json (maxxer) - Enh #145: Allowed the `+` sign in username (maxxer) - Bug #9: Documentation about migration from Dektrium tools (maxxer) +- Bug #110: Honor `enableFlashMessages` in `PasswordRecoveryService` (maxxer) ## 1.1.1 - November 27, 2017 - Bug #115: Convert client_id to string because pgsql fail with type convertion (Dezinger) diff --git a/src/User/Service/PasswordRecoveryService.php b/src/User/Service/PasswordRecoveryService.php index 5f319b0..032257e 100644 --- a/src/User/Service/PasswordRecoveryService.php +++ b/src/User/Service/PasswordRecoveryService.php @@ -16,12 +16,14 @@ use Da\User\Factory\TokenFactory; use Da\User\Model\User; use Da\User\Query\UserQuery; use Da\User\Traits\MailAwareTrait; +use Da\User\Traits\ModuleAwareTrait; use Exception; use Yii; class PasswordRecoveryService implements ServiceInterface { use MailAwareTrait; + use ModuleAwareTrait; protected $query; @@ -58,10 +60,12 @@ class PasswordRecoveryService implements ServiceInterface return false; } - Yii::$app->session->setFlash( - 'info', - Yii::t('usuario', 'An email has been sent with instructions for resetting your password') - ); + if ($this->getModule()->enableFlashMessages == true) { + Yii::$app->session->setFlash( + 'info', + Yii::t('usuario', 'An email has been sent with instructions for resetting your password') + ); + } return true; } catch (Exception $e) { From 4db77a4a84d812b87f8a38dac6a0002410acb3e2 Mon Sep 17 00:00:00 2001 From: Alec Pritchard Date: Fri, 9 Feb 2018 09:19:03 +0000 Subject: [PATCH 21/35] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index efd711b..b60dd52 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # CHANGELOG ## 1.1.2 - Work in progress +- Bug: Bugfix for Model events UserEvent::EVENT_BEFORE_CREATE and UserEvent::EVENT_AFTER_CREATE (ajmedway) - Enh #137: Added the ability to make `enableAutologin` configurable (pappfer) - Enh #135: Added Estonian translation (tonisormisson) - Bug #133: Fix user search returning no results in admin page (phiurs) From b8233114f8f992c69b3e798277ac4b9691f163d3 Mon Sep 17 00:00:00 2001 From: Alec Pritchard Date: Fri, 9 Feb 2018 09:34:01 +0000 Subject: [PATCH 22/35] Added `use MailAwareTrait;` --- src/User/Service/UserConfirmationService.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/User/Service/UserConfirmationService.php b/src/User/Service/UserConfirmationService.php index 5958080..aa18f4b 100644 --- a/src/User/Service/UserConfirmationService.php +++ b/src/User/Service/UserConfirmationService.php @@ -14,9 +14,12 @@ namespace Da\User\Service; use Da\User\Contracts\ServiceInterface; use Da\User\Event\UserEvent; use Da\User\Model\User; +use Da\User\Traits\MailAwareTrait; class UserConfirmationService implements ServiceInterface { + use MailAwareTrait; + protected $model; public function __construct(User $model) From f08babf961f04041a00eb0511d2ad42aacd9c8f8 Mon Sep 17 00:00:00 2001 From: Alec Pritchard Date: Fri, 9 Feb 2018 09:38:00 +0000 Subject: [PATCH 23/35] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b60dd52..a76ab6b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # CHANGELOG ## 1.1.2 - Work in progress +- Bug: Bugfix for Model events UserEvent::EVENT_BEFORE_CONFIRMATION and UserEvent::EVENT_AFTER_CONFIRMATION (ajmedway) - Bug: Bugfix for Model events UserEvent::EVENT_BEFORE_CREATE and UserEvent::EVENT_AFTER_CREATE (ajmedway) - Enh #137: Added the ability to make `enableAutologin` configurable (pappfer) - Enh #135: Added Estonian translation (tonisormisson) From 4928df077017b345dd39bcd935d593cc3acf00bd Mon Sep 17 00:00:00 2001 From: Arthur Khachaturov Date: Fri, 9 Feb 2018 15:41:15 +0300 Subject: [PATCH 24/35] Check enableEmailConfirmation --- src/User/Controller/RegistrationController.php | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/User/Controller/RegistrationController.php b/src/User/Controller/RegistrationController.php index 2834f9d..8c97bce 100644 --- a/src/User/Controller/RegistrationController.php +++ b/src/User/Controller/RegistrationController.php @@ -106,13 +106,17 @@ class RegistrationController extends Controller $mailService = MailFactory::makeWelcomeMailerService($user); if ($this->make(UserRegisterService::class, [$user, $mailService])->run()) { - Yii::$app->session->setFlash( - 'info', - Yii::t( - 'usuario', - 'Your account has been created and a message with further instructions has been sent to your email' - ) - ); + if ($this->module->enableEmailConfirmation) { + Yii::$app->session->setFlash( + 'info', + Yii::t( + 'usuario', + 'Your account has been created and a message with further instructions has been sent to your email' + ) + ); + } else { + Yii::$app->session->setFlash('info', Yii::t('usuario', 'Your account has been created')); + } $this->trigger(FormEvent::EVENT_AFTER_REGISTER, $event); return $this->render( '/shared/message', From 9e2e261bb8db3c63b05409a6753e938a6680e0f6 Mon Sep 17 00:00:00 2001 From: Arthur Khachaturov Date: Fri, 9 Feb 2018 15:41:46 +0300 Subject: [PATCH 25/35] Fix tests --- tests/functional/RegistrationCest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/functional/RegistrationCest.php b/tests/functional/RegistrationCest.php index d496dbe..bad4abf 100644 --- a/tests/functional/RegistrationCest.php +++ b/tests/functional/RegistrationCest.php @@ -50,7 +50,7 @@ class RegistrationCest $I->see(Html::encode('This email address has already been taken')); $this->register($I, 'tester@example.com', 'tester', 'tester'); - $I->see('Your account has been created and a message with further instructions has been sent to your email'); + $I->see('Your account has been created'); $user = $I->grabRecord(User::className(), ['email' => 'tester@example.com']); $I->assertTrue($user->isConfirmed); From a3826ef62ba1956181149c3221c3df1db8d059a8 Mon Sep 17 00:00:00 2001 From: Antonio Ramirez Date: Fri, 9 Feb 2018 13:52:00 +0100 Subject: [PATCH 26/35] Update CHANGELOG.md --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a00c07..188b622 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # CHANGELOG -## 1.1.2 - Work in progress +## 1.1.4 - Work in progress + +## 1.1.2-3 - February 9, 2018 - Bug: Bugfix for Model events UserEvent::EVENT_BEFORE_CONFIRMATION and UserEvent::EVENT_AFTER_CONFIRMATION (ajmedway) - Bug: Bugfix for Model events UserEvent::EVENT_BEFORE_CREATE and UserEvent::EVENT_AFTER_CREATE (ajmedway) - Enh #137: Added the ability to make `enableAutologin` configurable (pappfer) From 73a473e01bb870f5392026e7e15556d3ff986c54 Mon Sep 17 00:00:00 2001 From: Ferenc Papp Date: Fri, 9 Feb 2018 15:06:09 +0100 Subject: [PATCH 27/35] Update Module.php --- src/User/Module.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/User/Module.php b/src/User/Module.php index c7bb564..341b208 100644 --- a/src/User/Module.php +++ b/src/User/Module.php @@ -29,9 +29,9 @@ class Module extends BaseModule */ public $twoFactorAuthenticationCycles = 1; /** - * @var bool whether to allow autologin or not + * @var bool whether to allow auto login or not */ - public $enableAutologin = true; + public $enableAutoLogin = true; /** * @var bool whether to allow registration process or not */ From c324648e41f66c080aa68211f39d845ab92e72c1 Mon Sep 17 00:00:00 2001 From: Ferenc Papp Date: Fri, 9 Feb 2018 15:07:39 +0100 Subject: [PATCH 28/35] Update Bootstrap.php --- src/User/Bootstrap.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/User/Bootstrap.php b/src/User/Bootstrap.php index f166761..b7488a7 100644 --- a/src/User/Bootstrap.php +++ b/src/User/Bootstrap.php @@ -166,7 +166,7 @@ class Bootstrap implements BootstrapInterface $di->set( 'yii\web\User', [ - 'enableAutoLogin' => $app->getModule('user')->enableAutologin, + 'enableAutoLogin' => $app->getModule('user')->enableAutoLogin, 'loginUrl' => ['/user/security/login'], 'identityClass' => $di->get(ClassMapHelper::class)->get(User::class), ] From 7748dc2b3a33fb1bd58b7d22fb5203d7dbc4ea19 Mon Sep 17 00:00:00 2001 From: Antonio Ramirez Date: Tue, 13 Feb 2018 15:20:16 +0100 Subject: [PATCH 29/35] Fixes #154 --- src/User/Model/User.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/User/Model/User.php b/src/User/Model/User.php index 8fcf040..e833ae1 100644 --- a/src/User/Model/User.php +++ b/src/User/Model/User.php @@ -344,7 +344,7 @@ class User extends ActiveRecord implements IdentityInterface if (is_null($this->password_changed_at)) { return $this->getModule()->maxPasswordAge; } - $d = new \DateTime($this->password_changed_at); + $d = new \DateTime("@{$this->password_changed_at}"); return $d->diff(new \DateTime(), true)->format("%a"); } } From da1ed2f66fff890143d9aee2a6cb51653b0374a8 Mon Sep 17 00:00:00 2001 From: Antonio Ramirez Date: Tue, 13 Feb 2018 15:21:13 +0100 Subject: [PATCH 30/35] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 188b622..9a266c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # CHANGELOG ## 1.1.4 - Work in progress +- Fix #154: Fix DateTime constructor with Unix timestamps (tonydspaniard) ## 1.1.2-3 - February 9, 2018 - Bug: Bugfix for Model events UserEvent::EVENT_BEFORE_CONFIRMATION and UserEvent::EVENT_AFTER_CONFIRMATION (ajmedway) From 3dbe415e52986b3d6a1239f19a7655cf63a9153a Mon Sep 17 00:00:00 2001 From: Antonio Ramirez Date: Wed, 14 Feb 2018 06:22:50 +0100 Subject: [PATCH 31/35] Fix #155 --- src/User/Search/RuleSearch.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/User/Search/RuleSearch.php b/src/User/Search/RuleSearch.php index 96270cf..d56b855 100644 --- a/src/User/Search/RuleSearch.php +++ b/src/User/Search/RuleSearch.php @@ -66,8 +66,6 @@ class RuleSearch extends Rule if (!$this->validate()) { $query->where('0=1'); - var_dump($this->load($params)); - die(); } return $this->make( From 60e5ee2b80de3b9e0ecb1593fb41c8a36d2a1ec8 Mon Sep 17 00:00:00 2001 From: Arthur Khachaturov Date: Wed, 14 Feb 2018 13:01:22 +0300 Subject: [PATCH 32/35] Update RegistrationCest.php --- tests/functional/RegistrationCest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/functional/RegistrationCest.php b/tests/functional/RegistrationCest.php index bad4abf..dfc19cf 100644 --- a/tests/functional/RegistrationCest.php +++ b/tests/functional/RegistrationCest.php @@ -96,7 +96,7 @@ class RegistrationCest ]); $I->amOnRoute('/user/registration/register'); $this->register($I, 'tester@example.com', 'tester'); - $I->see('Your account has been created and a message with further instructions has been sent to your email'); + $I->see('Your account has been created'); $user = $I->grabRecord(User::className(), ['email' => 'tester@example.com']); $I->assertEquals('tester', $user->username); /** @var yii\swiftmailer\Message $message */ From 02accba45fc5753b016c79c3367ab6d126dfa209 Mon Sep 17 00:00:00 2001 From: Arthur Khachaturov Date: Wed, 14 Feb 2018 13:06:27 +0300 Subject: [PATCH 33/35] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a266c6..a63d6c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # CHANGELOG ## 1.1.4 - Work in progress +- Enh: Check enableEmailConfirmation on registration (faenir) - Fix #154: Fix DateTime constructor with Unix timestamps (tonydspaniard) ## 1.1.2-3 - February 9, 2018 From 7a1d5311f55f7a9acf763efc1764677663eb8be4 Mon Sep 17 00:00:00 2001 From: Antonio Ramirez Date: Wed, 14 Feb 2018 11:19:53 +0100 Subject: [PATCH 34/35] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a266c6..3131637 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## 1.1.4 - Work in progress - Fix #154: Fix DateTime constructor with Unix timestamps (tonydspaniard) +- Enh #152: Check enableEmailConfirmation (faenir) ## 1.1.2-3 - February 9, 2018 - Bug: Bugfix for Model events UserEvent::EVENT_BEFORE_CONFIRMATION and UserEvent::EVENT_AFTER_CONFIRMATION (ajmedway) From 84552567e0aa889797b020e8e45fa73c3aaf51ce Mon Sep 17 00:00:00 2001 From: Antonio Ramirez Date: Wed, 14 Feb 2018 11:20:30 +0100 Subject: [PATCH 35/35] Update CHANGELOG.md --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8988556..a63d6c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,6 @@ ## 1.1.4 - Work in progress - Enh: Check enableEmailConfirmation on registration (faenir) - Fix #154: Fix DateTime constructor with Unix timestamps (tonydspaniard) -- Enh #152: Check enableEmailConfirmation (faenir) ## 1.1.2-3 - February 9, 2018 - Bug: Bugfix for Model events UserEvent::EVENT_BEFORE_CONFIRMATION and UserEvent::EVENT_AFTER_CONFIRMATION (ajmedway)