Skip to content

Instantly share code, notes, and snippets.

@victorshdev
Created July 9, 2024 13:24
Show Gist options
  • Save victorshdev/379d4be4cfc665953502e6479f6959b1 to your computer and use it in GitHub Desktop.
Save victorshdev/379d4be4cfc665953502e6479f6959b1 to your computer and use it in GitHub Desktop.
Extended version of PasswordStrength (symfony)
<?php
namespace App\Validator\Constraints;
use Symfony\Component\Validator\Constraint;
/**
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*/
#[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
class PasswordStrengthExtended extends Constraint
{
public string $message = 'The password is too weak. Use at least {{ length }} characters, including {{ minUppercase }} uppercase letters, {{ minLowercase }} lowercase letters, {{ minNumbers }} numbers and {{ minSpec }} special characters.';
public function __construct(
public int $minUppercase = 1,
public int $minLowercase = 1,
public int $minNumbers = 1,
public int $minSpec = 1,
public int $minLength = 8,
?array $options = null,
?array $groups = null,
mixed $payload = null,
?string $message = null
) {
parent::__construct($options, $groups, $payload);
$this->message = $message ?? $this->message;
}
}
<?php
namespace App\Validator\Constraints;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
use Symfony\Component\Validator\Exception\UnexpectedValueException;
class PasswordStrengthExtendedValidator extends ConstraintValidator
{
public function validate(mixed $value, Constraint $constraint): void
{
if (!$constraint instanceof PasswordStrengthExtended) {
throw new UnexpectedTypeException($constraint, PasswordStrengthExtended::class);
}
if (null === $value || '' === $value) {
return;
}
if (!\is_scalar($value) && !$value instanceof \Stringable) {
throw new UnexpectedValueException($value, 'string');
}
$arrayValue = str_split($value);
$upper = count(array_filter($arrayValue, fn($l) => \IntlChar::isupper($l)));
$lower = count(array_filter($arrayValue, fn($l) => \IntlChar::islower($l)));
$isDigit = count(array_filter($arrayValue, fn($l) => \IntlChar::isdigit($l)));
$isSymbol = count(array_filter($arrayValue, fn($l) => !\IntlChar::isalpha($l) && !\IntlChar::isdigit($l)));
if ($constraint->minUppercase > $upper
|| $constraint->minLowercase > $lower
|| $constraint->minNumbers > $isDigit
|| $constraint->minSpec > $isSymbol
) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ length }}', $constraint->minLength)
->setParameter('{{ minUppercase }}', $constraint->minUppercase)
->setParameter('{{ minLowercase }}', $constraint->minLowercase)
->setParameter('{{ minNumbers }}', $constraint->minNumbers)
->setParameter('{{ minSpec }}', $constraint->minSpec)
->addViolation();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment