Class: NotPwnedValidator
- Inherits:
-
ActiveModel::EachValidator
- Object
- ActiveModel::EachValidator
- NotPwnedValidator
- Defined in:
- lib/pwned/not_pwned_validator.rb
Overview
An ActiveModel
validator to check passwords against the Pwned Passwords API.
Direct Known Subclasses
Constant Summary collapse
- DEFAULT_ON_ERROR =
The default behaviour of this validator in the case of an API failure. The default will mean that if the API fails the object will not be marked invalid.
:valid
- DEFAULT_THRESHOLD =
The default threshold for whether a breach is considered pwned. The default is 0, so any password that appears in a breach will mark the record as invalid.
0
Instance Method Summary collapse
-
#validate_each(record, attribute, value) ⇒ Object
Validates the
value
against the Pwned Passwords API.
Instance Method Details
#validate_each(record, attribute, value) ⇒ Object
Validates the value
against the Pwned Passwords API. If the pwned_count
is higher than the optional threshold
then the record is marked as invalid.
In the case of an API error the validator will either mark the record as valid or invalid. Alternatively it will run an associated proc or re-raise the original error.
The validation will short circuit and return with no errors added if the password is blank. The Pwned::Password
initializer expects the password to be a string and will throw a TypeError
if it is nil
. Also, technically the empty string is not a password that is reported to be found in data breaches, so returns false
, short circuiting that using value.blank?
saves us a trip to the API.
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/pwned/not_pwned_validator.rb', line 77 def validate_each(record, attribute, value) return if value.blank? begin pwned_check = Pwned::Password.new(value, ) if pwned_check.pwned_count > threshold record.errors.add(attribute, :not_pwned, **.merge(count: pwned_check.pwned_count)) end rescue Pwned::Error => error case on_error when :invalid record.errors.add(attribute, :pwned_error, **.merge(message: [:error_message])) when :valid # Do nothing, consider the record valid when Proc on_error.call(record, error) else raise end end end |