From e058d92bcb18076a51e29152504dac6dd8a5e4e2 Mon Sep 17 00:00:00 2001 From: Yannick Date: Fri, 10 May 2024 11:54:20 +0200 Subject: [PATCH] [Validator] Make `PasswordStrengthValidator::estimateStrength()` public --- src/Symfony/Component/Validator/CHANGELOG.md | 5 + .../Constraints/PasswordStrengthValidator.php | 2 +- .../PasswordStrengthValidatorTest.php | 16 +++ ...sswordStrengthValidatorWithClosureTest.php | 104 ++++++++++++++++++ 4 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 src/Symfony/Component/Validator/Tests/Constraints/PasswordStrengthValidatorWithClosureTest.php diff --git a/src/Symfony/Component/Validator/CHANGELOG.md b/src/Symfony/Component/Validator/CHANGELOG.md index 0060405821ed1..4e64932a49521 100644 --- a/src/Symfony/Component/Validator/CHANGELOG.md +++ b/src/Symfony/Component/Validator/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +7.2 +--- + + * Make `PasswordStrengthValidator::estimateStrength()` public + 7.1 --- diff --git a/src/Symfony/Component/Validator/Constraints/PasswordStrengthValidator.php b/src/Symfony/Component/Validator/Constraints/PasswordStrengthValidator.php index 96a4a74f7287a..509ea2a42dd3f 100644 --- a/src/Symfony/Component/Validator/Constraints/PasswordStrengthValidator.php +++ b/src/Symfony/Component/Validator/Constraints/PasswordStrengthValidator.php @@ -57,7 +57,7 @@ public function validate(#[\SensitiveParameter] mixed $value, Constraint $constr * * @return PasswordStrength::STRENGTH_* */ - private static function estimateStrength(#[\SensitiveParameter] string $password): int + public static function estimateStrength(#[\SensitiveParameter] string $password): int { if (!$length = \strlen($password)) { return PasswordStrength::STRENGTH_VERY_WEAK; diff --git a/src/Symfony/Component/Validator/Tests/Constraints/PasswordStrengthValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/PasswordStrengthValidatorTest.php index 78e7951a17c9c..fb063f4a719e5 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/PasswordStrengthValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/PasswordStrengthValidatorTest.php @@ -92,4 +92,20 @@ public static function provideInvalidConstraints(): iterable '0', ]; } + + /** + * @dataProvider getPasswordValues + */ + public function testStrengthEstimator(string $password, int $expectedStrength) + { + self::assertSame($expectedStrength, PasswordStrengthValidator::estimateStrength((string) $password)); + } + + public static function getPasswordValues(): iterable + { + yield ['How-is-this', PasswordStrength::STRENGTH_WEAK]; + yield ['Reasonable-pwd', PasswordStrength::STRENGTH_MEDIUM]; + yield ['This 1s a very g00d Pa55word! ;-)', PasswordStrength::STRENGTH_VERY_STRONG]; + yield ['pudding-smack-👌🏼-fox-😎', PasswordStrength::STRENGTH_VERY_STRONG]; + } } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/PasswordStrengthValidatorWithClosureTest.php b/src/Symfony/Component/Validator/Tests/Constraints/PasswordStrengthValidatorWithClosureTest.php new file mode 100644 index 0000000000000..3d24e8c5bbcd6 --- /dev/null +++ b/src/Symfony/Component/Validator/Tests/Constraints/PasswordStrengthValidatorWithClosureTest.php @@ -0,0 +1,104 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Validator\Tests\Constraints; + +use Symfony\Component\Validator\Constraints\PasswordStrength; +use Symfony\Component\Validator\Constraints\PasswordStrengthValidator; +use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; +use Symfony\Component\Validator\Tests\Constraints\Fixtures\StringableValue; + +class PasswordStrengthValidatorWithClosureTest extends ConstraintValidatorTestCase +{ + protected function createValidator(): PasswordStrengthValidator + { + return new PasswordStrengthValidator(static function (string $value) { + $length = \strlen($value); + + return match (true) { + $length < 6 => PasswordStrength::STRENGTH_VERY_WEAK, + $length < 10 => PasswordStrength::STRENGTH_WEAK, + $length < 15 => PasswordStrength::STRENGTH_MEDIUM, + $length < 20 => PasswordStrength::STRENGTH_STRONG, + default => PasswordStrength::STRENGTH_VERY_STRONG, + }; + }); + } + + /** + * @dataProvider getValidValues + */ + public function testValidValues(string|\Stringable $value, int $expectedStrength) + { + $this->validator->validate($value, new PasswordStrength(minScore: $expectedStrength)); + + $this->assertNoViolation(); + + if (PasswordStrength::STRENGTH_VERY_STRONG === $expectedStrength) { + return; + } + + $this->validator->validate($value, new PasswordStrength(minScore: $expectedStrength + 1)); + + $this->buildViolation('The password strength is too low. Please use a stronger password.') + ->setCode(PasswordStrength::PASSWORD_STRENGTH_ERROR) + ->setParameter('{{ strength }}', $expectedStrength) + ->assertRaised(); + } + + public static function getValidValues(): iterable + { + yield ['az34tyu', PasswordStrength::STRENGTH_WEAK]; + yield ['A med1um one', PasswordStrength::STRENGTH_MEDIUM]; + yield ['a str0ng3r one doh', PasswordStrength::STRENGTH_STRONG]; + yield [new StringableValue('HeloW0rld'), PasswordStrength::STRENGTH_WEAK]; + } + + /** + * @dataProvider provideInvalidConstraints + */ + public function testThePasswordIsWeak(PasswordStrength $constraint, string $password, string $expectedMessage, string $expectedCode, string $strength) + { + $this->validator->validate($password, $constraint); + + $this->buildViolation($expectedMessage) + ->setCode($expectedCode) + ->setParameters([ + '{{ strength }}' => $strength, + ]) + ->assertRaised(); + } + + public static function provideInvalidConstraints(): iterable + { + yield [ + new PasswordStrength(), + 'password', + 'The password strength is too low. Please use a stronger password.', + PasswordStrength::PASSWORD_STRENGTH_ERROR, + (string) PasswordStrength::STRENGTH_WEAK, + ]; + yield [ + new PasswordStrength(minScore: PasswordStrength::STRENGTH_VERY_STRONG), + 'Good password?', + 'The password strength is too low. Please use a stronger password.', + PasswordStrength::PASSWORD_STRENGTH_ERROR, + (string) PasswordStrength::STRENGTH_MEDIUM, + ]; + yield [ + new PasswordStrength(message: 'This password should be strong.'), + 'password', + 'This password should be strong.', + PasswordStrength::PASSWORD_STRENGTH_ERROR, + (string) PasswordStrength::STRENGTH_WEAK, + ]; + } +}