Commit 4a070084 authored by GitLab Bot's avatar GitLab Bot

Merge remote-tracking branch 'upstream/master' into ce-to-ee-2018-04-02

# Conflicts:
#	app/views/projects/deploy_keys/_index.html.haml
#	doc/ci/pipelines.md
#	doc/ci/quick_start/README.md
#	doc/ci/yaml/README.md
#	spec/javascripts/boards/mock_data.js
#	spec/javascripts/vue_mr_widget/mock_data.js

[ci skip]
parents 2a8e7703 f2e6a738
......@@ -321,7 +321,7 @@ end
group :development do
gem 'foreman', '~> 0.84.0'
gem 'brakeman', '~> 3.6.0', require: false
gem 'brakeman', '~> 4.2', require: false
gem 'letter_opener_web', '~> 1.3.0'
gem 'rblineprof', '~> 0.3.6', platform: :mri, require: false
......
......@@ -103,7 +103,7 @@ GEM
autoprefixer-rails (>= 5.2.1)
sass (>= 3.3.4)
bootstrap_form (2.7.0)
brakeman (3.6.1)
brakeman (4.2.1)
browser (2.2.0)
builder (3.2.3)
bullet (5.5.1)
......@@ -1042,7 +1042,7 @@ DEPENDENCIES
binding_of_caller (~> 0.7.2)
bootstrap-sass (~> 3.3.0)
bootstrap_form (~> 2.7.0)
brakeman (~> 3.6.0)
brakeman (~> 4.2)
browser (~> 2.2)
bullet (~> 5.5.0)
bundler-audit (~> 0.5.0)
......
<script>
import Flash from '../../../flash';
import editForm from './edit_form.vue';
import Icon from '../../../vue_shared/components/icon.vue';
import { __ } from '../../../locale';
import Flash from '../../../flash';
import editForm from './edit_form.vue';
import Icon from '../../../vue_shared/components/icon.vue';
import { __ } from '../../../locale';
import eventHub from '../../event_hub';
export default {
export default {
components: {
editForm,
Icon,
......@@ -33,27 +34,40 @@
return this.isConfidential ? 'eye-slash' : 'eye';
},
},
created() {
eventHub.$on('closeConfidentialityForm', this.toggleForm);
},
beforeDestroy() {
eventHub.$off('closeConfidentialityForm', this.toggleForm);
},
methods: {
toggleForm() {
this.edit = !this.edit;
},
updateConfidentialAttribute(confidential) {
this.service.update('issue', { confidential })
this.service
.update('issue', { confidential })
.then(() => location.reload())
.catch(() => {
Flash(__('Something went wrong trying to change the confidentiality of this issue'));
Flash(
__(
'Something went wrong trying to change the confidentiality of this issue',
),
);
});
},
},
};
};
</script>
<template>
<div class="block issuable-sidebar-item confidentiality">
<div class="sidebar-collapsed-icon">
<div
class="sidebar-collapsed-icon"
@click="toggleForm"
>
<icon
:name="confidentialityIcon"
:size="16"
aria-hidden="true"
/>
</div>
......@@ -71,7 +85,6 @@
<div class="value sidebar-item-value hide-collapsed">
<editForm
v-if="edit"
:toggle-form="toggleForm"
:is-confidential="isConfidential"
:update-confidential-attribute="updateConfidentialAttribute"
/>
......
<script>
import editFormButtons from './edit_form_buttons.vue';
import { s__ } from '../../../locale';
import editFormButtons from './edit_form_buttons.vue';
import { s__ } from '../../../locale';
export default {
export default {
components: {
editFormButtons,
},
......@@ -11,10 +11,6 @@
required: true,
type: Boolean,
},
toggleForm: {
required: true,
type: Function,
},
updateConfidentialAttribute: {
required: true,
type: Function,
......@@ -22,13 +18,17 @@
},
computed: {
confidentialityOnWarning() {
return s__('confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue.');
return s__(
'confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue.',
);
},
confidentialityOffWarning() {
return s__('confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue.');
return s__(
'confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue.',
);
},
},
};
};
</script>
<template>
......@@ -45,7 +45,6 @@
</p>
<edit-form-buttons
:is-confidential="isConfidential"
:toggle-form="toggleForm"
:update-confidential-attribute="updateConfidentialAttribute"
/>
</div>
......
<script>
import $ from 'jquery';
import eventHub from '../../event_hub';
export default {
props: {
isConfidential: {
required: true,
type: Boolean,
},
toggleForm: {
required: true,
type: Function,
},
updateConfidentialAttribute: {
required: true,
type: Function,
......@@ -22,6 +21,16 @@ export default {
return !this.isConfidential;
},
},
methods: {
closeForm() {
eventHub.$emit('closeConfidentialityForm');
$(this.$el).trigger('hidden.gl.dropdown');
},
submitForm() {
this.closeForm();
this.updateConfidentialAttribute(this.updateConfidentialBool);
},
},
};
</script>
......@@ -30,14 +39,14 @@ export default {
<button
type="button"
class="btn btn-default append-right-10"
@click="toggleForm"
@click="closeForm"
>
{{ __('Cancel') }}
</button>
<button
type="button"
class="btn btn-close"
@click.prevent="updateConfidentialAttribute(updateConfidentialBool)"
@click.prevent="submitForm"
>
{{ toggleButtonText }}
</button>
......
<script>
import editFormButtons from './edit_form_buttons.vue';
import issuableMixin from '../../../vue_shared/mixins/issuable';
import { __, sprintf } from '../../../locale';
import editFormButtons from './edit_form_buttons.vue';
import issuableMixin from '../../../vue_shared/mixins/issuable';
import { __, sprintf } from '../../../locale';
export default {
export default {
components: {
editFormButtons,
},
mixins: [
issuableMixin,
],
mixins: [issuableMixin],
props: {
isLocked: {
required: true,
type: Boolean,
},
toggleForm: {
required: true,
type: Function,
},
updateLockedAttribute: {
required: true,
type: Function,
......@@ -28,13 +21,23 @@
},
computed: {
lockWarning() {
return sprintf(__('Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment.'), { issuableDisplayName: this.issuableDisplayName });
return sprintf(
__(
'Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment.',
),
{ issuableDisplayName: this.issuableDisplayName },
);
},
unlockWarning() {
return sprintf(__('Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment.'), { issuableDisplayName: this.issuableDisplayName });
return sprintf(
__(
'Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment.',
),
{ issuableDisplayName: this.issuableDisplayName },
);
},
},
};
};
</script>
<template>
......@@ -54,7 +57,6 @@
<edit-form-buttons
:is-locked="isLocked"
:toggle-form="toggleForm"
:update-locked-attribute="updateLockedAttribute"
/>
</div>
......
<script>
import $ from 'jquery';
import eventHub from '../../event_hub';
export default {
props: {
isLocked: {
......@@ -6,11 +9,6 @@ export default {
type: Boolean,
},
toggleForm: {
required: true,
type: Function,
},
updateLockedAttribute: {
required: true,
type: Function,
......@@ -26,6 +24,17 @@ export default {
return !this.isLocked;
},
},
methods: {
closeForm() {
eventHub.$emit('closeLockForm');
$(this.$el).trigger('hidden.gl.dropdown');
},
submitForm() {
this.closeForm();
this.updateLockedAttribute(this.toggleLock);
},
},
};
</script>
......@@ -34,7 +43,7 @@ export default {
<button
type="button"
class="btn btn-default append-right-10"
@click="toggleForm"
@click="closeForm"
>
{{ __('Cancel') }}
</button>
......@@ -42,7 +51,7 @@ export default {
<button
type="button"
class="btn btn-close"
@click.prevent="updateLockedAttribute(toggleLock)"
@click.prevent="submitForm"
>
{{ buttonText }}
</button>
......
<script>
import Flash from '~/flash';
import editForm from './edit_form.vue';
import issuableMixin from '../../../vue_shared/mixins/issuable';
import Icon from '../../../vue_shared/components/icon.vue';
import Flash from '~/flash';
import editForm from './edit_form.vue';
import issuableMixin from '../../../vue_shared/mixins/issuable';
import Icon from '../../../vue_shared/components/icon.vue';
import eventHub from '../../event_hub';
export default {
export default {
components: {
editForm,
Icon,
},
mixins: [
issuableMixin,
],
mixins: [issuableMixin],
props: {
isLocked: {
......@@ -28,7 +27,11 @@
required: true,
type: Object,
validator(mediatorObject) {
return mediatorObject.service && mediatorObject.service.update && mediatorObject.store;
return (
mediatorObject.service &&
mediatorObject.service.update &&
mediatorObject.store
);
},
},
},
......@@ -43,28 +46,48 @@
},
},
created() {
eventHub.$on('closeLockForm', this.toggleForm);
},
beforeDestroy() {
eventHub.$off('closeLockForm', this.toggleForm);
},
methods: {
toggleForm() {
this.mediator.store.isLockDialogOpen = !this.mediator.store.isLockDialogOpen;
this.mediator.store.isLockDialogOpen = !this.mediator.store
.isLockDialogOpen;
},
updateLockedAttribute(locked) {
this.mediator.service.update(this.issuableType, {
this.mediator.service
.update(this.issuableType, {
discussion_locked: locked,
})
.then(() => location.reload())
.catch(() => Flash(this.__(`Something went wrong trying to change the locked state of this ${this.issuableDisplayName}`)));
.catch(() =>
Flash(
this.__(
`Something went wrong trying to change the locked state of this ${
this.issuableDisplayName
}`,
),
),
);
},
},
};
};
</script>
<template>
<div class="block issuable-sidebar-item lock">
<div class="sidebar-collapsed-icon">
<div
class="sidebar-collapsed-icon"
@click="toggleForm"
>
<icon
:name="lockIcon"
:size="16"
aria-hidden="true"
class="sidebar-item-icon is-active"
/>
......@@ -85,7 +108,6 @@
<div class="value sidebar-item-value hide-collapsed">
<edit-form
v-if="isLockDialogOpen"
:toggle-form="toggleForm"
:is-locked="isLocked"
:update-locked-attribute="updateLockedAttribute"
:issuable-type="issuableType"
......
......@@ -46,6 +46,8 @@ class Projects::ServicesController < Projects::ApplicationController
else
{ error: true, message: 'Validations failed.', service_response: @service.errors.full_messages.join(',') }
end
rescue Gitlab::HTTP::BlockedUrlError => e
{ error: true, message: 'Test failed.', service_response: e.message }
end
def success_message
......
......@@ -28,7 +28,11 @@ module Projects
def add_repository_to_project
if project.external_import? && !unknown_url?
raise Error, 'Blocked import URL.' if Gitlab::UrlBlocker.blocked_url?(project.import_url, valid_ports: Project::VALID_IMPORT_PORTS)
begin
Gitlab::UrlBlocker.validate!(project.import_url, valid_ports: Project::VALID_IMPORT_PORTS)
rescue Gitlab::UrlBlocker::BlockedUrlError => e
raise Error, "Blocked import URL: #{e.message}"
end
end
# We should skip the repository for a GitHub import or GitLab project import,
......
......@@ -4,8 +4,8 @@
# protect against Server-side Request Forgery (SSRF).
class ImportableUrlValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
if Gitlab::UrlBlocker.blocked_url?(value, valid_ports: Project::VALID_IMPORT_PORTS)
record.errors.add(attribute, "imports are not allowed from that URL")
end
Gitlab::UrlBlocker.validate!(value, valid_ports: Project::VALID_IMPORT_PORTS)
rescue Gitlab::UrlBlocker::BlockedUrlError => e
record.errors.add(attribute, "is blocked: #{e.message}")
end
end
......@@ -3,7 +3,11 @@
.settings-header
%h4
Deploy Keys
<<<<<<< HEAD
%button.btn.js-settings-toggle{ type: 'button' }
=======
%button.btn.js-settings-toggle.qa-expand-deploy-keys{ type: 'button' }
>>>>>>> upstream/master
= expanded ? 'Collapse' : 'Expand'
%p
Deploy keys allow read-only or read-write (if enabled) access to your repository. Deploy keys can be used for CI, staging or production servers. You can create a deploy key or add an existing one.
......
---
title: Update brakeman 3.6.1 to 4.2.1
merge_request: 18122
author: Takuya Noguchi
type: other
......@@ -3,7 +3,11 @@
> Introduced in GitLab 8.8.
NOTE: **Note:**
<<<<<<< HEAD
If you have a [mirrored repository where GitLab pulls from](../workflow/repository_mirroring.md#pulling-from-a-remote-repository),
=======
If you have a [mirrored repository where GitLab pulls from](https://docs.gitlab.com/ee/workflow/repository_mirroring.html#pulling-from-a-remote-repository),
>>>>>>> upstream/master
you may need to enable pipeline triggering in your project's
**Settings > Repository > Pull from a remote repository > Trigger pipelines for mirror updates**.
......
......@@ -127,7 +127,11 @@ Now if you go to the **Pipelines** page you will see that the pipeline is
pending.
NOTE: **Note:**
<<<<<<< HEAD
If you have a [mirrored repository where GitLab pulls from](../../workflow/repository_mirroring.md#pulling-from-a-remote-repository),
=======
If you have a [mirrored repository where GitLab pulls from](https://docs.gitlab.com/ee/workflow/repository_mirroring.html#pulling-from-a-remote-repository),
>>>>>>> upstream/master
you may need to enable pipeline triggering in your project's
**Settings > Repository > Pull from a remote repository > Trigger pipelines for mirror updates**.
......
......@@ -11,7 +11,11 @@ If you want a quick introduction to GitLab CI, follow our
[quick start guide](../quick_start/README.md).
NOTE: **Note:**
<<<<<<< HEAD
If you have a [mirrored repository where GitLab pulls from](../../workflow/repository_mirroring.md#pulling-from-a-remote-repository),
=======
If you have a [mirrored repository where GitLab pulls from](https://docs.gitlab.com/ee/workflow/repository_mirroring.html#pulling-from-a-remote-repository),
>>>>>>> upstream/master
you may need to enable pipeline triggering in your project's
**Settings > Repository > Pull from a remote repository > Trigger pipelines for mirror updates**.
......
......@@ -4,6 +4,8 @@
# calling internal IP or services.
module Gitlab
class HTTP
BlockedUrlError = Class.new(StandardError)
include HTTParty # rubocop:disable Gitlab/HTTParty
connection_adapter ProxyHTTPConnectionAdapter
......
......@@ -10,8 +10,12 @@
module Gitlab
class ProxyHTTPConnectionAdapter < HTTParty::ConnectionAdapter
def connection
if !allow_local_requests? && blocked_url?
raise URI::InvalidURIError
unless allow_local_requests?
begin
Gitlab::UrlBlocker.validate!(uri, allow_local_network: false)
rescue Gitlab::UrlBlocker::BlockedUrlError => e
raise Gitlab::HTTP::BlockedUrlError, "URL '#{uri}' is blocked: #{e.message}"
end
end
super
......@@ -19,10 +23,6 @@ module Gitlab
private
def blocked_url?
Gitlab::UrlBlocker.blocked_url?(uri, allow_private_networks: false)
end
def allow_local_requests?
options.fetch(:allow_local_requests, allow_settings_local_requests?)
end
......
......@@ -2,48 +2,84 @@ require 'resolv'
module Gitlab
class UrlBlocker
class << self
def blocked_url?(url, allow_private_networks: true, valid_ports: [])
return false if url.nil?
BlockedUrlError = Class.new(StandardError)
blocked_ips = ["127.0.0.1", "::1", "0.0.0.0"]
blocked_ips.concat(Socket.ip_address_list.map(&:ip_address))
class << self
def validate!(url, allow_localhost: false, allow_local_network: true, valid_ports: [])
return true if url.nil?
begin
uri = Addressable::URI.parse(url)
# Allow imports from the GitLab instance itself but only from the configured ports
return false if internal?(uri)
rescue Addressable::URI::InvalidURIError
raise BlockedUrlError, "URI is invalid"
end
return true if blocked_port?(uri.port, valid_ports)
return true if blocked_user_or_hostname?(uri.user)
return true if blocked_user_or_hostname?(uri.hostname)
# Allow imports from the GitLab instance itself but only from the configured ports
return true if internal?(uri)
addrs_info = Addrinfo.getaddrinfo(uri.hostname, 80, nil, :STREAM)
server_ips = addrs_info.map(&:ip_address)
port = uri.port || uri.default_port
validate_port!(port, valid_ports) if valid_ports.any?
validate_user!(uri.user)
validate_hostname!(uri.hostname)
return true if (blocked_ips & server_ips).any?
return true if !allow_private_networks && private_network?(addrs_info)
rescue Addressable::URI::InvalidURIError
return true
begin
addrs_info = Addrinfo.getaddrinfo(uri.hostname, port, nil, :STREAM)
rescue SocketError
return false
return true
end
validate_localhost!(addrs_info) unless allow_localhost
validate_local_network!(addrs_info) unless allow_local_network
true
end
def blocked_url?(*args)
validate!(*args)
false
rescue BlockedUrlError
true
end
private
def blocked_port?(port, valid_ports)
return false if port.blank? || valid_ports.blank?
def validate_port!(port, valid_ports)
return if port.blank?
# Only ports under 1024 are restricted
return if port >= 1024
return if valid_ports.include?(port)
raise BlockedUrlError, "Only allowed ports are #{valid_ports.join(', ')}, and any over 1024"
end
def validate_user!(value)
return if value.blank?
return if value =~ /\A\p{Alnum}/
port < 1024 && !valid_ports.include?(port)
raise BlockedUrlError, "Username needs to start with an alphanumeric character"
end
def blocked_user_or_hostname?(value)
return false if value.blank?
def validate_hostname!(value)
return if value.blank?
return if value =~ /\A\p{Alnum}/
value !~ /\A\p{Alnum}/
raise BlockedUrlError, "Hostname needs to start with an alphanumeric character"
end
def validate_localhost!(addrs_info)
local_ips = ["127.0.0.1", "::1", "0.0.0.0"]
local_ips.concat(Socket.ip_address_list.map(&:ip_address))
return if (local_ips & addrs_info.map(&:ip_address)).empty?
raise BlockedUrlError, "Requests to localhost are not allowed"
end
def validate_local_network!(addrs_info)
return unless addrs_info.any? { |addr| addr.ipv4_private? || addr.ipv6_sitelocal? }
raise BlockedUrlError, "Requests to the local network are not allowed"
end
def internal?(uri)
......@@ -60,10 +96,6 @@ module Gitlab
(uri.port.blank? || uri.port == config.gitlab_shell.ssh_port)
end
def private_network?(addrs_info)
addrs_info.any? { |addr| addr.ipv4_private? || addr.ipv6_sitelocal? }
end
def config
Gitlab.config
end
......
......@@ -161,6 +161,50 @@ feature 'Issue Sidebar' do
end
end
end
context 'interacting with collapsed sidebar', :js do
collapsed_sidebar_selector = 'aside.right-sidebar.right-sidebar-collapsed'
expanded_sidebar_selector = 'aside.right-sidebar.right-sidebar-expanded'
confidentiality_sidebar_block = '.block.confidentiality'
lock_sidebar_block = '.block.lock'
collapsed_sidebar_block_icon = '.sidebar-collapsed-icon'
before do
resize_screen_sm
end
it 'confidentiality block expands then collapses sidebar' do
expect(page).to have_css(collapsed_sidebar_selector)
page.within(confidentiality_sidebar_block) do
find(collapsed_sidebar_block_icon).click
end
expect(page).to have_css(expanded_sidebar_selector)
page.within(confidentiality_sidebar_block) do
page.find('button', text: 'Cancel').click
end
expect(page).to have_css(collapsed_sidebar_selector)
end
it 'lock block expands then collapses sidebar' do
expect(page).to have_css(collapsed_sidebar_selector)
page.within(lock_sidebar_block) do
find(collapsed_sidebar_block_icon).click
end
expect(page).to have_css(expanded_sidebar_selector)
page.within(lock_sidebar_block) do
page.find('button', text: 'Cancel').click
end
expect(page).to have_css(collapsed_sidebar_selector)
end
end
end
context 'as a guest' do
......
/* global BoardService */
<<<<<<< HEAD
export const boardObj = {
id: 1,
......@@ -6,6 +7,8 @@ export const boardObj = {
milestone_id: null,
};
=======
>>>>>>> upstream/master
export const listObj = {
id: 300,
position: 0,
......@@ -46,12 +49,15 @@ export const BoardsMockData = {
},
],
},
<<<<<<< HEAD
'/test/issue-boards/milestones.json': [
{
id: 1,
title: 'test',
},
],
=======
>>>>>>> upstream/master
},
POST: {
'/test/-/boards/1/lists': listObj,
......
......@@ -62,4 +62,22 @@ describe('Confidential Issue Sidebar Block', () => {
done();
});
});
it('displays the edit form when opened from collapsed state', (done) => {
expect(vm1.edit).toBe(false);
vm1.$el.querySelector('.sidebar-collapsed-icon').click();
expect(vm1.edit).toBe(true);
setTimeout(() => {
expect(
vm1.$el
.innerHTML
.includes('You are going to turn off the confidentiality.'),
).toBe(true);
done();
});
});
});
......@@ -68,4 +68,22 @@ describe('LockIssueSidebar', () => {
done();
});
});
it('displays the edit form when opened from collapsed state', (done) => {
expect(vm1.isLockDialogOpen).toBe(false);
vm1.$el.querySelector('.sidebar-collapsed-icon').click();
expect(vm1.isLockDialogOpen).toBe(true);
setTimeout(() => {
expect(
vm1.$el
.innerHTML
.includes('Unlock this issue?'),
).toBe(true);
done();
});
});
});
......@@ -159,6 +159,7 @@ export default {
avatar_url:
'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
web_url: 'http://localhost:3000/root',
<<<<<<< HEAD
},
author_gravatar_url:
'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
......@@ -393,3 +394,62 @@ export const codequalityParsedIssues = [
urlPath: 'foo/Gemfile.lock',
},
];
=======
},
author_gravatar_url:
'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
commit_url:
'http://localhost:3000/root/acets-app/commit/104096c51715e12e7ae41f9333e9fa35b73f385d',
commit_path: '/root/acets-app/commit/104096c51715e12e7ae41f9333e9fa35b73f385d',
},
retry_path: '/root/acets-app/pipelines/172/retry',
created_at: '2017-04-07T12:27:19.520Z',
updated_at: '2017-04-07T15:28:44.800Z',
},
work_in_progress: false,
source_branch_exists: false,
mergeable_discussions_state: true,
conflicts_can_be_resolved_in_ui: false,
branch_missing: true,
commits_count: 1,
has_conflicts: false,
can_be_merged: true,
has_ci: true,
ci_status: 'success',
pipeline_status_path: '/root/acets-app/merge_requests/22/pipeline_status',
issues_links: {
closing: '',
mentioned_but_not_closing: '',
},
current_user: {
can_resolve_conflicts: true,
can_remove_source_branch: false,
can_revert_on_current_merge_request: true,
can_cherry_pick_on_current_merge_request: true,
},
target_branch_path: '/root/acets-app/branches/master',
source_branch_path: '/root/acets-app/branches/daaaa',
conflict_resolution_ui_path: '/root/acets-app/merge_requests/22/conflicts',
remove_wip_path: '/root/acets-app/merge_requests/22/remove_wip',
cancel_merge_when_pipeline_succeeds_path:
'/root/acets-app/merge_requests/22/cancel_merge_when_pipeline_succeeds',
create_issue_to_resolve_discussions_path:
'/root/acets-app/issues/new?merge_request_to_resolve_discussions_of=22',
merge_path: '/root/acets-app/merge_requests/22/merge',
cherry_pick_in_fork_path:
'/root/acets-app/forks?continue%5Bnotice%5D=You%27re+not+allowed+to+make+changes+to+this+project+directly.+A+fork+of+this+project+has+been+created+that+you+can+make+changes+in%2C+so+you+can+submit+a+merge+request.+Try+to+revert+this+commit+again.&continue%5Bnotice_now%5D=You%27re+not+allowed+to+make+changes+to+this+project+directly.+A+fork+of+this+project+is+being+created+that+you+can+make+changes+in%2C+so+you+can+submit+a+merge+request.&continue%5Bto%5D=%2Froot%2Facets-app%2Fmerge_requests%2F22&namespace_key=1',
revert_in_fork_path:
'/root/acets-app/forks?continue%5Bnotice%5D=You%27re+not+allowed+to+make+changes+to+this+project+directly.+A+fork+of+this+project+has+been+created+that+you+can+make+changes+in%2C+so+you+can+submit+a+merge+request.+Try+to+cherry-pick+this+commit+again.&continue%5Bnotice_now%5D=You%27re+not+allowed+to+make+changes+to+this+project+directly.+A+fork+of+this+project+is+being+created+that+you+can+make+changes+in%2C+so+you+can+submit+a+merge+request.&continue%5Bto%5D=%2Froot%2Facets-app%2Fmerge_requests%2F22&namespace_key=1',
email_patches_path: '/root/acets-app/merge_requests/22.patch',
plain_diff_path: '/root/acets-app/merge_requests/22.diff',
status_path: '/root/acets-app/merge_requests/22.json',
merge_check_path: '/root/acets-app/merge_requests/22/merge_check',
ci_environments_status_url: '/root/acets-app/merge_requests/22/ci_environments_status',
project_archived: false,
merge_commit_message_with_description:
"Merge branch 'daaaa' into 'master'\n\nUpdate README.md\n\nSee merge request !22",
diverged_commits_count: 0,
only_allow_merge_if_pipeline_succeeds: false,
commit_change_content_path: '/root/acets-app/merge_requests/22/commit_change_content',
};
>>>>>>> upstream/master
......@@ -12,11 +12,11 @@ describe Gitlab::HTTP do
end
it 'deny requests to localhost' do
expect { described_class.get('http://localhost:3003') }.to raise_error(URI::InvalidURIError)
expect { described_class.get('http://localhost:3003') }.to raise_error(Gitlab::HTTP::BlockedUrlError)
end
it 'deny requests to private network' do
expect { described_class.get('http://192.168.1.2:3003') }.to raise_error(URI::InvalidURIError)
expect { described_class.get('http://192.168.1.2:3003') }.to raise_error(Gitlab::HTTP::BlockedUrlError)
end
context 'if allow_local_requests set to true' do
......@@ -41,7 +41,7 @@ describe Gitlab::HTTP do
context 'if allow_local_requests set to false' do
it 'override the global value and ban requests to localhost or private network' do
expect { described_class.get('http://localhost:3003', allow_local_requests: false) }.to raise_error(URI::InvalidURIError)
expect { described_class.get('http://localhost:3003', allow_local_requests: false) }.to raise_error(Gitlab::HTTP::BlockedUrlError)
end
end
end
......
......@@ -74,13 +74,13 @@ describe Gitlab::UrlBlocker do
expect(described_class.blocked_url?('https://gitlab.com/foo/foo.git')).to be false
end
context 'when allow_private_networks is' do
let(:private_networks) { ['192.168.1.2', '10.0.0.2', '172.16.0.2'] }
context 'when allow_local_network is' do
let(:local_ips) { ['192.168.1.2', '10.0.0.2', '172.16.0.2'] }
let(:fake_domain) { 'www.fakedomain.fake' }
context 'true (default)' do
it 'does not block urls from private networks' do
private_networks.each do |ip|
local_ips.each do |ip|
stub_domain_resolv(fake_domain, ip)
expect(described_class).not_to be_blocked_url("http://#{fake_domain}")
......@@ -94,14 +94,14 @@ describe Gitlab::UrlBlocker do
context 'false' do
it 'blocks urls from private networks' do
private_networks.each do |ip|
local_ips.each do |ip|
stub_domain_resolv(fake_domain, ip)
expect(described_class).to be_blocked_url("http://#{fake_domain}", allow_private_networks: false)
expect(described_class).to be_blocked_url("http://#{fake_domain}", allow_local_network: false)
unstub_domain_resolv
expect(described_class).to be_blocked_url("http://#{ip}", allow_private_networks: false)
expect(described_class).to be_blocked_url("http://#{ip}", allow_local_network: false)
end
end
end
......
......@@ -251,14 +251,14 @@ describe Project do
project2 = build(:project, import_url: 'http://localhost:9000/t.git')
expect(project2).to be_invalid
expect(project2.errors[:import_url]).to include('imports are not allowed from that URL')
expect(project2.errors[:import_url].first).to include('Requests to localhost are not allowed')
end
it "does not allow blocked import_url port" do
project2 = build(:project, import_url: 'http://github.com:25/t.git')
expect(project2).to be_invalid
expect(project2.errors[:import_url]).to include('imports are not allowed from that URL')
expect(project2.errors[:import_url].first).to include('Only allowed ports are 22, 80, 443')
end
it 'creates mirror data when enabled' do
......
......@@ -156,7 +156,7 @@ describe Projects::ImportService do
result = described_class.new(project, user).execute
expect(result[:status]).to eq :error
expect(result[:message]).to end_with 'Blocked import URL.'
expect(result[:message]).to include('Requests to localhost are not allowed')
end
it 'fails with port 25' do
......@@ -165,7 +165,7 @@ describe Projects::ImportService do
result = described_class.new(project, user).execute
expect(result[:status]).to eq :error
expect(result[:message]).to end_with 'Blocked import URL.'
expect(result[:message]).to include('Only allowed ports are 22, 80, 443')
end
end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment