Skip to content
Snippets Groups Projects
Commit b7dfe2ae authored by GitLab Bot's avatar GitLab Bot
Browse files

Add latest changes from gitlab-org/gitlab@master

parent 25cb337c
No related branches found
No related tags found
No related merge requests found
Showing
with 402 additions and 24 deletions
Loading
Loading
@@ -23,6 +23,7 @@ describe Gitlab::HookData::IssueBuilder do
last_edited_by_id
milestone_id
moved_to_id
duplicated_to_id
project_id
relative_position
state
Loading
Loading
Loading
Loading
@@ -14,6 +14,7 @@ issues:
- todos
- user_agent_detail
- moved_to
- duplicated_to
- events
- merge_requests_closing_issues
- metrics
Loading
Loading
Loading
Loading
@@ -19,6 +19,7 @@ Issue:
- closed_by_id
- due_date
- moved_to_id
- duplicated_to_id
- lock_version
- milestone_id
- weight
Loading
Loading
Loading
Loading
@@ -30,8 +30,12 @@ describe Gitlab::UrlBlocker do
context 'when URI is internal' do
let(:import_url) { 'http://localhost' }
 
before do
stub_dns(import_url, ip_address: '127.0.0.1')
end
it_behaves_like 'validates URI and hostname' do
let(:expected_uri) { 'http://[::1]' }
let(:expected_uri) { 'http://127.0.0.1' }
let(:expected_hostname) { 'localhost' }
end
end
Loading
Loading
@@ -347,6 +351,7 @@ describe Gitlab::UrlBlocker do
end
 
before do
allow(ApplicationSetting).to receive(:current).and_return(ApplicationSetting.new)
stub_application_setting(outbound_local_requests_whitelist: whitelist)
end
 
Loading
Loading
@@ -384,9 +389,15 @@ describe Gitlab::UrlBlocker do
it_behaves_like 'allows local requests', { allow_localhost: false, allow_local_network: false }
 
it 'whitelists IP when dns_rebind_protection is disabled' do
stub_domain_resolv('example.com', '192.168.1.1') do
expect(described_class).not_to be_blocked_url("http://example.com",
url_blocker_attributes.merge(dns_rebind_protection: false))
url = "http://example.com"
attrs = url_blocker_attributes.merge(dns_rebind_protection: false)
stub_domain_resolv('example.com', '192.168.1.2') do
expect(described_class).not_to be_blocked_url(url, attrs)
end
stub_domain_resolv('example.com', '192.168.1.3') do
expect(described_class).to be_blocked_url(url, attrs)
end
end
end
Loading
Loading
@@ -437,6 +448,51 @@ describe Gitlab::UrlBlocker do
url_blocker_attributes)
end
end
shared_examples 'dns rebinding checks' do
shared_examples 'whitelists the domain' do
let(:whitelist) { [domain] }
let(:url) { "http://#{domain}" }
before do
stub_env('RSPEC_ALLOW_INVALID_URLS', 'false')
end
it do
expect(described_class).not_to be_blocked_url(url, dns_rebind_protection: dns_rebind_value)
end
end
context 'when dns_rebinding_setting is' do
context 'enabled' do
let(:dns_rebind_value) { true }
it_behaves_like 'whitelists the domain'
end
context 'disabled' do
let(:dns_rebind_value) { false }
it_behaves_like 'whitelists the domain'
end
end
end
context 'when the domain cannot be resolved' do
let(:domain) { 'foobar.x' }
it_behaves_like 'dns rebinding checks'
end
context 'when the domain can be resolved' do
let(:domain) { 'example.com' }
before do
stub_dns(url, ip_address: '93.184.216.34')
end
it_behaves_like 'dns rebinding checks'
end
end
 
context 'with ip ranges in whitelist' do
Loading
Loading
# frozen_string_literal: true
require 'spec_helper'
describe Gitlab::UrlBlockers::UrlWhitelist do
include StubRequests
let(:whitelist) { [] }
before do
allow(ApplicationSetting).to receive(:current).and_return(ApplicationSetting.new)
stub_application_setting(outbound_local_requests_whitelist: whitelist)
end
describe '#domain_whitelisted?' do
let(:whitelist) do
[
'www.example.com',
'example.com'
]
end
it 'returns true if domains present in whitelist' do
aggregate_failures do
whitelist.each do |domain|
expect(described_class).to be_domain_whitelisted(domain)
end
['subdomain.example.com', 'example.org'].each do |domain|
expect(described_class).not_to be_domain_whitelisted(domain)
end
end
end
it 'returns false when domain is blank' do
expect(described_class).not_to be_domain_whitelisted(nil)
end
end
describe '#ip_whitelisted?' do
let(:whitelist) do
[
'0.0.0.0',
'127.0.0.1',
'192.168.1.1',
'0:0:0:0:0:ffff:192.168.1.2',
'::ffff:c0a8:102',
'fc00:bf8b:e62c:abcd:abcd:aaaa:aaaa:aaaa',
'0:0:0:0:0:ffff:169.254.169.254',
'::ffff:a9fe:a9fe',
'::ffff:a9fe:a864',
'fe80::c800:eff:fe74:8'
]
end
it 'returns true if ips present in whitelist' do
aggregate_failures do
whitelist.each do |ip_address|
expect(described_class).to be_ip_whitelisted(ip_address)
end
['172.16.2.2', '127.0.0.2', 'fe80::c800:eff:fe74:9'].each do |ip_address|
expect(described_class).not_to be_ip_whitelisted(ip_address)
end
end
end
it 'returns false when ip is blank' do
expect(described_class).not_to be_ip_whitelisted(nil)
end
end
end
Loading
Loading
@@ -21,23 +21,23 @@ describe Gitlab do
context 'when a REVISION file exists' do
before do
expect(File).to receive(:exist?)
.with(described_class.root.join('REVISION'))
.and_return(true)
.with(described_class.root.join('REVISION'))
.and_return(true)
end
 
it 'returns the actual Git revision' do
expect(File).to receive(:read)
.with(described_class.root.join('REVISION'))
.and_return("abc123\n")
.with(described_class.root.join('REVISION'))
.and_return("abc123\n")
 
expect(described_class.revision).to eq('abc123')
end
 
it 'memoizes the revision' do
expect(File).to receive(:read)
.once
.with(described_class.root.join('REVISION'))
.and_return("abc123\n")
.once
.with(described_class.root.join('REVISION'))
.and_return("abc123\n")
 
2.times { described_class.revision }
end
Loading
Loading
@@ -47,8 +47,8 @@ describe Gitlab do
context 'when the Git command succeeds' do
before do
expect(Gitlab::Popen).to receive(:popen_with_detail)
.with(cmd)
.and_return(Gitlab::Popen::Result.new(cmd, 'abc123', '', double(success?: true)))
.with(cmd)
.and_return(Gitlab::Popen::Result.new(cmd, 'abc123', '', double(success?: true)))
end
 
it 'returns the actual Git revision' do
Loading
Loading
@@ -59,8 +59,8 @@ describe Gitlab do
context 'when the Git command fails' do
before do
expect(Gitlab::Popen).to receive(:popen_with_detail)
.with(cmd)
.and_return(Gitlab::Popen::Result.new(cmd, '', 'fatal: Not a git repository', double('Process::Status', success?: false)))
.with(cmd)
.and_return(Gitlab::Popen::Result.new(cmd, '', 'fatal: Not a git repository', double('Process::Status', success?: false)))
end
 
it 'returns "Unknown"' do
Loading
Loading
@@ -123,6 +123,27 @@ describe Gitlab do
end
end
 
describe '.dev_env_or_com?' do
it 'is true when on .com' do
allow(described_class).to receive(:com?).and_return(true)
expect(described_class.dev_env_or_com?).to eq true
end
it 'is true when dev env' do
allow(described_class).to receive(:com?).and_return(false)
allow(Rails).to receive(:env).and_return(ActiveSupport::StringInquirer.new('development'))
expect(described_class.dev_env_or_com?).to eq true
end
it 'is false when not dev or com' do
allow(described_class).to receive(:com?).and_return(false)
expect(described_class.dev_env_or_com?).to eq false
end
end
describe '.ee?' do
before do
described_class.instance_variable_set(:@is_ee, nil)
Loading
Loading
@@ -138,12 +159,12 @@ describe Gitlab do
 
allow(described_class)
.to receive(:root)
.and_return(root)
.and_return(root)
 
allow(root)
.to receive(:join)
.with('ee/app/models/license.rb')
.and_return(license_path)
.with('ee/app/models/license.rb')
.and_return(license_path)
 
expect(described_class.ee?).to eq(true)
end
Loading
Loading
@@ -154,12 +175,12 @@ describe Gitlab do
 
allow(described_class)
.to receive(:root)
.and_return(Pathname.new('dummy'))
.and_return(Pathname.new('dummy'))
 
allow(root)
.to receive(:join)
.with('ee/app/models/license.rb')
.and_return(license_path)
.with('ee/app/models/license.rb')
.and_return(license_path)
 
expect(described_class.ee?).to eq(false)
end
Loading
Loading
Loading
Loading
@@ -7,6 +7,10 @@ describe Issue do
 
describe "Associations" do
it { is_expected.to belong_to(:milestone) }
it { is_expected.to belong_to(:project) }
it { is_expected.to belong_to(:moved_to).class_name('Issue') }
it { is_expected.to belong_to(:duplicated_to).class_name('Issue') }
it { is_expected.to belong_to(:closed_by).class_name('User') }
it { is_expected.to have_many(:assignees) }
end
 
Loading
Loading
@@ -310,6 +314,22 @@ describe Issue do
end
end
 
describe '#duplicated?' do
let(:issue) { create(:issue) }
subject { issue.duplicated? }
context 'issue not duplicated' do
it { is_expected.to eq false }
end
context 'issue already duplicated' do
let(:duplicated_to_issue) { create(:issue) }
let(:issue) { create(:issue, duplicated_to: duplicated_to_issue) }
it { is_expected.to eq true }
end
end
describe '#suggested_branch_name' do
let(:repository) { double }
 
Loading
Loading
Loading
Loading
@@ -195,7 +195,6 @@ describe MergeRequest do
with_them do
it "validates source_branch" do
subject = build(:merge_request, source_branch: branch_name, target_branch: 'master')
subject.valid?
 
expect(subject.errors.added?(:source_branch)).to eq(!valid)
Loading
Loading
@@ -203,7 +202,6 @@ describe MergeRequest do
 
it "validates target_branch" do
subject = build(:merge_request, source_branch: 'master', target_branch: branch_name)
subject.valid?
 
expect(subject.errors.added?(:target_branch)).to eq(!valid)
Loading
Loading
require "spec_helper"
require 'spec_helper'
 
describe 'Git HTTP requests' do
include ProjectForksHelper
Loading
Loading
Loading
Loading
@@ -11,6 +11,23 @@ describe RuboCop::Cop::Graphql::AuthorizeTypes do
 
subject(:cop) { described_class.new }
 
context 'when NOT in a type folder' do
before do
allow(cop).to receive(:in_type?).and_return(false)
end
it 'does not add an offense even though there is no authorize call' do
expect_no_offenses(<<~TYPE.strip)
module Types
class AType < BaseObject
field :a_thing
field :another_thing
end
end
TYPE
end
end
context 'when in a type folder' do
before do
allow(cop).to receive(:in_type?).and_return(true)
Loading
Loading
# frozen_string_literal: true
require 'fast_spec_helper'
require 'rubocop'
require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/graphql/descriptions'
describe RuboCop::Cop::Graphql::Descriptions do
include RuboCop::RSpec::ExpectOffense
include CopHelper
subject(:cop) { described_class.new }
context 'fields' do
it 'adds an offense when there is no field description' do
inspect_source(<<~TYPE)
module Types
class FakeType < BaseObject
field :a_thing,
GraphQL::STRING_TYPE,
null: false
end
end
TYPE
expect(cop.offenses.size).to eq 1
end
it 'does not add an offense for fields with a description' do
expect_no_offenses(<<~TYPE.strip)
module Types
class FakeType < BaseObject
graphql_name 'FakeTypeName'
argument :a_thing,
GraphQL::STRING_TYPE,
null: false,
description: 'A descriptive description'
end
end
TYPE
end
end
context 'arguments' do
it 'adds an offense when there is no argument description' do
inspect_source(<<~TYPE)
module Types
class FakeType < BaseObject
argument :a_thing,
GraphQL::STRING_TYPE,
null: false
end
end
TYPE
expect(cop.offenses.size).to eq 1
end
it 'does not add an offense for arguments with a description' do
expect_no_offenses(<<~TYPE.strip)
module Types
class FakeType < BaseObject
graphql_name 'FakeTypeName'
argument :a_thing,
GraphQL::STRING_TYPE,
null: false,
description: 'Behold! A description'
end
end
TYPE
end
end
end
require 'spec_helper'
describe ClusterBasicEntity do
describe '#as_json' do
subject { described_class.new(cluster, request: request).as_json }
let(:maintainer) { create(:user) }
let(:developer) { create(:user) }
let(:current_user) { maintainer }
let(:request) { double(:request, current_user: current_user) }
let(:project) { create(:project) }
let(:cluster) { create(:cluster, name: 'the-cluster', projects: [project]) }
before do
project.add_maintainer(maintainer)
project.add_developer(developer)
end
it 'matches cluster_basic entity schema' do
expect(subject.as_json).to match_schema('cluster_basic')
end
it 'exposes the cluster details' do
expect(subject[:name]).to eq('the-cluster')
expect(subject[:path]).to eq("/#{project.full_path}/clusters/#{cluster.id}")
end
context 'when the user does not have permission to view the cluster' do
let(:current_user) { developer }
it 'does not include the path' do
expect(subject[:path]).to be_nil
end
end
end
end
Loading
Loading
@@ -50,4 +50,44 @@ describe IssueEntity do
end
end
end
context 'when issue got duplicated' do
let(:private_project) { create(:project, :private) }
let(:member) { create(:user) }
let(:issue) { create(:issue, project: project) }
let(:new_issue) { create(:issue, project: private_project) }
before do
Issues::DuplicateService
.new(project, member)
.execute(issue, new_issue)
end
context 'when user cannot read new issue' do
let(:non_member) { create(:user) }
it 'does not return duplicated_to_id' do
request = double('request', current_user: non_member)
response = described_class.new(issue, request: request).as_json
expect(response[:duplicated_to_id]).to be_nil
end
end
context 'when user can read target project' do
before do
project.add_developer(member)
private_project.add_developer(member)
end
it 'returns duplicated duplicated_to_id' do
request = double('request', current_user: member)
response = described_class.new(issue, request: request).as_json
expect(response[:duplicated_to_id]).to eq(issue.duplicated_to_id)
end
end
end
end
Loading
Loading
@@ -77,6 +77,12 @@ describe Issues::DuplicateService do
 
subject.execute(duplicate_issue, canonical_issue)
end
it 'updates duplicate issue with canonical issue id' do
subject.execute(duplicate_issue, canonical_issue)
expect(duplicate_issue.reload.duplicated_to).to eq(canonical_issue)
end
end
end
end
Loading
Loading
@@ -32,6 +32,8 @@ end
require 'rainbow/ext/string'
Rainbow.enabled = false
 
require_relative('../ee/spec/spec_helper') if Gitlab.ee?
# Requires supporting ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories.
# Requires helpers, and shared contexts/examples first since they're used in other support files
Loading
Loading
Loading
Loading
@@ -13,3 +13,5 @@ module DbCleaner
DatabaseCleaner[:active_record, { connection: ActiveRecord::Base }]
end
end
DbCleaner.prepend_if_ee('EE::DbCleaner')
Loading
Loading
@@ -172,6 +172,31 @@ module GraphqlHelpers
post_graphql(mutation.query, current_user: current_user, variables: mutation.variables)
end
 
# this implements GraphQL multipart request v2
# https://github.com/jaydenseric/graphql-multipart-request-spec/tree/v2.0.0-alpha.2
# this is simplified and do not support file deduplication
def mutation_to_apollo_uploads_param(mutation, files: [])
operations = { 'query' => mutation.query, 'variables' => mutation.variables }
map = {}
extracted_files = {}
files.each_with_index do |file_path, idx|
apollo_idx = (idx + 1).to_s
parent_dig_path = file_path[0..-2]
file_key = file_path[-1]
parent = operations['variables']
parent = parent.dig(*parent_dig_path) unless parent_dig_path.empty?
extracted_files[apollo_idx] = parent[file_key]
parent[file_key] = nil
map[apollo_idx] = ["variables.#{file_path.join('.')}"]
end
{ operations: operations.to_json, map: map.to_json }.merge(extracted_files)
end
# Raises an error if no data is found
def graphql_data
json_response['data'] || (raise NoData, graphql_errors)
Loading
Loading
Loading
Loading
@@ -70,3 +70,5 @@ module LdapHelpers
.to receive(:ldap_search).and_raise(Gitlab::Auth::LDAP::LDAPConnectionError)
end
end
LdapHelpers.include_if_ee('EE::LdapHelpers')
Loading
Loading
@@ -6,3 +6,5 @@ module LicenseHelpers
# do nothing
end
end
LicenseHelpers.prepend_if_ee('EE::LicenseHelpers')
Loading
Loading
@@ -211,3 +211,5 @@ module LoginHelpers
allow(Gitlab::Auth::Saml::Config).to receive_messages({ options: { name: 'saml', groups_attribute: 'groups', external_groups: groups, args: {} } })
end
end
LoginHelpers.prepend_if_ee('EE::LoginHelpers')
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment