From ab49a901ff27aa22b2b7c1f186768da63991db17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20D?= Date: Mon, 28 Nov 2022 20:42:48 +0100 Subject: [PATCH] chore: Create AccountPresetService tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rubén D --- app/modules/web/Forms/ItemsPresetForm.php | 26 +-- lib/SP/DataModel/ItemPreset/Password.php | 214 +++--------------- .../DataModel/ItemPreset/PresetInterface.php | 33 +++ lib/SP/DataModel/ItemPresetData.php | 191 ++-------------- lib/SP/DataModel/SerializedModel.php | 6 +- .../Account/Services/AccountPresetService.php | 17 +- .../Validators/PasswordValidator.php | 46 ++-- .../Validators/ValidatorInterface.php | 11 +- .../Services/AccountPresetServiceTest.php | 206 +++++++++++++++++ .../SP/Generators/ItemPresetDataGenerator.php | 64 ++++++ 10 files changed, 405 insertions(+), 409 deletions(-) create mode 100644 lib/SP/DataModel/ItemPreset/PresetInterface.php create mode 100644 tests/SP/Domain/Account/Services/AccountPresetServiceTest.php create mode 100644 tests/SP/Generators/ItemPresetDataGenerator.php diff --git a/app/modules/web/Forms/ItemsPresetForm.php b/app/modules/web/Forms/ItemsPresetForm.php index c7eec2d6..ae7a9d70 100644 --- a/app/modules/web/Forms/ItemsPresetForm.php +++ b/app/modules/web/Forms/ItemsPresetForm.php @@ -172,26 +172,24 @@ final class ItemsPresetForm extends FormBase implements FormInterface */ private function makePasswordPreset(): Password { - $password = new Password(); - $password->setLength($this->request->analyzeInt('length', 1)); - $password->setExpireTime($this->request->analyzeInt('expire_time', 0)); - $password->setScore($this->request->analyzeInt('score', 0)); - $regex = $this->request->analyzeUnsafeString('regex'); if (!empty($regex) && Validator::isRegex($regex) === false) { throw new ValidationException(__u('Invalid regular expression')); } - $password->setRegex($regex); - $password->setUseNumbers($this->request->analyzeBool('use_numbers_enabled', false)); - $password->setUseLetters($this->request->analyzeBool('use_letters_enabled', false)); - $password->setUseSymbols($this->request->analyzeBool('use_symbols_enabled', false)); - $password->setUseLower($this->request->analyzeBool('use_lower_enabled', false)); - $password->setUseUpper($this->request->analyzeBool('use_upper_enabled', false)); - $password->setUseImage($this->request->analyzeBool('use_image_enabled', false)); - - return $password; + return new Password( + $this->request->analyzeInt('length', 1), + $this->request->analyzeBool('use_numbers_enabled', false), + $this->request->analyzeBool('use_letters_enabled', false), + $this->request->analyzeBool('use_symbols_enabled', false), + $this->request->analyzeBool('use_upper_enabled', false), + $this->request->analyzeBool('use_lower_enabled', false), + $this->request->analyzeBool('use_image_enabled', false), + $this->request->analyzeInt('expire_time', 0), + $this->request->analyzeInt('score', 0), + $regex + ); } /** diff --git a/lib/SP/DataModel/ItemPreset/Password.php b/lib/SP/DataModel/ItemPreset/Password.php index a8793ce8..070b33c7 100644 --- a/lib/SP/DataModel/ItemPreset/Password.php +++ b/lib/SP/DataModel/ItemPreset/Password.php @@ -4,7 +4,7 @@ * * @author nuxsmin * @link https://syspass.org - * @copyright 2012-2021, Rubén Domínguez nuxsmin@$syspass.org + * @copyright 2012-2022, Rubén Domínguez nuxsmin@$syspass.org * * This file is part of sysPass. * @@ -29,239 +29,91 @@ namespace SP\DataModel\ItemPreset; * * @package SP\DataModel\ItemPreset */ -class Password +class Password implements PresetInterface { - const EXPIRE_TIME_MULTIPLIER = 86400; + private const PRESET_TYPE = 'password'; + + public const EXPIRE_TIME_MULTIPLIER = 86400; /** - * @var int + * @param int $length + * @param bool $useNumbers + * @param bool $useLetters + * @param bool $useSymbols + * @param bool $useUpper + * @param bool $useLower + * @param bool $useImage + * @param int $expireTime + * @param int $score + * @param string|null $regex */ - private $length = 0; - /** - * @var bool - */ - private $useNumbers = false; - /** - * @var bool - */ - private $useLetters = false; - /** - * @var bool - */ - private $useSymbols = false; - /** - * @var bool - */ - private $useUpper = false; - /** - * @var bool - */ - private $useLower = false; - /** - * @var bool - */ - private $useImage = false; - /** - * @var int - */ - private $expireTime = 0; - /** - * @var int - */ - private $score = 0; - /** - * @var string - */ - private $regex; - - /** - * @return string - */ - public function getRegex(): string - { - return $this->regex ?: ''; + public function __construct( + private int $length, + private bool $useNumbers, + private bool $useLetters, + private bool $useSymbols, + private bool $useUpper, + private bool $useLower, + private bool $useImage, + private int $expireTime, + private int $score, + private ?string $regex = null + ) { + $this->expireTime = $expireTime * self::EXPIRE_TIME_MULTIPLIER; } - /** - * @param string $regex - * - * @return Password - */ - public function setRegex(string $regex): Password + public function getRegex(): ?string { - $this->regex = $regex; - return $this; + return $this->regex; } - /** - * @return int - */ public function getScore(): int { return $this->score; } - /** - * @param int $score - * - * @return Password - */ - public function setScore(int $score): Password - { - $this->score = $score; - return $this; - } - - /** - * @return int - */ public function getLength(): int { return $this->length; } - /** - * @param int $length - * - * @return Password - */ - public function setLength(int $length): Password - { - $this->length = $length; - return $this; - } - - /** - * @return bool - */ public function isUseNumbers(): bool { return $this->useNumbers; } - /** - * @param bool $useNumbers - * - * @return Password - */ - public function setUseNumbers(bool $useNumbers): Password - { - $this->useNumbers = $useNumbers; - return $this; - } - - /** - * @return bool - */ public function isUseLetters(): bool { return $this->useLetters; } - /** - * @param bool $useLetters - * - * @return Password - */ - public function setUseLetters(bool $useLetters): Password - { - $this->useLetters = $useLetters; - return $this; - } - - /** - * @return bool - */ public function isUseSymbols(): bool { return $this->useSymbols; } - /** - * @param bool $useSymbols - * - * @return Password - */ - public function setUseSymbols(bool $useSymbols): Password - { - $this->useSymbols = $useSymbols; - return $this; - } - - /** - * @return bool - */ public function isUseUpper(): bool { return $this->useUpper; } - /** - * @param bool $useUpper - * - * @return Password - */ - public function setUseUpper(bool $useUpper): Password - { - $this->useUpper = $useUpper; - return $this; - } - - /** - * @return bool - */ public function isUseLower(): bool { return $this->useLower; } - /** - * @param bool $useLower - * - * @return Password - */ - public function setUseLower(bool $useLower): Password - { - $this->useLower = $useLower; - return $this; - } - - /** - * @return bool - */ public function isUseImage(): bool { return $this->useImage; } - /** - * @param bool $useImage - * - * @return Password - */ - public function setUseImage(bool $useImage): Password - { - $this->useImage = $useImage; - return $this; - } - - /** - * @return int - */ public function getExpireTime(): int { return $this->expireTime; } - /** - * @param int $expireTime - * - * @return Password - */ - public function setExpireTime(int $expireTime): Password + public function getPresetType(): string { - $this->expireTime = $expireTime * self::EXPIRE_TIME_MULTIPLIER; - - return $this; + return self::PRESET_TYPE; } -} \ No newline at end of file +} diff --git a/lib/SP/DataModel/ItemPreset/PresetInterface.php b/lib/SP/DataModel/ItemPreset/PresetInterface.php new file mode 100644 index 00000000..d817a3b2 --- /dev/null +++ b/lib/SP/DataModel/ItemPreset/PresetInterface.php @@ -0,0 +1,33 @@ +. + */ + +namespace SP\DataModel\ItemPreset; + +/** + * Interface PresetInterface + */ +interface PresetInterface +{ + public function getPresetType(): string; +} diff --git a/lib/SP/DataModel/ItemPresetData.php b/lib/SP/DataModel/ItemPresetData.php index 29cb6059..103cce2b 100644 --- a/lib/SP/DataModel/ItemPresetData.php +++ b/lib/SP/DataModel/ItemPresetData.php @@ -36,196 +36,49 @@ class ItemPresetData extends DataModel implements HydratableInterface { use SerializedModel; - /** - * @var int - */ - public $id; - /** - * @var string - */ - public $type; - /** - * @var int - */ - public $userId; - /** - * @var int - */ - public $userGroupId; - /** - * @var int - */ - public $userProfileId; - /** - * @var int - */ - public $fixed; - /** - * @var int - */ - public $priority; - /** - * @var string - */ - public $data; + protected ?int $id = null; + protected ?string $type = null; + protected ?int $userId = null; + protected ?int $userGroupId = null; + protected ?int $userProfileId = null; + protected ?int $fixed = null; + protected ?int $priority = null; + protected ?string $data = null; - /** - * @return int - */ - public function getId(): int + public function getUserGroupId(): ?int { - return $this->id ?? 0; + return $this->userGroupId; } - /** - * @param int $id - * - * @return ItemPresetData - */ - public function setId(int $id) + public function getUserProfileId(): ?int { - $this->id = $id; - - return $this; + return $this->userProfileId; } - /** - * @return int - */ - public function getUserId() + public function getFixed(): ?int { - return $this->userId !== null ? (int)$this->userId : null; + return $this->fixed; } - /** - * @param int $userId - * - * @return ItemPresetData - */ - public function setUserId(int $userId) + public function getPriority(): ?int { - $this->userId = $userId; - - return $this; + return $this->priority; } - /** - * @return int - */ - public function getUserGroupId() - { - return $this->userGroupId !== null ? (int)$this->userGroupId : null; - } - - /** - * @param int $userGroupId - * - * @return ItemPresetData - */ - public function setUserGroupId(int $userGroupId) - { - $this->userGroupId = $userGroupId; - - return $this; - } - - /** - * @return int - */ - public function getUserProfileId() - { - return $this->userProfileId !== null ? (int)$this->userProfileId : null; - } - - /** - * @param int $userProfileId - * - * @return ItemPresetData - */ - public function setUserProfileId(int $userProfileId) - { - $this->userProfileId = $userProfileId; - - return $this; - } - - /** - * @return int - */ - public function getFixed(): int - { - return (int)$this->fixed; - } - - /** - * @param int $fixed - * - * @return ItemPresetData - */ - public function setFixed(int $fixed) - { - $this->fixed = $fixed; - - return $this; - } - - /** - * @return int - */ - public function getPriority(): int - { - return (int)$this->priority; - } - - /** - * @param int $priority - * - * @return ItemPresetData - */ - public function setPriority(int $priority) - { - $this->priority = $priority; - - return $this; - } - - /** - * @return string - */ - public function getData() + public function getData(): ?string { return $this->data; } - /** - * @param string $data - */ - public function setData(string $data) + public function getHash(): string { - $this->data = $data; + return sha1( + $this->type.(int)$this->userId.(int)$this->userGroupId.(int)$this->userProfileId.(int)$this->priority + ); } - /** - * @return string - */ - public function getHash() - { - return sha1($this->type . (int)$this->userId . (int)$this->userGroupId . (int)$this->userProfileId . (int)$this->priority); - } - - /** - * @return string - */ - public function getType() + public function getType(): ?string { return $this->type; } - - /** - * @param string $type - */ - public function setType(string $type) - { - $this->type = $type; - } } diff --git a/lib/SP/DataModel/SerializedModel.php b/lib/SP/DataModel/SerializedModel.php index 7beb5176..b3e81b75 100644 --- a/lib/SP/DataModel/SerializedModel.php +++ b/lib/SP/DataModel/SerializedModel.php @@ -24,7 +24,6 @@ namespace SP\DataModel; - use SP\Core\Exceptions\NoSuchPropertyException; use SP\Util\Util; @@ -36,8 +35,8 @@ use SP\Util\Util; trait SerializedModel { /** - * @param string|null $class - * @param string $property + * @param string|null $class + * @param string $property * * @return mixed|null * @throws NoSuchPropertyException @@ -53,6 +52,7 @@ trait SerializedModel return Util::unserialize($class, $this->{$property}); } + /** @noinspection UnserializeExploitsInspection */ return unserialize($this->{$property}); } diff --git a/lib/SP/Domain/Account/Services/AccountPresetService.php b/lib/SP/Domain/Account/Services/AccountPresetService.php index c27bf829..6152e77b 100644 --- a/lib/SP/Domain/Account/Services/AccountPresetService.php +++ b/lib/SP/Domain/Account/Services/AccountPresetService.php @@ -34,7 +34,7 @@ use SP\Domain\Account\Ports\AccountPresetServiceInterface; use SP\Domain\Config\Ports\ConfigDataInterface; use SP\Domain\ItemPreset\Ports\ItemPresetInterface; use SP\Domain\ItemPreset\Ports\ItemPresetServiceInterface; -use SP\Mvc\Controller\Validators\PasswordValidator; +use SP\Mvc\Controller\Validators\ValidatorInterface; /** * Class AccountPreset @@ -43,16 +43,11 @@ use SP\Mvc\Controller\Validators\PasswordValidator; */ final class AccountPresetService implements AccountPresetServiceInterface { - private ItemPresetServiceInterface $itemPresetService; - private ConfigDataInterface $configData; - public function __construct( - ItemPresetServiceInterface $itemPresetService, - ConfigDataInterface $configData - ) { - $this->itemPresetService = $itemPresetService; - $this->configData = $configData; - } + private ItemPresetServiceInterface $itemPresetService, + private ConfigDataInterface $configData, + private ValidatorInterface $validator + ) {} /** * @throws ValidationException @@ -67,7 +62,7 @@ final class AccountPresetService implements AccountPresetServiceInterface if ($itemPreset !== null && $itemPreset->getFixed() === 1) { $passwordPreset = $itemPreset->hydrate(Password::class); - PasswordValidator::factory($passwordPreset)->validate($accountRequest->pass); + $this->validator->validate($passwordPreset, $accountRequest->pass); if ($this->configData->isAccountExpireEnabled()) { $expireTimePreset = $passwordPreset->getExpireTime(); diff --git a/lib/SP/Mvc/Controller/Validators/PasswordValidator.php b/lib/SP/Mvc/Controller/Validators/PasswordValidator.php index 7e35da66..6ce34d50 100644 --- a/lib/SP/Mvc/Controller/Validators/PasswordValidator.php +++ b/lib/SP/Mvc/Controller/Validators/PasswordValidator.php @@ -4,7 +4,7 @@ * * @author nuxsmin * @link https://syspass.org - * @copyright 2012-2021, Rubén Domínguez nuxsmin@$syspass.org + * @copyright 2012-2022, Rubén Domínguez nuxsmin@$syspass.org * * This file is part of sysPass. * @@ -27,6 +27,9 @@ namespace SP\Mvc\Controller\Validators; use SP\Core\Exceptions\SPException; use SP\Core\Exceptions\ValidationException; use SP\DataModel\ItemPreset\Password; +use SP\DataModel\ItemPreset\PresetInterface; +use function SP\__; +use function SP\__u; /** * Class PasswordValidator @@ -35,38 +38,27 @@ use SP\DataModel\ItemPreset\Password; */ final class PasswordValidator implements ValidatorInterface { - private Password $password; - - /** - * PasswordValidator constructor. - */ - public function __construct(Password $password) - { - $this->password = $password; - } - - public static function factory(Password $password): PasswordValidator - { - return new self($password); - } - /** * @throws ValidationException */ - public function validate(string $string): bool + public function validate(PresetInterface $preset, string $string): bool { - if (mb_strlen($string) < $this->password->getLength()) { + if (!$preset instanceof Password) { + throw new ValidationException(__u('Preset not valid for this validator')); + } + + if (mb_strlen($string) < $preset->getLength()) { throw new ValidationException( sprintf( __('Password needs to be %d characters long'), - $this->password->getLength() + $preset->getLength() ) ); } - $regex = $this->password->getRegex(); + $regex = $preset->getRegex(); - if (!empty($this->password->getRegex()) && !Validator::matchRegex($string, $regex)) { + if (!empty($preset->getRegex()) && !Validator::matchRegex($string, $regex)) { throw new ValidationException( __u('Password does not contain the required characters'), SPException::ERROR, @@ -74,28 +66,28 @@ final class PasswordValidator implements ValidatorInterface ); } - if ($this->password->isUseLetters()) { + if ($preset->isUseLetters()) { if (!Validator::hasLetters($string)) { throw new ValidationException(__u('Password needs to contain letters')); } - if ($this->password->isUseLower() && !Validator::hasLower($string)) { + if ($preset->isUseLower() && !Validator::hasLower($string)) { throw new ValidationException(__u('Password needs to contain lower case letters')); } - if ($this->password->isUseUpper() && !Validator::hasUpper($string)) { + if ($preset->isUseUpper() && !Validator::hasUpper($string)) { throw new ValidationException(__u('Password needs to contain upper case letters')); } } - if ($this->password->isUseNumbers() && !Validator::hasNumbers($string)) { + if ($preset->isUseNumbers() && !Validator::hasNumbers($string)) { throw new ValidationException(__u('Password needs to contain numbers')); } - if ($this->password->isUseSymbols() && !Validator::hasSymbols($string)) { + if ($preset->isUseSymbols() && !Validator::hasSymbols($string)) { throw new ValidationException(__u('Password needs to contain symbols')); } return true; } -} \ No newline at end of file +} diff --git a/lib/SP/Mvc/Controller/Validators/ValidatorInterface.php b/lib/SP/Mvc/Controller/Validators/ValidatorInterface.php index 066eb6f1..7863ded3 100644 --- a/lib/SP/Mvc/Controller/Validators/ValidatorInterface.php +++ b/lib/SP/Mvc/Controller/Validators/ValidatorInterface.php @@ -4,7 +4,7 @@ * * @author nuxsmin * @link https://syspass.org - * @copyright 2012-2021, Rubén Domínguez nuxsmin@$syspass.org + * @copyright 2012-2022, Rubén Domínguez nuxsmin@$syspass.org * * This file is part of sysPass. * @@ -24,6 +24,8 @@ namespace SP\Mvc\Controller\Validators; +use SP\DataModel\ItemPreset\PresetInterface; + /** * Interface ValidatorInterface * @@ -32,9 +34,10 @@ namespace SP\Mvc\Controller\Validators; interface ValidatorInterface { /** - * @param string $string + * @param PresetInterface $preset + * @param string $string * * @return bool */ - public function validate(string $string): bool; -} \ No newline at end of file + public function validate(PresetInterface $preset, string $string): bool; +} diff --git a/tests/SP/Domain/Account/Services/AccountPresetServiceTest.php b/tests/SP/Domain/Account/Services/AccountPresetServiceTest.php new file mode 100644 index 00000000..db32c632 --- /dev/null +++ b/tests/SP/Domain/Account/Services/AccountPresetServiceTest.php @@ -0,0 +1,206 @@ +. + */ + +namespace SP\Tests\Domain\Account\Services; + +use PHPUnit\Framework\MockObject\MockObject; +use SP\Core\Exceptions\ValidationException; +use SP\DataModel\ItemPreset\Password; +use SP\DataModel\ItemPresetData; +use SP\Domain\Account\Dtos\AccountRequest; +use SP\Domain\Account\Services\AccountPresetService; +use SP\Domain\ItemPreset\Ports\ItemPresetInterface; +use SP\Domain\ItemPreset\Ports\ItemPresetServiceInterface; +use SP\Mvc\Controller\Validators\ValidatorInterface; +use SP\Tests\Generators\ItemPresetDataGenerator; +use SP\Tests\UnitaryTestCase; + +/** + * Class AccountPresetServiceTest + */ +class AccountPresetServiceTest extends UnitaryTestCase +{ + + private ItemPresetServiceInterface|MockObject $itemPresetService; + private AccountPresetService $accountPresetService; + private ValidatorInterface|MockObject $passwordValidator; + + /** + * @throws \SP\Core\Exceptions\QueryException + * @throws \SP\Core\Exceptions\ConstraintException + * @throws \SP\Core\Exceptions\ValidationException + * @throws \SP\Core\Exceptions\NoSuchPropertyException + */ + public function testCheckPasswordPreset(): void + { + $this->config->getConfigData()->setAccountExpireEnabled(true); + + $itemPresetDataGenerator = ItemPresetDataGenerator::factory(); + $itemPreset = ItemPresetData::buildFromSimpleModel( + $itemPresetDataGenerator->buildItemPresetData($itemPresetDataGenerator->buildPasswordPreset()) + ); + $itemPreset->fixed = 1; + + $this->itemPresetService + ->expects(self::once()) + ->method('getForCurrentUser') + ->with(ItemPresetInterface::ITEM_TYPE_ACCOUNT_PASSWORD) + ->willReturn($itemPreset); + $this->passwordValidator + ->expects(self::once()) + ->method('validate') + ->with(self::callback(static fn($password) => $password instanceof Password)); + + $this->accountPresetService->checkPasswordPreset($this->buildAccountRequest()); + } + + private function buildAccountRequest(): AccountRequest + { + $accountRequest = new AccountRequest(); + $accountRequest->id = self::$faker->randomNumber(); + $accountRequest->name = self::$faker->name; + $accountRequest->login = self::$faker->userName; + $accountRequest->url = self::$faker->url; + $accountRequest->notes = self::$faker->text; + $accountRequest->userEditId = self::$faker->randomNumber(); + $accountRequest->passDateChange = self::$faker->unixTime; + $accountRequest->clientId = self::$faker->randomNumber(); + $accountRequest->categoryId = self::$faker->randomNumber(); + $accountRequest->isPrivate = self::$faker->numberBetween(0, 1); + $accountRequest->isPrivateGroup = self::$faker->numberBetween(0, 1); + $accountRequest->parentId = self::$faker->randomNumber(); + $accountRequest->userId = self::$faker->randomNumber(); + $accountRequest->userGroupId = self::$faker->randomNumber(); + $accountRequest->key = self::$faker->password; + $accountRequest->pass = self::$faker->password(10, 10); + + return $accountRequest; + } + + /** + * @throws \SP\Core\Exceptions\QueryException + * @throws \SP\Core\Exceptions\ConstraintException + * @throws \SP\Core\Exceptions\ValidationException + * @throws \SP\Core\Exceptions\NoSuchPropertyException + */ + public function testCheckPasswordPresetThrowsValidatorException(): void + { + $this->config->getConfigData()->setAccountExpireEnabled(true); + + $itemPresetDataGenerator = ItemPresetDataGenerator::factory(); + $itemPreset = ItemPresetData::buildFromSimpleModel( + $itemPresetDataGenerator->buildItemPresetData($itemPresetDataGenerator->buildPasswordPreset()) + ); + $itemPreset->fixed = 1; + + $this->itemPresetService + ->expects(self::once()) + ->method('getForCurrentUser') + ->with(ItemPresetInterface::ITEM_TYPE_ACCOUNT_PASSWORD) + ->willReturn($itemPreset); + $this->passwordValidator + ->expects(self::once()) + ->method('validate') + ->with(self::callback(static fn($password) => $password instanceof Password)) + ->willThrowException(new ValidationException('test')); + + $this->expectException(ValidationException::class); + + $this->accountPresetService->checkPasswordPreset($this->buildAccountRequest()); + } + + /** + * @throws \SP\Core\Exceptions\QueryException + * @throws \SP\Core\Exceptions\ConstraintException + * @throws \SP\Core\Exceptions\ValidationException + * @throws \SP\Core\Exceptions\NoSuchPropertyException + */ + public function testCheckPasswordPresetWithoutFixed(): void + { + $itemPresetDataGenerator = ItemPresetDataGenerator::factory(); + $itemPreset = ItemPresetData::buildFromSimpleModel( + $itemPresetDataGenerator->buildItemPresetData($itemPresetDataGenerator->buildPasswordPreset()) + ); + + $itemPreset->fixed = 0; + + $this->itemPresetService + ->expects(self::once()) + ->method('getForCurrentUser') + ->with(ItemPresetInterface::ITEM_TYPE_ACCOUNT_PASSWORD) + ->willReturn($itemPreset); + $this->passwordValidator + ->expects(self::never()) + ->method('validate'); + + $this->accountPresetService->checkPasswordPreset($this->buildAccountRequest()); + } + + /** + * @throws \SP\Core\Exceptions\QueryException + * @throws \SP\Core\Exceptions\ConstraintException + * @throws \SP\Core\Exceptions\ValidationException + * @throws \SP\Core\Exceptions\NoSuchPropertyException + */ + public function testCheckPasswordPresetWithPassDateChangeModified(): void + { + $itemPresetDataGenerator = ItemPresetDataGenerator::factory(); + $passwordPreset = $itemPresetDataGenerator->buildPasswordPreset(); + + $itemPreset = ItemPresetData::buildFromSimpleModel( + $itemPresetDataGenerator->buildItemPresetData($passwordPreset) + ); + $itemPreset->fixed = 1; + + $this->itemPresetService + ->expects(self::once()) + ->method('getForCurrentUser') + ->with(ItemPresetInterface::ITEM_TYPE_ACCOUNT_PASSWORD) + ->willReturn($itemPreset); + $this->passwordValidator + ->expects(self::once()) + ->method('validate'); + + $accountRequest = $this->buildAccountRequest(); + $accountRequest->passDateChange = 0; + + $this->accountPresetService->checkPasswordPreset($accountRequest); + + $this->assertGreaterThan(0, $accountRequest->passDateChange); + } + + protected function setUp(): void + { + parent::setUp(); + + $configData = $this->config->getConfigData(); + $configData->setAccountExpireEnabled(true); + + $this->itemPresetService = $this->createMock(ItemPresetServiceInterface::class); + $this->passwordValidator = $this->createMock(ValidatorInterface::class); + + $this->accountPresetService = + new AccountPresetService($this->itemPresetService, $configData, $this->passwordValidator); + } +} diff --git a/tests/SP/Generators/ItemPresetDataGenerator.php b/tests/SP/Generators/ItemPresetDataGenerator.php new file mode 100644 index 00000000..dd8376e6 --- /dev/null +++ b/tests/SP/Generators/ItemPresetDataGenerator.php @@ -0,0 +1,64 @@ +. + */ + +namespace SP\Tests\Generators; + +use SP\DataModel\ItemPreset\Password; +use SP\Domain\Common\Adapters\SimpleModel; + +/** + * Class ItemPresetDataGenerator + */ +final class ItemPresetDataGenerator extends DataGenerator +{ + public function buildItemPresetData(object $data): SimpleModel + { + return new SimpleModel([ + 'id' => $this->faker->randomNumber(), + 'type' => $this->faker->colorName, + 'userId' => $this->faker->randomNumber(), + 'userGroupId' => $this->faker->randomNumber(), + 'userProfileId' => $this->faker->randomNumber(), + 'fixed' => $this->faker->numberBetween(0, 1), + 'priority' => $this->faker->randomNumber(), + 'data' => serialize($data), + ]); + } + + public function buildPasswordPreset(): Password + { + return new Password( + $this->faker->numberBetween(1, 12), + $this->faker->boolean, + $this->faker->boolean, + $this->faker->boolean, + $this->faker->boolean, + $this->faker->boolean, + $this->faker->boolean, + $this->faker->unixTime, + $this->faker->randomNumber(), + $this->faker->regexify('abc123') + ); + } +}