66 lines
1.9 KiB
Ruby
66 lines
1.9 KiB
Ruby
|
require_dependency 'carto/base_password_strategy'
|
|||
|
|
|||
|
module Carto
|
|||
|
class StrongPasswordStrategy < BasePasswordStrategy
|
|||
|
|
|||
|
DEFAULT_MIN_LENGTH = 8
|
|||
|
DEFAULT_MAX_LENGTH = 64
|
|||
|
DEFAULT_MIN_NUMBERS = 1
|
|||
|
DEFAULT_MIN_SYMBOLS = 1
|
|||
|
DEFAULT_MIN_LETTERS = 1
|
|||
|
|
|||
|
SYMBOLS = %w({ } [ ] , . < > ; : ‘ “ \? \/ \| \ ` ~ ! @ # $ % ^ & \* ( ) _ - \+ =).freeze
|
|||
|
|
|||
|
def initialize(min_length: DEFAULT_MIN_LENGTH,
|
|||
|
max_length: DEFAULT_MAX_LENGTH,
|
|||
|
min_letters: DEFAULT_MIN_NUMBERS,
|
|||
|
min_symbols: DEFAULT_MIN_SYMBOLS,
|
|||
|
min_numbers: DEFAULT_MIN_LETTERS)
|
|||
|
|
|||
|
@min_length = min_length
|
|||
|
@max_length = max_length
|
|||
|
@min_letters = min_letters
|
|||
|
@min_symbols = min_symbols
|
|||
|
@min_numbers = min_numbers
|
|||
|
end
|
|||
|
|
|||
|
def validate(password, password_confirmation, user = nil)
|
|||
|
errors = super(password, password_confirmation, user)
|
|||
|
return errors if password.nil?
|
|||
|
|
|||
|
if password.length < @min_length
|
|||
|
errors << "must be at least #{@min_length} #{'character'.pluralize(@min_length)} long"
|
|||
|
end
|
|||
|
|
|||
|
if password.length > @max_length
|
|||
|
errors << "must be at most #{@max_length} #{'character'.pluralize(@max_length)} long"
|
|||
|
end
|
|||
|
|
|||
|
if letters_in(password) < @min_letters
|
|||
|
errors << "must contain at least #{@min_letters} #{'letter'.pluralize(@min_letters)}"
|
|||
|
end
|
|||
|
|
|||
|
if symbols_in(password) < @min_symbols && numbers_in(password) < @min_numbers
|
|||
|
errors << "must contain at least #{@min_symbols} #{'symbol'.pluralize(@min_symbols)} or " +
|
|||
|
"#{@min_numbers} #{'number'.pluralize(@min_numbers)}"
|
|||
|
end
|
|||
|
|
|||
|
errors
|
|||
|
end
|
|||
|
|
|||
|
private
|
|||
|
|
|||
|
def letters_in(string)
|
|||
|
string.scan(/[[:alpha:]]/).size
|
|||
|
end
|
|||
|
|
|||
|
def symbols_in(string)
|
|||
|
string.scan(/[#{SYMBOLS.join('|')}]/).size
|
|||
|
end
|
|||
|
|
|||
|
def numbers_in(string)
|
|||
|
string.scan(/\d/).size
|
|||
|
end
|
|||
|
end
|
|||
|
end
|