From 17083f10d84f2a308a24e6644ecf702c5c021f6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20D?= Date: Sun, 12 Nov 2023 10:47:51 +0100 Subject: [PATCH] chore(tests): UT for Database auth MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rubén D --- lib/SP/DataModel/UserData.php | 38 +-- lib/SP/Domain/Common/Models/Model.php | 38 +-- .../Auth/Database/DatabaseAuthTest.php | 260 ++++++++++++++++++ 3 files changed, 299 insertions(+), 37 deletions(-) create mode 100644 tests/SP/Providers/Auth/Database/DatabaseAuthTest.php diff --git a/lib/SP/DataModel/UserData.php b/lib/SP/DataModel/UserData.php index 2b4139c7..42ff8f3a 100644 --- a/lib/SP/DataModel/UserData.php +++ b/lib/SP/DataModel/UserData.php @@ -35,25 +35,25 @@ defined('APP_ROOT') || die(); */ class UserData extends UserPassData implements DataModelInterface { - public ?string $login = null; - public ?string $ssoLogin = null; - public ?string $name = null; - public ?string $email = null; - public ?string $notes = null; - public ?int $userGroupId = null; - public ?int $userProfileId = null; - public ?int $isAdminApp = null; - public bool $isAdminAcc = false; - public bool $isDisabled = false; - public bool $isChangePass = false; - public bool $isChangedPass = false; - public bool $isLdap = false; - public ?int $loginCount = null; - public ?string $lastLogin = null; - public ?string $lastUpdate = null; - public ?bool $isMigrate = false; - public ?string $preferences = null; - public ?string $userGroupName = null; + protected ?string $login = null; + protected ?string $ssoLogin = null; + protected ?string $name = null; + protected ?string $email = null; + protected ?string $notes = null; + protected ?int $userGroupId = null; + protected ?int $userProfileId = null; + protected ?int $isAdminApp = null; + protected bool $isAdminAcc = false; + protected bool $isDisabled = false; + protected bool $isChangePass = false; + protected bool $isChangedPass = false; + protected bool $isLdap = false; + protected ?int $loginCount = null; + protected ?string $lastLogin = null; + protected ?string $lastUpdate = null; + protected ?bool $isMigrate = false; + protected ?string $preferences = null; + protected ?string $userGroupName = null; public function getLoginCount(): int { diff --git a/lib/SP/Domain/Common/Models/Model.php b/lib/SP/Domain/Common/Models/Model.php index 925e89e7..89c3e09b 100644 --- a/lib/SP/Domain/Common/Models/Model.php +++ b/lib/SP/Domain/Common/Models/Model.php @@ -24,12 +24,14 @@ namespace SP\Domain\Common\Models; +use ArrayAccess; +use JsonException; use JsonSerializable; /** * Class DataModel */ -abstract class Model implements JsonSerializable, \ArrayAccess +abstract class Model implements JsonSerializable, ArrayAccess { /** * Dynamically declared properties. Must not be class' properties @@ -67,7 +69,7 @@ abstract class Model implements JsonSerializable, \ArrayAccess /** * Build a new concrete object from a simple model * - * @param \SP\Domain\Common\Models\Simple $model + * @param Simple $model * * @return static */ @@ -77,9 +79,9 @@ abstract class Model implements JsonSerializable, \ArrayAccess } /** - * @param array|null $only Include only these properties - * @param array|null $filter Filter out these properties - * @param bool $includeOuter Whether to include non-class properties + * @param array|null $only Include only these properties + * @param array|null $filter Filter out these properties + * @param bool $includeOuter Whether to include non-class properties * * @return array */ @@ -105,7 +107,7 @@ abstract class Model implements JsonSerializable, \ArrayAccess /** * Get columns name for this model * - * @param array|null $filter + * @param array|null $filter * * @return array */ @@ -119,7 +121,7 @@ abstract class Model implements JsonSerializable, \ArrayAccess /** * Create a new object with properties changed * - * @param array $properties + * @param array $properties * * @return $this */ @@ -132,7 +134,7 @@ abstract class Model implements JsonSerializable, \ArrayAccess * Convert the model to its string representation. * * @return string - * @throws \JsonException + * @throws JsonException */ public function __toString() { @@ -142,10 +144,10 @@ abstract class Model implements JsonSerializable, \ArrayAccess /** * Convert the model instance to JSON. * - * @param int $options + * @param int $options * * @return string - * @throws \JsonException + * @throws JsonException */ public function toJson(int $options = 0): string { @@ -168,7 +170,7 @@ abstract class Model implements JsonSerializable, \ArrayAccess /** * Get non-class properties * - * @param string $name + * @param string $name * * @return void */ @@ -180,7 +182,7 @@ abstract class Model implements JsonSerializable, \ArrayAccess /** * Set non-class properties * - * @param string $name + * @param string $name * @param $value * * @return void @@ -193,7 +195,7 @@ abstract class Model implements JsonSerializable, \ArrayAccess /** * Get non-class properties * - * @param mixed $offset + * @param mixed $offset * * @return mixed */ @@ -205,8 +207,8 @@ abstract class Model implements JsonSerializable, \ArrayAccess /** * Set non-class properties * - * @param mixed $offset - * @param mixed $value + * @param mixed $offset + * @param mixed $value * * @return void */ @@ -220,14 +222,14 @@ abstract class Model implements JsonSerializable, \ArrayAccess * * @link https://php.net/manual/en/arrayaccess.offsetexists.php * - * @param mixed $offset

+ * @param mixed $offset

* An offset to check for. *

* * @return bool true on success or false on failure. *

*

- * The return value will be casted to boolean if non-boolean was returned. + * The return value will be cast to boolean if non-boolean was returned. */ public function offsetExists(mixed $offset): bool { @@ -237,7 +239,7 @@ abstract class Model implements JsonSerializable, \ArrayAccess /** * Unset a non-class property * - * @param mixed $offset + * @param mixed $offset * * @return void */ diff --git a/tests/SP/Providers/Auth/Database/DatabaseAuthTest.php b/tests/SP/Providers/Auth/Database/DatabaseAuthTest.php new file mode 100644 index 00000000..972ed2d8 --- /dev/null +++ b/tests/SP/Providers/Auth/Database/DatabaseAuthTest.php @@ -0,0 +1,260 @@ +. + */ + +namespace SP\Tests\Providers\Auth\Database; + +use PHPUnit\Framework\MockObject\MockObject; +use SP\Core\Crypt\Hash; +use SP\DataModel\UserLoginData; +use SP\Domain\User\Ports\UserPassServiceInterface; +use SP\Domain\User\Ports\UserServiceInterface; +use SP\Infrastructure\Common\Repositories\NoSuchItemException; +use SP\Providers\Auth\Database\DatabaseAuth; +use SP\Tests\Generators\UserDataGenerator; +use SP\Tests\UnitaryTestCase; + +/** + * Class DatabaseAuthTest + * + * @group unitary + */ +class DatabaseAuthTest extends UnitaryTestCase +{ + + private UserServiceInterface|MockObject $userService; + private MockObject|UserPassServiceInterface $userPassService; + private DatabaseAuth $databaseAuth; + + public function testAuthenticate() + { + $user = self::$faker->userName; + $pass = self::$faker->password; + $hashedPass = Hash::hashKey($pass); + + $userData = UserDataGenerator::factory()->buildUserData()->mutate(['login' => $user, 'pass' => $hashedPass]); + + $this->userService + ->expects(self::once()) + ->method('getByLogin') + ->with($user) + ->willReturn($userData); + + $userLoginData = new UserLoginData(); + $userLoginData->setLoginUser($user); + $userLoginData->setLoginPass($pass); + + self::assertTrue($this->databaseAuth->authenticate($userLoginData)->isOk()); + } + + public function testAuthenticateWithWrongLogin() + { + $user = self::$faker->userName; + $pass = self::$faker->password; + + $this->userService + ->expects(self::once()) + ->method('getByLogin') + ->with($user) + ->willThrowException(new NoSuchItemException('User does not exist')); + + $userLoginData = new UserLoginData(); + $userLoginData->setLoginUser($user); + $userLoginData->setLoginPass($pass); + + self::assertFalse($this->databaseAuth->authenticate($userLoginData)->isOk()); + } + + public function testAuthenticateWithWrongPass() + { + $user = self::$faker->userName; + $pass = self::$faker->password; + + $userData = UserDataGenerator::factory()->buildUserData()->mutate(['login' => $user]); + + $this->userService + ->expects(self::once()) + ->method('getByLogin') + ->with($user) + ->willReturn($userData); + + $userLoginData = new UserLoginData(); + $userLoginData->setLoginUser($user); + $userLoginData->setLoginPass($pass); + + self::assertFalse($this->databaseAuth->authenticate($userLoginData)->isOk()); + } + + public function testAuthenticateWithMigrationBySHA1() + { + $user = self::$faker->userName; + $pass = self::$faker->password; + + $userData = UserDataGenerator::factory() + ->buildUserData() + ->mutate( + [ + 'login' => $user, + 'pass' => md5($pass), + 'isMigrate' => true + ] + ); + + $this->userService + ->expects(self::once()) + ->method('getByLogin') + ->with($user) + ->willReturn($userData); + + $this->userPassService + ->expects(self::once()) + ->method('migrateUserPassById') + ->with($userData->getId(), $pass); + + $userLoginData = new UserLoginData(); + $userLoginData->setLoginUser($user); + $userLoginData->setLoginPass($pass); + + self::assertTrue($this->databaseAuth->authenticate($userLoginData)->isOk()); + } + + public function testAuthenticateWithMigrationByMD5() + { + $user = self::$faker->userName; + $pass = self::$faker->password; + $salt = self::$faker->password; + + $userData = UserDataGenerator::factory() + ->buildUserData() + ->mutate( + [ + 'login' => $user, + 'pass' => sha1($salt . $pass), + 'hashSalt' => $salt, + 'isMigrate' => true + ] + ); + + $this->userService + ->expects(self::once()) + ->method('getByLogin') + ->with($user) + ->willReturn($userData); + + $this->userPassService + ->expects(self::once()) + ->method('migrateUserPassById') + ->with($userData->getId(), $pass); + + $userLoginData = new UserLoginData(); + $userLoginData->setLoginUser($user); + $userLoginData->setLoginPass($pass); + + self::assertTrue($this->databaseAuth->authenticate($userLoginData)->isOk()); + } + + public function testAuthenticateWithMigrationByCrypt() + { + $user = self::$faker->userName; + $pass = self::$faker->password; + $salt = self::$faker->password; + + $userData = UserDataGenerator::factory() + ->buildUserData() + ->mutate( + [ + 'login' => $user, + 'pass' => crypt($pass, $salt), + 'hashSalt' => $salt, + 'isMigrate' => true + ] + ); + + $this->userService + ->expects(self::once()) + ->method('getByLogin') + ->with($user) + ->willReturn($userData); + + $this->userPassService + ->expects(self::once()) + ->method('migrateUserPassById') + ->with($userData->getId(), $pass); + + $userLoginData = new UserLoginData(); + $userLoginData->setLoginUser($user); + $userLoginData->setLoginPass($pass); + + self::assertTrue($this->databaseAuth->authenticate($userLoginData)->isOk()); + } + + public function testAuthenticateWithMigrationByHash() + { + $user = self::$faker->userName; + $pass = self::$faker->password; + $hashedPass = Hash::hashKey($pass); + + $userData = UserDataGenerator::factory() + ->buildUserData() + ->mutate( + [ + 'login' => $user, + 'pass' => $hashedPass, + 'isMigrate' => true + ] + ); + + $this->userService + ->expects(self::once()) + ->method('getByLogin') + ->with($user) + ->willReturn($userData); + + $this->userPassService + ->expects(self::once()) + ->method('migrateUserPassById') + ->with($userData->getId(), $pass); + + $userLoginData = new UserLoginData(); + $userLoginData->setLoginUser($user); + $userLoginData->setLoginPass($pass); + + self::assertTrue($this->databaseAuth->authenticate($userLoginData)->isOk()); + } + + public function testIsAuthGranted() + { + self::assertTrue($this->databaseAuth->isAuthGranted()); + } + + protected function setUp(): void + { + parent::setUp(); + + $this->userService = $this->createMock(UserServiceInterface::class); + $this->userPassService = $this->createMock(UserPassServiceInterface::class); + + $this->databaseAuth = new DatabaseAuth($this->userService, $this->userPassService); + } + +}