2019-08-22 06:57:44 -04:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2016-05-18 22:16:36 -04:00
|
|
|
require 'spec_helper'
|
|
|
|
|
2020-06-24 14:09:03 -04:00
|
|
|
RSpec.describe Gitlab::UrlSanitizer do
|
2017-09-06 10:20:25 -04:00
|
|
|
using RSpec::Parameterized::TableSyntax
|
2016-05-18 22:16:36 -04:00
|
|
|
|
|
|
|
describe '.sanitize' do
|
|
|
|
def sanitize_url(url)
|
|
|
|
# We want to try with multi-line content because is how error messages are formatted
|
|
|
|
described_class.sanitize(%Q{
|
|
|
|
remote: Not Found
|
|
|
|
fatal: repository '#{url}' not found
|
|
|
|
})
|
|
|
|
end
|
|
|
|
|
2017-09-06 10:20:25 -04:00
|
|
|
where(:input, :output) do
|
|
|
|
'http://user:pass@test.com/root/repoC.git/' | 'http://*****:*****@test.com/root/repoC.git/'
|
|
|
|
'https://user:pass@test.com/root/repoA.git/' | 'https://*****:*****@test.com/root/repoA.git/'
|
|
|
|
'ssh://user@host.test/path/to/repo.git' | 'ssh://*****@host.test/path/to/repo.git'
|
2016-05-18 22:16:36 -04:00
|
|
|
|
2017-09-06 10:20:25 -04:00
|
|
|
# git protocol does not support authentication but clean any details anyway
|
|
|
|
'git://user:pass@host.test/path/to/repo.git' | 'git://*****:*****@host.test/path/to/repo.git'
|
|
|
|
'git://host.test/path/to/repo.git' | 'git://host.test/path/to/repo.git'
|
2016-05-18 22:16:36 -04:00
|
|
|
|
2017-09-06 10:20:25 -04:00
|
|
|
# SCP-style URLs are left unmodified
|
|
|
|
'user@server:project.git' | 'user@server:project.git'
|
|
|
|
'user:pass@server:project.git' | 'user:pass@server:project.git'
|
2016-05-18 22:16:36 -04:00
|
|
|
|
2017-09-06 10:20:25 -04:00
|
|
|
# return an empty string for invalid URLs
|
|
|
|
'ssh://' | ''
|
2016-05-18 22:16:36 -04:00
|
|
|
end
|
|
|
|
|
2017-09-06 10:20:25 -04:00
|
|
|
with_them do
|
|
|
|
it { expect(sanitize_url(input)).to include("repository '#{output}' not found") }
|
2016-05-18 22:16:36 -04:00
|
|
|
end
|
2017-09-06 10:20:25 -04:00
|
|
|
end
|
2016-05-18 22:16:36 -04:00
|
|
|
|
2017-09-06 10:20:25 -04:00
|
|
|
describe '.valid?' do
|
|
|
|
where(:value, :url) do
|
|
|
|
false | nil
|
|
|
|
false | ''
|
|
|
|
false | '123://invalid:url'
|
2017-09-29 08:42:27 -04:00
|
|
|
false | 'valid@project:url.git'
|
2017-09-29 09:45:00 -04:00
|
|
|
false | 'valid:pass@project:url.git'
|
2018-12-09 02:23:39 -05:00
|
|
|
false | %w(test array)
|
2017-09-06 10:20:25 -04:00
|
|
|
true | 'ssh://example.com'
|
|
|
|
true | 'ssh://:@example.com'
|
|
|
|
true | 'ssh://foo@example.com'
|
|
|
|
true | 'ssh://foo:bar@example.com'
|
|
|
|
true | 'ssh://foo:bar@example.com/group/group/project.git'
|
|
|
|
true | 'git://example.com/group/group/project.git'
|
|
|
|
true | 'git://foo:bar@example.com/group/group/project.git'
|
|
|
|
true | 'http://foo:bar@example.com/group/group/project.git'
|
|
|
|
true | 'https://foo:bar@example.com/group/group/project.git'
|
|
|
|
end
|
2016-05-18 22:16:36 -04:00
|
|
|
|
2017-09-06 10:20:25 -04:00
|
|
|
with_them do
|
|
|
|
it { expect(described_class.valid?(url)).to eq(value) }
|
2016-05-18 22:16:36 -04:00
|
|
|
end
|
2017-09-06 10:20:25 -04:00
|
|
|
end
|
|
|
|
|
2020-05-27 17:08:05 -04:00
|
|
|
describe '.valid_web?' do
|
|
|
|
where(:value, :url) do
|
|
|
|
false | nil
|
|
|
|
false | ''
|
|
|
|
false | '123://invalid:url'
|
|
|
|
false | 'valid@project:url.git'
|
|
|
|
false | 'valid:pass@project:url.git'
|
|
|
|
false | %w(test array)
|
|
|
|
false | 'ssh://example.com'
|
|
|
|
false | 'ssh://:@example.com'
|
|
|
|
false | 'ssh://foo@example.com'
|
|
|
|
false | 'ssh://foo:bar@example.com'
|
|
|
|
false | 'ssh://foo:bar@example.com/group/group/project.git'
|
|
|
|
false | 'git://example.com/group/group/project.git'
|
|
|
|
false | 'git://foo:bar@example.com/group/group/project.git'
|
|
|
|
true | 'http://foo:bar@example.com/group/group/project.git'
|
|
|
|
true | 'https://foo:bar@example.com/group/group/project.git'
|
|
|
|
end
|
|
|
|
|
|
|
|
with_them do
|
|
|
|
it { expect(described_class.valid_web?(url)).to eq(value) }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-09-06 10:20:25 -04:00
|
|
|
describe '#sanitized_url' do
|
|
|
|
context 'credentials in hash' do
|
|
|
|
where(username: ['foo', '', nil], password: ['bar', '', nil])
|
2016-05-18 22:16:36 -04:00
|
|
|
|
2017-09-06 10:20:25 -04:00
|
|
|
with_them do
|
|
|
|
let(:credentials) { { user: username, password: password } }
|
|
|
|
subject { described_class.new('http://example.com', credentials: credentials).sanitized_url }
|
2016-05-18 22:16:36 -04:00
|
|
|
|
2017-09-06 10:20:25 -04:00
|
|
|
it { is_expected.to eq('http://example.com') }
|
|
|
|
end
|
2016-05-18 22:16:36 -04:00
|
|
|
end
|
2016-07-11 03:01:09 -04:00
|
|
|
|
2017-09-06 10:20:25 -04:00
|
|
|
context 'credentials in URL' do
|
|
|
|
where(userinfo: %w[foo:bar@ foo@ :bar@ :@ @] + [nil])
|
2016-07-11 03:01:09 -04:00
|
|
|
|
2017-09-06 10:20:25 -04:00
|
|
|
with_them do
|
|
|
|
subject { described_class.new("http://#{userinfo}example.com").sanitized_url }
|
2016-05-18 22:16:36 -04:00
|
|
|
|
2017-09-06 10:20:25 -04:00
|
|
|
it { is_expected.to eq('http://example.com') }
|
|
|
|
end
|
2017-03-20 05:56:43 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-05-18 22:16:36 -04:00
|
|
|
describe '#credentials' do
|
2017-09-06 10:20:25 -04:00
|
|
|
context 'credentials in hash' do
|
|
|
|
it 'overrides URL-provided credentials' do
|
|
|
|
sanitizer = described_class.new('http://a:b@example.com', credentials: { user: 'c', password: 'd' })
|
|
|
|
|
|
|
|
expect(sanitizer.credentials).to eq(user: 'c', password: 'd')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'credentials in URL' do
|
|
|
|
where(:url, :credentials) do
|
|
|
|
'http://foo:bar@example.com' | { user: 'foo', password: 'bar' }
|
2018-07-10 16:00:21 -04:00
|
|
|
'http://foo:bar:baz@example.com' | { user: 'foo', password: 'bar:baz' }
|
2017-09-06 10:20:25 -04:00
|
|
|
'http://:bar@example.com' | { user: nil, password: 'bar' }
|
|
|
|
'http://foo:@example.com' | { user: 'foo', password: nil }
|
|
|
|
'http://foo@example.com' | { user: 'foo', password: nil }
|
|
|
|
'http://:@example.com' | { user: nil, password: nil }
|
|
|
|
'http://@example.com' | { user: nil, password: nil }
|
|
|
|
'http://example.com' | { user: nil, password: nil }
|
|
|
|
|
|
|
|
# Other invalid URLs
|
|
|
|
nil | { user: nil, password: nil }
|
|
|
|
'' | { user: nil, password: nil }
|
|
|
|
'no' | { user: nil, password: nil }
|
|
|
|
end
|
|
|
|
|
|
|
|
with_them do
|
|
|
|
subject { described_class.new(url).credentials }
|
|
|
|
|
|
|
|
it { is_expected.to eq(credentials) }
|
|
|
|
end
|
2017-03-20 05:56:43 -04:00
|
|
|
end
|
2022-03-24 23:08:30 -04:00
|
|
|
|
|
|
|
context 'with mixed credentials' do
|
|
|
|
where(:url, :credentials, :result) do
|
|
|
|
'http://a@example.com' | { password: 'd' } | { user: 'a', password: 'd' }
|
|
|
|
'http://a:b@example.com' | { password: 'd' } | { user: 'a', password: 'd' }
|
|
|
|
'http://:b@example.com' | { password: 'd' } | { user: nil, password: 'd' }
|
|
|
|
'http://a@example.com' | { user: 'c' } | { user: 'c', password: nil }
|
|
|
|
'http://a:b@example.com' | { user: 'c' } | { user: 'c', password: 'b' }
|
|
|
|
'http://a:b@example.com' | { user: '' } | { user: 'a', password: 'b' }
|
|
|
|
end
|
|
|
|
|
|
|
|
with_them do
|
|
|
|
subject { described_class.new(url, credentials: credentials).credentials }
|
|
|
|
|
|
|
|
it { is_expected.to eq(result) }
|
|
|
|
end
|
|
|
|
end
|
2016-05-18 22:16:36 -04:00
|
|
|
end
|
|
|
|
|
2019-04-11 11:26:16 -04:00
|
|
|
describe '#user' do
|
|
|
|
context 'credentials in hash' do
|
|
|
|
it 'overrides URL-provided user' do
|
|
|
|
sanitizer = described_class.new('http://a:b@example.com', credentials: { user: 'c', password: 'd' })
|
|
|
|
|
|
|
|
expect(sanitizer.user).to eq('c')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'credentials in URL' do
|
|
|
|
where(:url, :user) do
|
|
|
|
'http://foo:bar@example.com' | 'foo'
|
|
|
|
'http://foo:bar:baz@example.com' | 'foo'
|
|
|
|
'http://:bar@example.com' | nil
|
|
|
|
'http://foo:@example.com' | 'foo'
|
|
|
|
'http://foo@example.com' | 'foo'
|
|
|
|
'http://:@example.com' | nil
|
|
|
|
'http://@example.com' | nil
|
|
|
|
'http://example.com' | nil
|
|
|
|
|
|
|
|
# Other invalid URLs
|
|
|
|
nil | nil
|
|
|
|
'' | nil
|
|
|
|
'no' | nil
|
|
|
|
end
|
|
|
|
|
|
|
|
with_them do
|
|
|
|
subject { described_class.new(url).user }
|
|
|
|
|
|
|
|
it { is_expected.to eq(user) }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-05-18 22:16:36 -04:00
|
|
|
describe '#full_url' do
|
2017-09-06 10:20:25 -04:00
|
|
|
context 'credentials in hash' do
|
|
|
|
where(:credentials, :userinfo) do
|
|
|
|
{ user: 'foo', password: 'bar' } | 'foo:bar@'
|
|
|
|
{ user: 'foo', password: '' } | 'foo@'
|
|
|
|
{ user: 'foo', password: nil } | 'foo@'
|
|
|
|
{ user: '', password: 'bar' } | ':bar@'
|
|
|
|
{ user: '', password: '' } | nil
|
|
|
|
{ user: '', password: nil } | nil
|
|
|
|
{ user: nil, password: 'bar' } | ':bar@'
|
|
|
|
{ user: nil, password: '' } | nil
|
|
|
|
{ user: nil, password: nil } | nil
|
|
|
|
end
|
2016-05-18 22:16:36 -04:00
|
|
|
|
2017-09-06 10:20:25 -04:00
|
|
|
with_them do
|
|
|
|
subject { described_class.new('http://example.com', credentials: credentials).full_url }
|
2016-05-18 22:16:36 -04:00
|
|
|
|
2017-09-06 10:20:25 -04:00
|
|
|
it { is_expected.to eq("http://#{userinfo}example.com") }
|
|
|
|
end
|
2016-05-18 22:16:36 -04:00
|
|
|
end
|
2017-03-09 10:39:09 -05:00
|
|
|
|
2017-09-06 10:20:25 -04:00
|
|
|
context 'credentials in URL' do
|
|
|
|
where(:input, :output) do
|
|
|
|
nil | ''
|
|
|
|
'' | :same
|
|
|
|
'git@example.com' | :same
|
|
|
|
'http://example.com' | :same
|
|
|
|
'http://foo@example.com' | :same
|
|
|
|
'http://foo:@example.com' | 'http://foo@example.com'
|
|
|
|
'http://:bar@example.com' | :same
|
|
|
|
'http://foo:bar@example.com' | :same
|
2018-07-18 01:50:08 -04:00
|
|
|
'http://foo:g p@example.com' | 'http://foo:g%20p@example.com'
|
|
|
|
'http://foo:s/h@example.com' | 'http://foo:s%2Fh@example.com'
|
|
|
|
'http://t u:a#b@example.com' | 'http://t%20u:a%23b@example.com'
|
|
|
|
'http://t+u:a#b@example.com' | 'http://t%2Bu:a%23b@example.com'
|
2017-03-20 05:56:43 -04:00
|
|
|
end
|
|
|
|
|
2017-09-06 10:20:25 -04:00
|
|
|
with_them do
|
|
|
|
let(:expected) { output == :same ? input : output }
|
|
|
|
|
|
|
|
it { expect(described_class.new(input).full_url).to eq(expected) }
|
|
|
|
end
|
2017-03-09 10:39:09 -05:00
|
|
|
end
|
|
|
|
end
|
2017-09-08 10:48:10 -04:00
|
|
|
|
|
|
|
context 'when credentials contains special chars' do
|
2019-04-05 04:43:27 -04:00
|
|
|
it 'parses the URL without errors' do
|
2017-09-08 10:48:10 -04:00
|
|
|
url_sanitizer = described_class.new("https://foo:b?r@github.com/me/project.git")
|
|
|
|
|
|
|
|
expect(url_sanitizer.sanitized_url).to eq("https://github.com/me/project.git")
|
2018-07-18 01:50:08 -04:00
|
|
|
expect(url_sanitizer.full_url).to eq("https://foo:b%3Fr@github.com/me/project.git")
|
2017-09-08 10:48:10 -04:00
|
|
|
end
|
|
|
|
end
|
2016-05-18 22:16:36 -04:00
|
|
|
end
|