From ec0752f27b8de87b1dba01039ec04ecbc62d3ca9 Mon Sep 17 00:00:00 2001 From: Samuel Asor Date: Sun, 17 Jul 2022 07:52:31 +0100 Subject: [PATCH 1/8] Add previousLogin method --- src/Entities/User.php | 11 +++++++++++ src/Models/LoginModel.php | 13 +++++++++++++ 2 files changed, 24 insertions(+) diff --git a/src/Entities/User.php b/src/Entities/User.php index 1ffd1f8b1..fe5b0538c 100644 --- a/src/Entities/User.php +++ b/src/Entities/User.php @@ -242,6 +242,17 @@ public function getPasswordHash(): ?string return $this->password_hash; } + /** + * Returns the previous login information for this user + */ + public function previousLogin(): ?Login + { + /** @var LoginModel $logins */ + $logins = model(LoginModel::class); + + return $logins->previousLogin($this); + } + /** * Returns the last login information for this user as */ diff --git a/src/Models/LoginModel.php b/src/Models/LoginModel.php index f36d91989..63bb8ec15 100644 --- a/src/Models/LoginModel.php +++ b/src/Models/LoginModel.php @@ -67,6 +67,19 @@ public function recordLoginAttempt( $this->checkQueryReturn($return); } + /** + * Returns the previous login information for the user, + * useful to display to the user the last time the account + * was accessed. + */ + public function previousLogin(User $user): ?Login + { + return $this->where('success', 1) + ->where('user_id', $user->id) + ->orderBy('id', 'desc')->get() + ->getRow(1, Login::class); + } + /** * Returns the last login information for the user */ From 95160f82dae4e5e56f838433def86443098b34d0 Mon Sep 17 00:00:00 2001 From: Samuel Asor Date: Mon, 18 Jul 2022 13:29:52 +0100 Subject: [PATCH 2/8] Updated previousLogin method to use the model's method and added test --- src/Models/LoginModel.php | 7 ++++--- tests/Unit/UserTest.php | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/Models/LoginModel.php b/src/Models/LoginModel.php index 63bb8ec15..5fafb42d5 100644 --- a/src/Models/LoginModel.php +++ b/src/Models/LoginModel.php @@ -74,10 +74,11 @@ public function recordLoginAttempt( */ public function previousLogin(User $user): ?Login { - return $this->where('success', 1) + $previous = $this->where('success', 1) ->where('user_id', $user->id) - ->orderBy('id', 'desc')->get() - ->getRow(1, Login::class); + ->orderBy('id', 'desc') + ->findAll(1, 1); + return ($previous) ? $previous[0] : NULL; } /** diff --git a/tests/Unit/UserTest.php b/tests/Unit/UserTest.php index 3c19549b8..deba3b5fa 100644 --- a/tests/Unit/UserTest.php +++ b/tests/Unit/UserTest.php @@ -114,6 +114,41 @@ public function testLastLogin(): void $this->assertInstanceOf(Time::class, $last->date); } + public function testPreviousLogin(): void + { + fake( + UserIdentityModel::class, + ['user_id' => $this->user->id, 'type' => Session::ID_TYPE_EMAIL_PASSWORD, 'secret' => 'foo@example.com'] + ); + + // No logins found. + $this->assertNull($this->user->previousLogin()); + + fake( + LoginModel::class, + ['id_type' => 'email', 'identifier' => $this->user->email, 'user_id' => $this->user->id] + ); + $login2 = fake( + LoginModel::class, + ['id_type' => 'email', 'identifier' => $this->user->email, 'user_id' => $this->user->id] + ); + fake( + LoginModel::class, + [ + 'id_type' => 'email', + 'identifier' => $this->user->email, + 'user_id' => $this->user->id, + 'success' => false, + ] + ); + + $previous = $this->user->previousLogin(); + + $this->assertInstanceOf(Login::class, $previous); // @phpstan-ignore-line + $this->assertSame($login2->id, $previous->id); + $this->assertInstanceOf(Time::class, $previous->date); + } + /** * @see https://github.com/codeigniter4/shield/issues/103 */ From d151ee725b3670726a3b198f72f86ff6e2765ca1 Mon Sep 17 00:00:00 2001 From: Samuel Asor Date: Mon, 18 Jul 2022 13:57:31 +0100 Subject: [PATCH 3/8] Updated previousLogin method to use limit() and first() model methods instead. --- src/Models/LoginModel.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Models/LoginModel.php b/src/Models/LoginModel.php index 5fafb42d5..2d136763c 100644 --- a/src/Models/LoginModel.php +++ b/src/Models/LoginModel.php @@ -74,11 +74,10 @@ public function recordLoginAttempt( */ public function previousLogin(User $user): ?Login { - $previous = $this->where('success', 1) + return $this->where('success', 1) ->where('user_id', $user->id) ->orderBy('id', 'desc') - ->findAll(1, 1); - return ($previous) ? $previous[0] : NULL; + ->limit(1, 1)->first(); } /** From 84fef1e486c837b87e113edfd922dc37fb610b8e Mon Sep 17 00:00:00 2001 From: Samuel Asor Date: Mon, 18 Jul 2022 22:16:20 +0100 Subject: [PATCH 4/8] Added another null check to demonstrate that the very most login is skipped. --- tests/Unit/UserTest.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/Unit/UserTest.php b/tests/Unit/UserTest.php index deba3b5fa..68da13db0 100644 --- a/tests/Unit/UserTest.php +++ b/tests/Unit/UserTest.php @@ -123,11 +123,15 @@ public function testPreviousLogin(): void // No logins found. $this->assertNull($this->user->previousLogin()); - + fake( LoginModel::class, ['id_type' => 'email', 'identifier' => $this->user->email, 'user_id' => $this->user->id] ); + + // The very most login is skipped. + $this->assertNull($this->user->previousLogin()); + $login2 = fake( LoginModel::class, ['id_type' => 'email', 'identifier' => $this->user->email, 'user_id' => $this->user->id] From adfa75f5585fb34fb52589bdccee98360db3d605 Mon Sep 17 00:00:00 2001 From: Samuel Asor Date: Tue, 19 Jul 2022 10:22:02 +0100 Subject: [PATCH 5/8] Updated test file --- tests/Unit/UserTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Unit/UserTest.php b/tests/Unit/UserTest.php index 68da13db0..b97cdc830 100644 --- a/tests/Unit/UserTest.php +++ b/tests/Unit/UserTest.php @@ -132,7 +132,7 @@ public function testPreviousLogin(): void // The very most login is skipped. $this->assertNull($this->user->previousLogin()); - $login2 = fake( + $login1 = fake( LoginModel::class, ['id_type' => 'email', 'identifier' => $this->user->email, 'user_id' => $this->user->id] ); @@ -149,7 +149,7 @@ public function testPreviousLogin(): void $previous = $this->user->previousLogin(); $this->assertInstanceOf(Login::class, $previous); // @phpstan-ignore-line - $this->assertSame($login2->id, $previous->id); + $this->assertSame($login1->id, $previous->id); $this->assertInstanceOf(Time::class, $previous->date); } From 84f539454e4d3e437ff84de64cb274bd9d3ea435 Mon Sep 17 00:00:00 2001 From: Samuel Asor Date: Tue, 19 Jul 2022 10:24:42 +0100 Subject: [PATCH 6/8] Fixed coding style violations --- tests/Unit/UserTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Unit/UserTest.php b/tests/Unit/UserTest.php index b97cdc830..513b46142 100644 --- a/tests/Unit/UserTest.php +++ b/tests/Unit/UserTest.php @@ -123,7 +123,7 @@ public function testPreviousLogin(): void // No logins found. $this->assertNull($this->user->previousLogin()); - + fake( LoginModel::class, ['id_type' => 'email', 'identifier' => $this->user->email, 'user_id' => $this->user->id] From 97052da30f9cf7ab626846d8d9034a5fdad49a52 Mon Sep 17 00:00:00 2001 From: Samuel Asor Date: Sun, 24 Jul 2022 08:38:13 +0100 Subject: [PATCH 7/8] Updated tests: previous now checks for the first login --- tests/Unit/UserTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Unit/UserTest.php b/tests/Unit/UserTest.php index 513b46142..320fa184a 100644 --- a/tests/Unit/UserTest.php +++ b/tests/Unit/UserTest.php @@ -124,7 +124,7 @@ public function testPreviousLogin(): void // No logins found. $this->assertNull($this->user->previousLogin()); - fake( + $login1 = fake( LoginModel::class, ['id_type' => 'email', 'identifier' => $this->user->email, 'user_id' => $this->user->id] ); @@ -132,7 +132,7 @@ public function testPreviousLogin(): void // The very most login is skipped. $this->assertNull($this->user->previousLogin()); - $login1 = fake( + $login2 = fake( LoginModel::class, ['id_type' => 'email', 'identifier' => $this->user->email, 'user_id' => $this->user->id] ); From b1cae0e1f59fe3af4caab89ec1a76f7723a373e0 Mon Sep 17 00:00:00 2001 From: Samuel Asor Date: Sun, 24 Jul 2022 08:57:35 +0100 Subject: [PATCH 8/8] Updated tests: removed used variable. --- tests/Unit/UserTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Unit/UserTest.php b/tests/Unit/UserTest.php index 320fa184a..204b07acb 100644 --- a/tests/Unit/UserTest.php +++ b/tests/Unit/UserTest.php @@ -132,7 +132,7 @@ public function testPreviousLogin(): void // The very most login is skipped. $this->assertNull($this->user->previousLogin()); - $login2 = fake( + fake( LoginModel::class, ['id_type' => 'email', 'identifier' => $this->user->email, 'user_id' => $this->user->id] );