Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Delete most of the logic, and clean-up what's left #83

Merged
merged 5 commits into from
Oct 25, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 8 additions & 102 deletions lib/uri_format_validator/validators/uri_validator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,32 +13,7 @@ module Validators
# TODO: documentation
#
class UriValidator < ::ActiveModel::EachValidator
SCHEMES = %w[
aaa aaas about acap acct cap cid coap coaps crid data dav dict dns
example file ftp geo go gopher h323 http https iax icap im imap info ipp
ipps iris iris.beep iris.lwz iris.xpc iris.xpcs jabber ldap mailto mid
msrp msrps mtqp mupdate news nfs ni nih nntp opaquelocktoken pkcs11 pop
pres reload rtsp rtsps rtspu service session shttp sieve sip sips sms
snmp soap.beep soap.beeps stun stuns tag tel telnet tftp thismessage tip
tn3270 turn turns tv urn vemmi vnc ws wss xcon xcon-userid xmlrpc.beep
xmlrpc.beeps xmpp z39.50r z39.50s
].freeze

# Examples: http://www.rubular.com/r/Xy4iNY2ztf
RESERVED_DOMAINS = %r{
(\.(test|example|invalid|localhost)$)|
((^|\.)example\.(...?)(\...)?$)
}x

def initialize(options)
@schemes =
case options[:scheme]
when :all then SCHEMES
when nil then %w[http https]
else options[:scheme]
end

options[:message] ||= I18n.t("errors.messages.invalid_uri")
super(options)
end

Expand All @@ -56,16 +31,9 @@ def validate_each(record, attribute, value)

def do_checks(uri_string)
uri = string_to_uri(uri_string)
fail_unless uri

if accept_relative_uris?
validate_domain_absense(uri)
else
validate_domain(uri_string)
validate_against_options(uri, :authority, :scheme, :retrievable)
end
invalid unless uri

validate_against_options(uri, :path, :query, :fragment)
validate_against_options(uri, :retrievable)
end

def string_to_uri(uri_string)
Expand All @@ -75,19 +43,11 @@ def string_to_uri(uri_string)
end

def set_failure_message(record, attribute)
record.errors[attribute] << options[:message]
end

def fail_if(condition)
throw STOP_VALIDATION if condition
record.errors[attribute] << failure_message
end

def fail_unless(condition)
fail_if !condition
end

def validate_domain(uri)
fail_unless uri =~ regexp
def invalid
throw STOP_VALIDATION
end

def validate_against_options(uri, *option_keys_list)
Expand All @@ -97,66 +57,12 @@ def validate_against_options(uri, *option_keys_list)
end
end

def validate_scheme(_option, uri)
scheme = uri.scheme
if @schemes.is_a?(Regexp)
fail_if scheme !~ @schemes
else
fail_unless @schemes.include?(scheme)
end
end

def validate_path(option, uri)
path = uri.path
fail_if option == true && path == "/" || path == ""
fail_if option == false && path != "/" && path != ""
fail_if option.is_a?(Regexp) && path !~ option
end

def validate_query(option, uri)
fail_unless uri.query.present? == option
end

def validate_fragment(option, uri)
fail_unless uri.fragment.present? == option
end

def validate_authority(option, uri)
fail_if option.is_a?(Regexp) && uri.host !~ option
fail_if option.is_a?(Array) && !option.include?(uri.host)

if option.is_a?(Hash) && option[:allow_reserved] == false
check_reserved_domains(uri)
end
end

def validate_retrievable(option, uri)
fail_unless Reacher.new(uri).retrievable? if option
invalid if option && !Reacher.new(uri).retrievable?
end

def accept_relative_uris?
options.key?(:authority) && options[:authority] == false
end

def validate_domain_absense(uri)
fail_if uri.host.present?
end

def check_reserved_domains(uri)
fail_if uri.host =~ RESERVED_DOMAINS
end

def regexp
protocol =
if @schemes.is_a?(Regexp)
"(#{@schemes.source})://"
else
"(#{@schemes.join('|')})://"
end

%r{^#{
protocol
}[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(([0-9]{1,5})?\/.*)?$}iux
def failure_message
options[:message] || I18n.t("errors.messages.invalid_uri")
end
end
end
Expand Down
6 changes: 6 additions & 0 deletions spec/helper_methods_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@
let(:post) { Post.new }

it "provides alternative, old-fashioned way to set validations" do
# Validating URLs requires additional constraints. Not all valid URIs
# with http(s) scheme set are valid URLs. We used to have a RegExp
# for that, but it has been proven to be way too limited.
#
# Disabling for now, these tests may (should be) reintroduced later.
pending "General URL-specific specs have been disabled"
Post.validates_uri_format_of :url

post.url = "http://google"
Expand Down
Loading