diff --git a/src/Database/Migrations/2020-12-28-223112_create_auth_tables.php b/src/Database/Migrations/2020-12-28-223112_create_auth_tables.php index 3c4ec9e3d..c3c39acf5 100644 --- a/src/Database/Migrations/2020-12-28-223112_create_auth_tables.php +++ b/src/Database/Migrations/2020-12-28-223112_create_auth_tables.php @@ -136,13 +136,13 @@ public function down(): void { $this->db->disableForeignKeyChecks(); - $this->forge->dropTable('users', true); $this->forge->dropTable('auth_logins', true); $this->forge->dropTable('auth_token_logins', true); $this->forge->dropTable('auth_remember_tokens', true); $this->forge->dropTable('auth_identities', true); $this->forge->dropTable('auth_groups_users', true); $this->forge->dropTable('auth_permissions_users', true); + $this->forge->dropTable('users', true); $this->db->enableForeignKeyChecks(); } diff --git a/src/Entities/Cast/IntBoolCast.php b/src/Entities/Cast/IntBoolCast.php new file mode 100644 index 000000000..92402b002 --- /dev/null +++ b/src/Entities/Cast/IntBoolCast.php @@ -0,0 +1,29 @@ + Class property: bool + */ +final class IntBoolCast extends BaseCast +{ + /** + * @param int $value + */ + public static function get($value, array $params = []): bool + { + return (bool) $value; + } + + /** + * @param bool|int|string $value + */ + public static function set($value, array $params = []): int + { + return (int) $value; + } +} diff --git a/src/Entities/Entity.php b/src/Entities/Entity.php new file mode 100644 index 000000000..51b613aea --- /dev/null +++ b/src/Entities/Entity.php @@ -0,0 +1,22 @@ + + * @phpstan-var array + */ + protected $castHandlers = [ + 'int_bool' => IntBoolCast::class, + ]; +} diff --git a/src/Entities/Login.php b/src/Entities/Login.php index 8d0f378a1..640437a7b 100644 --- a/src/Entities/Login.php +++ b/src/Entities/Login.php @@ -2,8 +2,6 @@ namespace CodeIgniter\Shield\Entities; -use CodeIgniter\Entity\Entity; - class Login extends Entity { /** @@ -11,6 +9,6 @@ class Login extends Entity */ protected $casts = [ 'date' => 'datetime', - 'success' => 'boolean', + 'success' => 'int_bool', ]; } diff --git a/src/Entities/User.php b/src/Entities/User.php index 6949ef1a8..ab4b7e568 100644 --- a/src/Entities/User.php +++ b/src/Entities/User.php @@ -3,7 +3,6 @@ namespace CodeIgniter\Shield\Entities; use CodeIgniter\Database\Exceptions\DataException; -use CodeIgniter\Entity\Entity; use CodeIgniter\Shield\Authentication\Authenticators\Session; use CodeIgniter\Shield\Authentication\Traits\HasAccessTokens; use CodeIgniter\Shield\Authorization\Traits\Authorizable; @@ -41,7 +40,7 @@ class User extends Entity */ protected $casts = [ 'id' => '?integer', - 'active' => 'boolean', + 'active' => 'int_bool', 'permissions' => 'array', 'groups' => 'array', ]; diff --git a/src/Entities/UserIdentity.php b/src/Entities/UserIdentity.php index 9637779dd..30fbd47bf 100644 --- a/src/Entities/UserIdentity.php +++ b/src/Entities/UserIdentity.php @@ -2,7 +2,6 @@ namespace CodeIgniter\Shield\Entities; -use CodeIgniter\Entity\Entity; use CodeIgniter\Shield\Authentication\Passwords; /** @@ -25,7 +24,7 @@ class UserIdentity extends Entity * @var array */ protected $casts = [ - 'force_reset' => 'boolean', + 'force_reset' => 'int_bool', ]; /** diff --git a/src/Models/CheckQueryReturnTrait.php b/src/Models/CheckQueryReturnTrait.php index 05b49215a..a49f5a988 100644 --- a/src/Models/CheckQueryReturnTrait.php +++ b/src/Models/CheckQueryReturnTrait.php @@ -21,7 +21,7 @@ private function checkQueryReturn(bool $return): void $message = 'Query error: ' . $error['code'] . ', ' . $error['message'] . ', query: ' . $this->db->getLastQuery(); - throw new DatabaseException($message, $error['code']); + throw new DatabaseException($message, (int) $error['code']); } } diff --git a/tests/Controllers/LoginTest.php b/tests/Controllers/LoginTest.php index d1a49daa5..88368168c 100644 --- a/tests/Controllers/LoginTest.php +++ b/tests/Controllers/LoginTest.php @@ -85,7 +85,7 @@ public function testLoginActionEmailSuccess(): void $this->seeInDatabase('auth_logins', [ 'identifier' => 'foo@example.com', 'user_id' => $this->user->id, - 'success' => true, + 'success' => 1, ]); // Last Used date should have been set $identity = $this->user->getEmailIdentity(); @@ -147,7 +147,7 @@ public function testLoginActionUsernameSuccess(): void $this->seeInDatabase('auth_logins', [ 'identifier' => $this->user->username, 'user_id' => $this->user->id, - 'success' => true, + 'success' => 1, ]); // Last Used date should have been set $identity = $this->user->getEmailIdentity(); diff --git a/tests/Unit/UserModelTest.php b/tests/Unit/UserModelTest.php index e411b6b49..eb5b60075 100644 --- a/tests/Unit/UserModelTest.php +++ b/tests/Unit/UserModelTest.php @@ -60,6 +60,14 @@ public function testInsertUserObject(): void ]); } + /** + * This test is not correct. + * + * Entity's `toArray()` method returns array with properties and values. + * The array may have different keys with the DB column names. + * And the values may be different types with the DB column types. + * So $userArray is not data to be inserted into the database. + */ public function testInsertUserArray(): void { $users = $this->createUserModel(); @@ -67,7 +75,10 @@ public function testInsertUserArray(): void $user = $this->createNewUser(); $userArray = $user->toArray(); - $id = $users->insert($userArray); + // Fix value type + $userArray['active'] = (int) $userArray['active']; + + $id = $users->insert($userArray); $this->dontSeeInDatabase('auth_identities', [ 'user_id' => $id, @@ -85,7 +96,7 @@ private function createNewUser(): User $user->username = 'foo'; $user->email = 'foo@bar.com'; $user->password = 'password'; - $user->active = 0; + $user->active = false; return $user; } @@ -100,7 +111,7 @@ public function testSaveUpdateUserObjectWithUserDataToUpdate(): void $user->username = 'bar'; $user->email = 'bar@bar.com'; - $user->active = 1; + $user->active = true; $users->save($user); @@ -124,7 +135,7 @@ public function testUpdateUserObjectWithUserDataToUpdate(): void $user->username = 'bar'; $user->email = 'bar@bar.com'; - $user->active = 1; + $user->active = true; $users->update(null, $user); @@ -138,6 +149,14 @@ public function testUpdateUserObjectWithUserDataToUpdate(): void ]); } + /** + * This test is not correct. + * + * Entity's `toArray()` method returns array with properties and values. + * The array may have different keys with the DB column names. + * And the values may be different types with the DB column types. + * So $userArray is not data to be inserted into the database. + */ public function testUpdateUserArrayWithUserDataToUpdate(): void { $users = $this->createUserModel(); @@ -148,9 +167,12 @@ public function testUpdateUserArrayWithUserDataToUpdate(): void $user->username = 'bar'; $user->email = 'bar@bar.com'; - $user->active = 1; + $user->active = true; $userArray = $user->toArray(); + // Fix value type + $userArray['active'] = (int) $userArray['active']; + $users->update(null, $userArray); $this->dontSeeInDatabase('auth_identities', [ diff --git a/tests/Unit/UserTest.php b/tests/Unit/UserTest.php index 204b07acb..ec22a0374 100644 --- a/tests/Unit/UserTest.php +++ b/tests/Unit/UserTest.php @@ -160,7 +160,7 @@ public function testUpdateEmail(): void { // Update user's email $this->user->email = 'foo@bar.com'; - $this->user->active = 0; + $this->user->active = false; $users = model(UserModel::class); $users->save($this->user); @@ -182,7 +182,7 @@ public function testUpdatePassword(): void // Update user's email $this->user->email = 'foo@bar.com'; $this->user->password = 'foobar'; - $this->user->active = 0; + $this->user->active = false; $users = model(UserModel::class); $users->save($this->user); @@ -201,7 +201,7 @@ public function testUpdatePasswordHash(): void $hash = service('passwords')->hash('foobar'); $this->user->email = 'foo@bar.com'; $this->user->password_hash = $hash; - $this->user->active = 0; + $this->user->active = false; $users = model(UserModel::class); $users->save($this->user);