Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThong Kuah <tkuah@gitlab.com>2019-04-11 09:29:07 +0300
committerJames Lopez <james@gitlab.com>2019-04-11 09:29:07 +0300
commitd119d3d1b25aac661e6251addf87b280bd37f0c5 (patch)
treeaeaf0d9503326ec7f51968e8d1de48d83ce90503 /spec/validators/addressable_url_validator_spec.rb
parent79bf4bdaad438dc0f82771b102f3c07225a428da (diff)
Align UrlValidator to validate_url gem implementation.
Renamed UrlValidator to AddressableUrlValidator to avoid 'url:' naming collision with ActiveModel::Validations::UrlValidator in 'validates' statement. Make use of the options attribute of the parent class ActiveModel::EachValidator. Add more options: allow_nil, allow_blank, message. Renamed 'protocols' option to 'schemes' to match the option naming from UrlValidator.
Diffstat (limited to 'spec/validators/addressable_url_validator_spec.rb')
-rw-r--r--spec/validators/addressable_url_validator_spec.rb315
1 files changed, 315 insertions, 0 deletions
diff --git a/spec/validators/addressable_url_validator_spec.rb b/spec/validators/addressable_url_validator_spec.rb
new file mode 100644
index 00000000000..387e84b2d04
--- /dev/null
+++ b/spec/validators/addressable_url_validator_spec.rb
@@ -0,0 +1,315 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe AddressableUrlValidator do
+ let!(:badge) { build(:badge, link_url: 'http://www.example.com') }
+ subject { validator.validate(badge) }
+
+ include_examples 'url validator examples', described_class::DEFAULT_OPTIONS[:schemes]
+
+ describe 'validations' do
+ include_context 'invalid urls'
+
+ let(:validator) { described_class.new(attributes: [:link_url]) }
+
+ it 'returns error when url is nil' do
+ expect(validator.validate_each(badge, :link_url, nil)).to be_falsey
+ expect(badge.errors.first[1]).to eq validator.options.fetch(:message)
+ end
+
+ it 'returns error when url is empty' do
+ expect(validator.validate_each(badge, :link_url, '')).to be_falsey
+ expect(badge.errors.first[1]).to eq validator.options.fetch(:message)
+ end
+
+ it 'does not allow urls with CR or LF characters' do
+ aggregate_failures do
+ urls_with_CRLF.each do |url|
+ expect(validator.validate_each(badge, :link_url, url)[0]).to eq 'is blocked: URI is invalid'
+ end
+ end
+ end
+
+ it 'provides all arguments to UrlBlock validate' do
+ expect(Gitlab::UrlBlocker)
+ .to receive(:validate!)
+ .with(badge.link_url, described_class::BLOCKER_VALIDATE_OPTIONS)
+ .and_return(true)
+
+ subject
+
+ expect(badge.errors).to be_empty
+ end
+ end
+
+ context 'by default' do
+ let(:validator) { described_class.new(attributes: [:link_url]) }
+
+ it 'does not block urls pointing to localhost' do
+ badge.link_url = 'https://127.0.0.1'
+
+ subject
+
+ expect(badge.errors).to be_empty
+ end
+
+ it 'does not block urls pointing to the local network' do
+ badge.link_url = 'https://192.168.1.1'
+
+ subject
+
+ expect(badge.errors).to be_empty
+ end
+
+ it 'does block nil urls' do
+ badge.link_url = nil
+
+ subject
+
+ expect(badge.errors).to be_present
+ end
+
+ it 'does block blank urls' do
+ badge.link_url = '\n\r \n'
+
+ subject
+
+ expect(badge.errors).to be_present
+ end
+
+ it 'strips urls' do
+ badge.link_url = "\n\r\n\nhttps://127.0.0.1\r\n\r\n\n\n\n"
+
+ # It's unusual for a validator to modify its arguments. Some extensions,
+ # such as attr_encrypted, freeze the string to signal that modifications
+ # will not be persisted, so freeze this string to ensure the scheme is
+ # compatible with them.
+ badge.link_url.freeze
+
+ subject
+
+ expect(badge.errors).to be_empty
+ expect(badge.link_url).to eq('https://127.0.0.1')
+ end
+ end
+
+ context 'when message is set' do
+ let(:message) { 'is blocked: test message' }
+ let(:validator) { described_class.new(attributes: [:link_url], allow_nil: false, message: message) }
+
+ it 'does block nil url with provided error message' do
+ expect(validator.validate_each(badge, :link_url, nil)).to be_falsey
+ expect(badge.errors.first[1]).to eq message
+ end
+ end
+
+ context 'when allow_nil is set to true' do
+ let(:validator) { described_class.new(attributes: [:link_url], allow_nil: true) }
+
+ it 'does not block nil urls' do
+ badge.link_url = nil
+
+ subject
+
+ expect(badge.errors).to be_empty
+ end
+ end
+
+ context 'when allow_blank is set to true' do
+ let(:validator) { described_class.new(attributes: [:link_url], allow_blank: true) }
+
+ it 'does not block blank urls' do
+ badge.link_url = "\n\r \n"
+
+ subject
+
+ expect(badge.errors).to be_empty
+ end
+ end
+
+ context 'when allow_localhost is set to false' do
+ let(:validator) { described_class.new(attributes: [:link_url], allow_localhost: false) }
+
+ it 'blocks urls pointing to localhost' do
+ badge.link_url = 'https://127.0.0.1'
+
+ subject
+
+ expect(badge.errors).to be_present
+ end
+
+ context 'when allow_setting_local_requests is set to true' do
+ it 'does not block urls pointing to localhost' do
+ expect(described_class)
+ .to receive(:allow_setting_local_requests?)
+ .and_return(true)
+
+ badge.link_url = 'https://127.0.0.1'
+
+ subject
+
+ expect(badge.errors).to be_empty
+ end
+ end
+ end
+
+ context 'when allow_local_network is set to false' do
+ let(:validator) { described_class.new(attributes: [:link_url], allow_local_network: false) }
+
+ it 'blocks urls pointing to the local network' do
+ badge.link_url = 'https://192.168.1.1'
+
+ subject
+
+ expect(badge.errors).to be_present
+ end
+
+ context 'when allow_setting_local_requests is set to true' do
+ it 'does not block urls pointing to local network' do
+ expect(described_class)
+ .to receive(:allow_setting_local_requests?)
+ .and_return(true)
+
+ badge.link_url = 'https://192.168.1.1'
+
+ subject
+
+ expect(badge.errors).to be_empty
+ end
+ end
+ end
+
+ context 'when ports is' do
+ let(:validator) { described_class.new(attributes: [:link_url], ports: ports) }
+
+ context 'empty' do
+ let(:ports) { [] }
+
+ it 'does not block any port' do
+ subject
+
+ expect(badge.errors).to be_empty
+ end
+ end
+
+ context 'set' do
+ let(:ports) { [443] }
+
+ it 'blocks urls with a different port' do
+ subject
+
+ expect(badge.errors).to be_present
+ end
+ end
+ end
+
+ context 'when enforce_user is' do
+ let(:url) { 'http://$user@example.com'}
+ let(:validator) { described_class.new(attributes: [:link_url], enforce_user: enforce_user) }
+
+ context 'true' do
+ let(:enforce_user) { true }
+
+ it 'checks user format' do
+ badge.link_url = url
+
+ subject
+
+ expect(badge.errors).to be_present
+ end
+ end
+
+ context 'false (default)' do
+ let(:enforce_user) { false }
+
+ it 'does not check user format' do
+ badge.link_url = url
+
+ subject
+
+ expect(badge.errors).to be_empty
+ end
+ end
+ end
+
+ context 'when ascii_only is' do
+ let(:url) { 'https://𝕘itⅼαƄ.com/foo/foo.bar'}
+ let(:validator) { described_class.new(attributes: [:link_url], ascii_only: ascii_only) }
+
+ context 'true' do
+ let(:ascii_only) { true }
+
+ it 'prevents unicode characters' do
+ badge.link_url = url
+
+ subject
+
+ expect(badge.errors).to be_present
+ end
+ end
+
+ context 'false (default)' do
+ let(:ascii_only) { false }
+
+ it 'does not prevent unicode characters' do
+ badge.link_url = url
+
+ subject
+
+ expect(badge.errors).to be_empty
+ end
+ end
+ end
+
+ context 'when enforce_sanitization is' do
+ let(:validator) { described_class.new(attributes: [:link_url], enforce_sanitization: enforce_sanitization) }
+ let(:unsafe_url) { "https://replaceme.com/'><script>alert(document.cookie)</script>" }
+ let(:safe_url) { 'https://replaceme.com/path/to/somewhere' }
+
+ let(:unsafe_internal_url) do
+ Gitlab.config.gitlab.protocol + '://' + Gitlab.config.gitlab.host +
+ "/'><script>alert(document.cookie)</script>"
+ end
+
+ context 'true' do
+ let(:enforce_sanitization) { true }
+
+ it 'prevents unsafe urls' do
+ badge.link_url = unsafe_url
+
+ subject
+
+ expect(badge.errors).to be_present
+ end
+
+ it 'prevents unsafe internal urls' do
+ badge.link_url = unsafe_internal_url
+
+ subject
+
+ expect(badge.errors).to be_present
+ end
+
+ it 'allows safe urls' do
+ badge.link_url = safe_url
+
+ subject
+
+ expect(badge.errors).to be_empty
+ end
+ end
+
+ context 'false' do
+ let(:enforce_sanitization) { false }
+
+ it 'allows unsafe urls' do
+ badge.link_url = unsafe_url
+
+ subject
+
+ expect(badge.errors).to be_empty
+ end
+ end
+ end
+end