I need to add a denylist to a Web application. It is working with a single string. Just not sure how to do it with multiple values
**Below is working fine **
def correct_password_format(password)
(
password.count('0-9').positive? &&
!password.match(/[^A-Za-z0-9]/).nil? &&
password.count('A-Z').positive? && password.count('a-z').positive? &&
password.length >= 8 && password != 'P@ssword1'
end
I need to add more than one item but having a hard time :(
def correct_password_format(password)
(
password.count('0-9').positive? &&
!password.match(/[^A-Za-z0-9]/).nil? &&
password.count('A-Z').positive? && password.count('a-z').positive? &&
password.length >= 8 && password != ['P@ssword1','shabixuege!@#','P@$$W0rd0123','P@ssw0rd5tgb','adminbigdata','Pa$$w0rdp!@#','adm1nistrator1','administrator!@#$'].include?
)
end
CodePudding user response:
You can use include?
to check if a string (the password) is included in an array.
require 'set'
FORBIDDEN_PASSWORDS = Set.new(
['P@ssword1', 'shabixuege!@#', 'P@$$W0rd0123', 'P@ssw0rd5tgb', 'adminbigdata', 'Pa$$w0rdp!@#', 'adm1nistrator1', 'administrator!@#$']
)
def correct_password_format(password)
password.length >= 8 &&
password.match?(/[0-9]/) &&
password.match?(/[A-Z]/) &&
password.match?(/[a-z]/) &&
password.match?(/[^A-Za-z0-9]/) &&
!FORBIDDEN_PASSWORDS.include?(password)
end
I suggest using a Set
to speed up the lookup if this method is used frequently.
CodePudding user response:
You can test that with a regular expression. I will express the regex in free-spacing mode to make it self-documenting.
FORBIDDEN = [
"P@ssword1", "shabixuege!@#", "P@$$W0rd0123", "P@ssw0rd5tgb",
"adminbigdata", "Pa$$w0rdp!@#", "adm1nistrator1", "administrator!@\#$"
]
RGX = /
\A # match beginning of string
(?= # begin positive lookahead
.* # match zero or more characters
\d # match a digit
) # end positive lookahead
(?=.*[A-Z]) # pos lookahead asserts there is an uppercase letter
(?=.*[a-z]) # pos lookahead asserts there is an lowercase letter
(?=.{8}) # pos lookahead asserts there are 8 (or more) chars
(?=.*[^A-Za-z\d]) # pos lookahead asserts there is a char other than
# a letter or digit
(?! # begin a negative lookahead
#{Regexp.union(*FORBIDDEN)}
\z # match end of string
) # end neg lookahead
/x # free-spacing regex definition mode
(?=...)
denotes a positive lookahead (search Positive lookahead and Negative lookahead at the link).
Here
#{Regexp.union(*FORBIDDEN)}
expands to
(?-mix:P@ssword1|shabixuege!@\#|P@\$\$W0rd0123|P@ssw0rd5tgb|adminbigdata|Pa\$\$w0rdp!@\#|adm1nistrator1|administrator!@\#\$)
Note that Regexp::union escapes "#"
and "$"
as they are reserved characters in regular expressions.
We may now write
def correct_password_format(password)
password.match?(RGX)
end
correct_password_format('aA#45678') #=> true
correct_password_format('aA#456789') #=> true
correct_password_format('A0shabixuege!@#') #=> true
correct_password_format('aA#4567') #=> false
correct_password_format('Aa345678') #=> false
correct_password_format('a#345678') #=> false
correct_password_format('a#BCDEFG') #=> false
correct_password_format('adminbigdata') #=> false
Demo. Notice that at the link I've changed the beginning and end of string anchors (\A
and \z
) to beginning and end of line anchors (^
and $
) (and prevented newlines from being matched) so that multiple tests could be performed.
The regular expression could of course be expressed in conventional notation:
RGX = /\A(?=.*\d)(?=.*[A-Z])(?=.*[a-z])(?=.{8})(?=.*[^A-Za-z\d])(?!#{Regexp.union(*FORBIDDEN)}\z)/