From 71f95873748bc6aeed7e10aae1a5e0e5118cace6 Mon Sep 17 00:00:00 2001 From: Kartik Visweswaran Date: Wed, 16 May 2018 18:59:08 +0530 Subject: [PATCH] Add `last-login-ip` capture capability (#184) --- CHANGELOG.md | 1 + src/User/Controller/SecurityController.php | 5 +++- .../m000000_000008_add_last_login_ip.php | 29 +++++++++++++++++++ src/User/Model/User.php | 6 ++-- src/User/Search/UserSearch.php | 12 ++++++-- src/User/Service/PasswordExpireService.php | 6 +++- src/User/resources/views/admin/index.php | 13 +++++++-- tests/_data/schema.sql | 1 + 8 files changed, 64 insertions(+), 9 deletions(-) create mode 100644 src/User/Migration/m000000_000008_add_last_login_ip.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e162fb..04e3992 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # CHANGELOG ## 1.1.5 - Work in progress + - Enh #184: Add `last-login-ip` capture capability (kartik-v) - Enh: Changed `View::render()` calls in views to use absolute paths (ajmedway) - Fix #169: Fix bug in ReCaptchaComponent (BuTaMuH) - Fix #168: Fix spelling in russian language (EvgenyOrekhov) diff --git a/src/User/Controller/SecurityController.php b/src/User/Controller/SecurityController.php index 6d0826f..00c373e 100644 --- a/src/User/Controller/SecurityController.php +++ b/src/User/Controller/SecurityController.php @@ -137,7 +137,10 @@ class SecurityController extends Controller $this->trigger(FormEvent::EVENT_BEFORE_LOGIN, $event); if ($form->login()) { - $form->getUser()->updateAttributes(['last_login_at' => time()]); + $form->getUser()->updateAttributes([ + 'last_login_at' => time(), + 'last_login_ip' => Yii::$app->request->getUserIP(), + ]); $this->trigger(FormEvent::EVENT_AFTER_LOGIN, $event); diff --git a/src/User/Migration/m000000_000008_add_last_login_ip.php b/src/User/Migration/m000000_000008_add_last_login_ip.php new file mode 100644 index 0000000..3bbe4f6 --- /dev/null +++ b/src/User/Migration/m000000_000008_add_last_login_ip.php @@ -0,0 +1,29 @@ +addColumn('{{%user}}', 'last_login_ip', Schema::TYPE_STRING . '(45) DEFAULT NULL AFTER last_login_at'); + } + + /** + * {@inheritdoc} + */ + public function safeDown() + { + $this->dropColumn('{{%user}}', 'last_login_ip'); + } +} diff --git a/src/User/Model/User.php b/src/User/Model/User.php index e833ae1..c268297 100644 --- a/src/User/Model/User.php +++ b/src/User/Model/User.php @@ -43,13 +43,14 @@ use yii\web\IdentityInterface; * @property string $auth_key * @property string $auth_tf_key * @property int $auth_tf_enabled - * @property int $registration_ip + * @property string $registration_ip * @property int $confirmed_at * @property int $blocked_at * @property int $flags * @property int $created_at * @property int $updated_at * @property int $last_login_at + * @property string $last_login_ip * @property int $password_changed_at * @property int $password_age * @@ -150,7 +151,8 @@ class User extends ActiveRecord implements IdentityInterface 'password' => Yii::t('usuario', 'Password'), 'created_at' => Yii::t('usuario', 'Registration time'), 'confirmed_at' => Yii::t('usuario', 'Confirmation time'), - 'last_login_at' => Yii::t('usuario', 'Last login'), + 'last_login_at' => Yii::t('usuario', 'Last login time'), + 'last_login_ip' => Yii::t('usuario', 'Last login IP'), 'password_changed_at' => Yii::t('usuario', 'Last password change'), 'password_age' => Yii::t('usuario', 'Password age'), ]; diff --git a/src/User/Search/UserSearch.php b/src/User/Search/UserSearch.php index ea31688..d8e5085 100644 --- a/src/User/Search/UserSearch.php +++ b/src/User/Search/UserSearch.php @@ -39,6 +39,10 @@ class UserSearch extends Model * @var string */ public $registration_ip; + /** + * @var string + */ + public $last_login_ip; /** * @var UserQuery */ @@ -62,7 +66,7 @@ class UserSearch extends Model public function rules() { return [ - 'safeFields' => [['username', 'email', 'registration_ip', 'created_at', 'last_login_at'], 'safe'], + 'safeFields' => [['username', 'email', 'registration_ip', 'created_at', 'last_login_at, last_login_ip'], 'safe'], 'createdDefault' => [['created_at', 'last_login_at'], 'default', 'value' => null], ]; } @@ -77,7 +81,8 @@ class UserSearch extends Model 'email' => Yii::t('usuario', 'Email'), 'created_at' => Yii::t('usuario', 'Registration time'), 'registration_ip' => Yii::t('usuario', 'Registration IP'), - 'last_login_at' => Yii::t('usuario', 'Last login'), + 'last_login_at' => Yii::t('usuario', 'Last login time'), + 'last_login_ip' => Yii::t('usuario', 'Last login IP'), ]; } @@ -114,7 +119,8 @@ class UserSearch extends Model $query ->andFilterWhere(['like', 'username', $this->username]) ->andFilterWhere(['like', 'email', $this->email]) - ->andFilterWhere(['registration_ip' => $this->registration_ip]); + ->andFilterWhere(['registration_ip' => $this->registration_ip]) + ->andFilterWhere(['last_login_ip' => $this->last_login_ip]); return $dataProvider; } diff --git a/src/User/Service/PasswordExpireService.php b/src/User/Service/PasswordExpireService.php index 6a7e75f..d3487fc 100644 --- a/src/User/Service/PasswordExpireService.php +++ b/src/User/Service/PasswordExpireService.php @@ -11,6 +11,7 @@ namespace Da\User\Service; +use Yii; use Da\User\Contracts\ServiceInterface; use Da\User\Model\User; @@ -25,6 +26,9 @@ class PasswordExpireService implements ServiceInterface public function run() { - return $this->model->updateAttributes(['last_login_at' => time()]); + return $this->model->updateAttributes([ + 'last_login_at' => time(), + 'last_login_ip' => Yii::$app->request->getUserIP(), + ]); } } diff --git a/src/User/resources/views/admin/index.php b/src/User/resources/views/admin/index.php index 8827ecc..c9a9e46 100644 --- a/src/User/resources/views/admin/index.php +++ b/src/User/resources/views/admin/index.php @@ -52,7 +52,7 @@ $module = Yii::$app->getModule('user'); 'attribute' => 'created_at', 'value' => function ($model) { if (extension_loaded('intl')) { - return Yii::t('usuario', '{0, date, MMMM dd, YYYY HH:mm}', [$model->created_at]); + return Yii::t('usuario', '{0, date, MMM dd, YYYY HH:mm}', [$model->created_at]); } return date('Y-m-d G:i:s', $model->created_at); @@ -64,12 +64,21 @@ $module = Yii::$app->getModule('user'); if (!$model->last_login_at || $model->last_login_at == 0) { return Yii::t('usuario', 'Never'); } elseif (extension_loaded('intl')) { - return Yii::t('usuario', '{0, date, MMMM dd, YYYY HH:mm}', [$model->last_login_at]); + return Yii::t('usuario', '{0, date, MMM dd, YYYY HH:mm}', [$model->last_login_at]); } else { return date('Y-m-d G:i:s', $model->last_login_at); } }, ], + [ + 'attribute' => 'last_login_ip', + 'value' => function ($model) { + return $model->last_login_ip == null + ? '' . Yii::t('usuario', '(not set)') . '' + : $model->last_login_ip; + }, + 'format' => 'html', + ], [ 'header' => Yii::t('usuario', 'Confirmation'), 'value' => function ($model) { diff --git a/tests/_data/schema.sql b/tests/_data/schema.sql index a282a51..ae108a9 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_login_ip` varchar(45) DEFAULT NULL, `password_changed_at` int(11) DEFAULT NULL, PRIMARY KEY (`id`),