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
valueagainst 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 |