validate method
Validates a password against the configured policy.
Implementation
ValidationResult<PasswordValidationIssue, String> validate(String input) {
if (input.isEmpty) {
return const Left(PasswordEmptyIssue());
}
if (input.length < config.minLength) {
return Left(
PasswordTooShortIssue(
currentLength: input.length,
minLength: config.minLength,
),
);
}
if (input.length > config.maxLength) {
return Left(
PasswordTooLongIssue(
currentLength: input.length,
maxLength: config.maxLength,
),
);
}
if (config.requireUppercase && !hasUppercase(input)) {
return const Left(PasswordMissingUppercaseIssue());
}
if (config.requireLowercase && !hasLowercase(input)) {
return const Left(PasswordMissingLowercaseIssue());
}
if (config.requireDigit && !hasDigit(input)) {
return const Left(PasswordMissingDigitIssue());
}
if (config.requireSpecialCharacter && !hasSpecialCharacter(input)) {
return const Left(PasswordMissingSpecialCharacterIssue());
}
final lowered = input.toLowerCase();
if (config.rejectCommonPasswords) {
if (config.commonPasswords.contains(lowered)) {
return const Left(PasswordTooCommonIssue());
}
final hasCommonPrefix = config.commonPrefixes.any(
(prefix) =>
lowered.startsWith(prefix) && lowered.length <= prefix.length + 4,
);
if (hasCommonPrefix) {
return const Left(PasswordTooCommonIssue());
}
}
if (config.rejectRepeatedCharacters && hasOnlyRepeatedCharacters(input)) {
return const Left(PasswordRepeatedCharacterIssue());
}
final sequentialThreshold =
config.minSequentialRun < 3 ? 3 : config.minSequentialRun;
if (config.rejectSequentialPatterns &&
hasSequentialRun(input, minRun: sequentialThreshold)) {
return const Left(PasswordSequentialPatternIssue());
}
return Right(input);
}