diff options
Diffstat (limited to 'app')
35 files changed, 180 insertions, 137 deletions
diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js index 2afa4e4c1bf..09f0ea37103 100644 --- a/app/assets/javascripts/notes.js +++ b/app/assets/javascripts/notes.js @@ -1727,6 +1727,7 @@ export default class Notes { // Get Form metadata const $submitBtn = $(e.target); + $submitBtn.prop('disabled', true); let $form = $submitBtn.parents('form'); const $closeBtn = $form.find('.js-note-target-close'); const isDiscussionNote = @@ -1761,7 +1762,6 @@ export default class Notes { // If comment is to resolve discussion, disable submit buttons while // comment posting is finished. if (isDiscussionResolve) { - $submitBtn.disable(); $form.find('.js-comment-submit-button').disable(); } @@ -1816,6 +1816,7 @@ export default class Notes { .then(res => { const note = res.data; + $submitBtn.prop('disabled', false); // Submission successful! remove placeholder $notesContainer.find(`#${noteUniqueId}`).remove(); @@ -1899,7 +1900,7 @@ export default class Notes { .catch(() => { // Submission failed, remove placeholder note and show Flash error message $notesContainer.find(`#${noteUniqueId}`).remove(); - + $submitBtn.prop('disabled', false); const blurEvent = new CustomEvent('blur.imageDiff', { detail: e, }); diff --git a/app/assets/javascripts/performance_bar/components/detailed_metric.vue b/app/assets/javascripts/performance_bar/components/detailed_metric.vue index 145465f4ee9..db8a0055acd 100644 --- a/app/assets/javascripts/performance_bar/components/detailed_metric.vue +++ b/app/assets/javascripts/performance_bar/components/detailed_metric.vue @@ -27,12 +27,21 @@ export default { required: true, }, }, + computed: { + metricDetails() { + return this.currentRequest.details[this.metric]; + }, + detailsList() { + return this.metricDetails[this.details]; + }, + }, }; </script> <template> <div :id="`peek-view-${metric}`" class="view" + v-if="currentRequest.details" > <button :data-target="`#modal-peek-${metric}-details`" @@ -40,34 +49,40 @@ export default { type="button" data-toggle="modal" > - <span - v-if="currentRequest.details" - class="bold" - > - {{ currentRequest.details[metric].duration }} - / - {{ currentRequest.details[metric].calls }} - </span> + {{ metricDetails.duration }} + / + {{ metricDetails.calls }} </button> <gl-modal - v-if="currentRequest.details" :id="`modal-peek-${metric}-details`" :header-title-text="header" class="performance-bar-modal" > - <table class="table"> - <tr - v-for="(item, index) in currentRequest.details[metric][details]" - :key="index" - > - <td><strong>{{ item.duration }}ms</strong></td> - <td - v-for="key in keys" - :key="key" + <table + class="table" + > + <template v-if="detailsList.length"> + <tr + v-for="(item, index) in detailsList" + :key="index" > - {{ item[key] }} - </td> - </tr> + <td><strong>{{ item.duration }}ms</strong></td> + <td + v-for="key in keys" + :key="key" + class="break-word" + > + {{ item[key] }} + </td> + </tr> + </template> + <template v-else> + <tr> + <td> + No {{ header.toLowerCase() }} for this request. + </td> + </tr> + </template> </table> <div slot="footer"> diff --git a/app/assets/javascripts/performance_bar/components/performance_bar_app.vue b/app/assets/javascripts/performance_bar/components/performance_bar_app.vue index 88345cf2ad9..2fd1715ee79 100644 --- a/app/assets/javascripts/performance_bar/components/performance_bar_app.vue +++ b/app/assets/javascripts/performance_bar/components/performance_bar_app.vue @@ -113,27 +113,21 @@ export default { id="js-peek" :class="env" > - <request-selector - v-if="currentRequest" - :current-request="currentRequest" - :requests="requests" - @change-current-request="changeCurrentRequest" - /> - <div - id="peek-view-host" - class="view prepend-left-5" - > - <span - v-if="currentRequest && currentRequest.details" - class="current-host" - > - {{ currentRequest.details.host.hostname }} - </span> - </div> <div v-if="currentRequest" - class="wrapper" + class="container-fluid container-limited" > + <div + id="peek-view-host" + class="view" + > + <span + v-if="currentRequest.details" + class="current-host" + > + {{ currentRequest.details.host.hostname }} + </span> + </div> <upstream-performance-bar v-if="initialRequest && currentRequest.details" /> @@ -186,6 +180,12 @@ export default { gc </span> </div> + <request-selector + v-if="currentRequest" + :current-request="currentRequest" + :requests="requests" + @change-current-request="changeCurrentRequest" + /> </div> </div> </template> diff --git a/app/assets/javascripts/performance_bar/components/request_selector.vue b/app/assets/javascripts/performance_bar/components/request_selector.vue index 2f360ea6f6c..3ed07a4a47d 100644 --- a/app/assets/javascripts/performance_bar/components/request_selector.vue +++ b/app/assets/javascripts/performance_bar/components/request_selector.vue @@ -37,7 +37,7 @@ export default { <template> <div id="peek-request-selector" - class="append-right-5 pull-right" + class="pull-right" > <select v-model="currentRequestId"> <option diff --git a/app/assets/javascripts/performance_bar/components/upstream_performance_bar.vue b/app/assets/javascripts/performance_bar/components/upstream_performance_bar.vue index d438b1ec27b..2b5915f381f 100644 --- a/app/assets/javascripts/performance_bar/components/upstream_performance_bar.vue +++ b/app/assets/javascripts/performance_bar/components/upstream_performance_bar.vue @@ -5,6 +5,8 @@ export default { .getElementById('peek-view-performance-bar') .cloneNode(true); + upstreamPerformanceBar.classList.remove('hidden'); + this.$refs.wrapper.appendChild(upstreamPerformanceBar); }, }; diff --git a/app/assets/javascripts/performance_bar/index.js b/app/assets/javascripts/performance_bar/index.js index fca488120f6..a0ddf36a672 100644 --- a/app/assets/javascripts/performance_bar/index.js +++ b/app/assets/javascripts/performance_bar/index.js @@ -4,9 +4,9 @@ import Vue from 'vue'; import performanceBarApp from './components/performance_bar_app.vue'; import PerformanceBarStore from './stores/performance_bar_store'; -export default () => +export default ({ container }) => new Vue({ - el: '#js-peek', + el: container, components: { performanceBarApp, }, diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss index 37d33320445..d0dda50a835 100644 --- a/app/assets/stylesheets/framework/common.scss +++ b/app/assets/stylesheets/framework/common.scss @@ -446,6 +446,10 @@ img.emoji { opacity: .5; } +.break-word { + word-wrap: break-word; +} + /** COMMON CLASSES **/ .prepend-top-0 { margin-top: 0; } .prepend-top-5 { margin-top: 5px; } diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index 85de0d8e70f..584b0579b72 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -9,7 +9,6 @@ .new_project, .edit-project, .import-project { - .help-block { margin-bottom: 10px; } @@ -18,18 +17,25 @@ border-radius: $border-radius-base; } - .input-group > div { + .input-group { + display: flex; - &:last-child { - padding-right: 0; + .select2-container { + display: unset; + max-width: unset; + width: unset !important; + flex-grow: 1; + } + + > div { + &:last-child { + padding-right: 0; + } } } @media (max-width: $screen-xs-max) { .input-group > div { - - margin-bottom: 14px; - &:last-child { margin-bottom: 0; } @@ -41,17 +47,24 @@ } .input-group-addon { + overflow: hidden; + text-overflow: ellipsis; + line-height: unset; + width: unset; + max-width: 50%; + text-align: left; &.static-namespace { height: 35px; border-radius: 3px; border: 1px solid $border-color; + max-width: 100%; + flex-grow: 1; } + .select2 a, + .btn-default { - border-top-left-radius: 0; - border-bottom-left-radius: 0; + border-radius: 0 $border-radius-base $border-radius-base 0; } } } @@ -290,7 +303,7 @@ font-size: 13px; font-weight: $gl-font-weight-bold; line-height: 13px; - letter-spacing: .4px; + letter-spacing: 0.4px; padding: 6px 14px; text-align: center; vertical-align: middle; @@ -443,7 +456,7 @@ a.deploy-project-label { text-decoration: none; &.disabled { - opacity: .3; + opacity: 0.3; cursor: not-allowed; } } @@ -600,26 +613,26 @@ a.deploy-project-label { } .first-column { - @media(min-width: $screen-xs-min) { + @media (min-width: $screen-xs-min) { max-width: 50%; padding-right: 30px; } - @media(max-width: $screen-xs-max) { + @media (max-width: $screen-xs-max) { max-width: 100%; width: 100%; } } .second-column { - @media(min-width: $screen-xs-min) { + @media (min-width: $screen-xs-min) { width: 50%; flex: 1; padding-left: 30px; position: relative; } - @media(max-width: $screen-xs-max) { + @media (max-width: $screen-xs-max) { max-width: 100%; width: 100%; padding-left: 0; @@ -632,7 +645,7 @@ a.deploy-project-label { } &::before { - content: "OR"; + content: 'OR'; position: absolute; left: -10px; top: 50%; @@ -656,7 +669,7 @@ a.deploy-project-label { } &::after { - content: ""; + content: ''; position: absolute; background-color: $border-color; bottom: 0; @@ -921,10 +934,7 @@ pre.light-well { border-right: solid 1px transparent; } } -} -.protected-tags-list, -.protected-branches-list { .dropdown-menu-toggle { width: 100%; max-width: 300px; diff --git a/app/assets/stylesheets/performance_bar.scss b/app/assets/stylesheets/performance_bar.scss index d06148a7bf8..d69b390ac27 100644 --- a/app/assets/stylesheets/performance_bar.scss +++ b/app/assets/stylesheets/performance_bar.scss @@ -43,12 +43,6 @@ } } - .wrapper { - width: 80%; - height: $performance-bar-height; - margin: 0 auto; - } - // UI Elements .bucket { background: $perf-bar-bucket-bg; @@ -108,8 +102,14 @@ } } - .performance-bar-modal .modal-footer { - display: none; + .performance-bar-modal { + .modal-footer { + display: none; + } + + .modal-dialog { + width: 860px; + } } } diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb index 8440945ab43..fff249577a2 100644 --- a/app/controllers/omniauth_callbacks_controller.rb +++ b/app/controllers/omniauth_callbacks_controller.rb @@ -95,6 +95,14 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController handle_omniauth end + def auth0 + if oauth['uid'].blank? + fail_auth0_login + else + handle_omniauth + end + end + private def handle_omniauth @@ -170,6 +178,12 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController redirect_to new_user_session_path end + def fail_auth0_login + flash[:alert] = 'Wrong extern UID provided. Make sure Auth0 is configured correctly.' + + redirect_to new_user_session_path + end + def handle_disabled_provider label = Gitlab::Auth::OAuth::Provider.label_for(oauth['provider']) flash[:alert] = "Signing in using #{label} has been disabled" diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb index 4c4d7cca8a5..63e4a5dc45c 100644 --- a/app/helpers/application_settings_helper.rb +++ b/app/helpers/application_settings_helper.rb @@ -245,7 +245,8 @@ module ApplicationSettingsHelper :usage_ping_enabled, :user_default_external, :user_oauth_applications, - :version_check_enabled + :version_check_enabled, + :allow_local_requests_from_hooks_and_services ] end end diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb index 3cbbf8b5dfa..862933bf127 100644 --- a/app/models/application_setting.rb +++ b/app/models/application_setting.rb @@ -330,7 +330,8 @@ class ApplicationSetting < ActiveRecord::Base usage_ping_enabled: Settings.gitlab['usage_ping_enabled'], gitaly_timeout_fast: 10, gitaly_timeout_medium: 30, - gitaly_timeout_default: 55 + gitaly_timeout_default: 55, + allow_local_requests_from_hooks_and_services: false } end diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index f2edcdd61fd..44f9bdf111e 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -14,7 +14,7 @@ module Ci has_many :stages has_many :statuses, class_name: 'CommitStatus', foreign_key: :commit_id, inverse_of: :pipeline - has_many :builds, foreign_key: :commit_id + has_many :builds, foreign_key: :commit_id, inverse_of: :pipeline has_many :trigger_requests, dependent: :destroy, foreign_key: :commit_id # rubocop:disable Cop/ActiveRecordDependent has_many :variables, class_name: 'Ci::PipelineVariable' diff --git a/app/models/project.rb b/app/models/project.rb index e5ede967668..250680e2a2c 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -38,6 +38,9 @@ class Project < ActiveRecord::Base attachments: 2 }.freeze + # Valids ports to import from + VALID_IMPORT_PORTS = [22, 80, 443].freeze + cache_markdown_field :description, pipeline: :description delegate :feature_available?, :builds_enabled?, :wiki_enabled?, diff --git a/app/models/project_services/assembla_service.rb b/app/models/project_services/assembla_service.rb index ae6af732ed4..4234b8044e5 100644 --- a/app/models/project_services/assembla_service.rb +++ b/app/models/project_services/assembla_service.rb @@ -1,6 +1,4 @@ class AssemblaService < Service - include HTTParty - prop_accessor :token, :subdomain validates :token, presence: true, if: :activated? @@ -31,6 +29,6 @@ class AssemblaService < Service return unless supported_events.include?(data[:object_kind]) url = "https://atlas.assembla.com/spaces/#{subdomain}/github_tool?secret_key=#{token}" - AssemblaService.post(url, body: { payload: data }.to_json, headers: { 'Content-Type' => 'application/json' }) + Gitlab::HTTP.post(url, body: { payload: data }.to_json, headers: { 'Content-Type' => 'application/json' }) end end diff --git a/app/models/project_services/bamboo_service.rb b/app/models/project_services/bamboo_service.rb index 42939ea0ec8..54e4b3278db 100644 --- a/app/models/project_services/bamboo_service.rb +++ b/app/models/project_services/bamboo_service.rb @@ -117,14 +117,14 @@ class BambooService < CiService url = build_url(path) if username.blank? && password.blank? - HTTParty.get(url, verify: false) + Gitlab::HTTP.get(url, verify: false) else url << '&os_authType=basic' - HTTParty.get(url, verify: false, - basic_auth: { - username: username, - password: password - }) + Gitlab::HTTP.get(url, verify: false, + basic_auth: { + username: username, + password: password + }) end end end diff --git a/app/models/project_services/buildkite_service.rb b/app/models/project_services/buildkite_service.rb index fc30f6e3365..d2aaff8817a 100644 --- a/app/models/project_services/buildkite_service.rb +++ b/app/models/project_services/buildkite_service.rb @@ -71,7 +71,7 @@ class BuildkiteService < CiService end def calculate_reactive_cache(sha, ref) - response = HTTParty.get(commit_status_path(sha), verify: false) + response = Gitlab::HTTP.get(commit_status_path(sha), verify: false) status = if response.code == 200 && response['status'] diff --git a/app/models/project_services/campfire_service.rb b/app/models/project_services/campfire_service.rb index 8d7a4fceb08..cb4af73807b 100644 --- a/app/models/project_services/campfire_service.rb +++ b/app/models/project_services/campfire_service.rb @@ -1,6 +1,4 @@ class CampfireService < Service - include HTTParty - prop_accessor :token, :subdomain, :room validates :token, presence: true, if: :activated? @@ -31,7 +29,6 @@ class CampfireService < Service def execute(data) return unless supported_events.include?(data[:object_kind]) - self.class.base_uri base_uri message = build_message(data) speak(self.room, message, auth) end @@ -69,14 +66,14 @@ class CampfireService < Service } } } - res = self.class.post(path, auth.merge(body)) + res = Gitlab::HTTP.post(path, base_uri: base_uri, **auth.merge(body)) res.code == 201 ? res : nil end # Returns a list of rooms, or []. # https://github.com/basecamp/campfire-api/blob/master/sections/rooms.md#get-rooms def rooms(auth) - res = self.class.get("/rooms.json", auth) + res = Gitlab::HTTP.get("/rooms.json", base_uri: base_uri, **auth) res.code == 200 ? res["rooms"] : [] end diff --git a/app/models/project_services/drone_ci_service.rb b/app/models/project_services/drone_ci_service.rb index c93f1632652..71b10fc6bc1 100644 --- a/app/models/project_services/drone_ci_service.rb +++ b/app/models/project_services/drone_ci_service.rb @@ -49,7 +49,7 @@ class DroneCiService < CiService end def calculate_reactive_cache(sha, ref) - response = HTTParty.get(commit_status_path(sha, ref), verify: enable_ssl_verification) + response = Gitlab::HTTP.get(commit_status_path(sha, ref), verify: enable_ssl_verification) status = if response.code == 200 && response['status'] diff --git a/app/models/project_services/external_wiki_service.rb b/app/models/project_services/external_wiki_service.rb index 720ad61162e..1553f169827 100644 --- a/app/models/project_services/external_wiki_service.rb +++ b/app/models/project_services/external_wiki_service.rb @@ -1,6 +1,4 @@ class ExternalWikiService < Service - include HTTParty - prop_accessor :external_wiki_url validates :external_wiki_url, presence: true, url: true, if: :activated? @@ -24,7 +22,7 @@ class ExternalWikiService < Service end def execute(_data) - @response = HTTParty.get(properties['external_wiki_url'], verify: true) rescue nil + @response = Gitlab::HTTP.get(properties['external_wiki_url'], verify: true) rescue nil if @response != 200 nil end diff --git a/app/models/project_services/issue_tracker_service.rb b/app/models/project_services/issue_tracker_service.rb index 5fb15c383ca..df6dcd90985 100644 --- a/app/models/project_services/issue_tracker_service.rb +++ b/app/models/project_services/issue_tracker_service.rb @@ -77,13 +77,13 @@ class IssueTrackerService < Service result = false begin - response = HTTParty.head(self.project_url, verify: true) + response = Gitlab::HTTP.head(self.project_url, verify: true) if response message = "#{self.type} received response #{response.code} when attempting to connect to #{self.project_url}" result = true end - rescue HTTParty::Error, Timeout::Error, SocketError, Errno::ECONNRESET, Errno::ECONNREFUSED, OpenSSL::SSL::SSLError => error + rescue Gitlab::HTTP::Error, Timeout::Error, SocketError, Errno::ECONNRESET, Errno::ECONNREFUSED, OpenSSL::SSL::SSLError => error message = "#{self.type} had an error when trying to connect to #{self.project_url}: #{error.message}" end Rails.logger.info(message) diff --git a/app/models/project_services/mock_ci_service.rb b/app/models/project_services/mock_ci_service.rb index 72ddf9a4be3..2221459c90b 100644 --- a/app/models/project_services/mock_ci_service.rb +++ b/app/models/project_services/mock_ci_service.rb @@ -52,7 +52,7 @@ class MockCiService < CiService # # def commit_status(sha, ref) - response = HTTParty.get(commit_status_path(sha), verify: false) + response = Gitlab::HTTP.get(commit_status_path(sha), verify: false) read_commit_status(response) rescue Errno::ECONNREFUSED :error diff --git a/app/models/project_services/packagist_service.rb b/app/models/project_services/packagist_service.rb index f68a0c1a3c3..ba62a5b7ac0 100644 --- a/app/models/project_services/packagist_service.rb +++ b/app/models/project_services/packagist_service.rb @@ -1,6 +1,4 @@ class PackagistService < Service - include HTTParty - prop_accessor :username, :token, :server validates :username, presence: true, if: :activated? diff --git a/app/models/project_services/pivotaltracker_service.rb b/app/models/project_services/pivotaltracker_service.rb index f9dfa2e91c3..3476e7d2283 100644 --- a/app/models/project_services/pivotaltracker_service.rb +++ b/app/models/project_services/pivotaltracker_service.rb @@ -1,6 +1,4 @@ class PivotaltrackerService < Service - include HTTParty - API_ENDPOINT = 'https://www.pivotaltracker.com/services/v5/source_commits'.freeze prop_accessor :token, :restrict_to_branch @@ -52,7 +50,7 @@ class PivotaltrackerService < Service 'message' => commit[:message] } } - PivotaltrackerService.post( + Gitlab::HTTP.post( API_ENDPOINT, body: message.to_json, headers: { diff --git a/app/models/project_services/pushover_service.rb b/app/models/project_services/pushover_service.rb index e3a1ca2d45f..8777a44b72f 100644 --- a/app/models/project_services/pushover_service.rb +++ b/app/models/project_services/pushover_service.rb @@ -1,6 +1,5 @@ class PushoverService < Service - include HTTParty - base_uri 'https://api.pushover.net/1' + BASE_URI = 'https://api.pushover.net/1'.freeze prop_accessor :api_key, :user_key, :device, :priority, :sound validates :api_key, :user_key, :priority, presence: true, if: :activated? @@ -99,6 +98,6 @@ class PushoverService < Service pushover_data[:sound] = sound end - PushoverService.post('/messages.json', body: pushover_data) + Gitlab::HTTP.post('/messages.json', base_uri: BASE_URI, body: pushover_data) end end diff --git a/app/models/project_services/teamcity_service.rb b/app/models/project_services/teamcity_service.rb index cbe137452bd..145313b8e71 100644 --- a/app/models/project_services/teamcity_service.rb +++ b/app/models/project_services/teamcity_service.rb @@ -83,7 +83,7 @@ class TeamcityService < CiService branch = Gitlab::Git.ref_name(data[:ref]) - HTTParty.post( + Gitlab::HTTP.post( build_url('httpAuth/app/rest/buildQueue'), body: "<build branchName=\"#{branch}\">"\ "<buildType id=\"#{build_type}\"/>"\ @@ -134,10 +134,10 @@ class TeamcityService < CiService end def get_path(path) - HTTParty.get(build_url(path), verify: false, - basic_auth: { - username: username, - password: password - }) + Gitlab::HTTP.get(build_url(path), verify: false, + basic_auth: { + username: username, + password: password + }) end end diff --git a/app/services/projects/import_service.rb b/app/services/projects/import_service.rb index f2d676af5c3..a34024f4f80 100644 --- a/app/services/projects/import_service.rb +++ b/app/services/projects/import_service.rb @@ -28,7 +28,7 @@ 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) + raise Error, 'Blocked import URL.' if Gitlab::UrlBlocker.blocked_url?(project.import_url, valid_ports: Project::VALID_IMPORT_PORTS) end # We should skip the repository for a GitHub import or GitLab project import, diff --git a/app/services/submit_usage_ping_service.rb b/app/services/submit_usage_ping_service.rb index 2623f253d98..ac029fad7ea 100644 --- a/app/services/submit_usage_ping_service.rb +++ b/app/services/submit_usage_ping_service.rb @@ -14,16 +14,17 @@ class SubmitUsagePingService def execute return false unless Gitlab::CurrentSettings.usage_ping_enabled? - response = HTTParty.post( + response = Gitlab::HTTP.post( URL, body: Gitlab::UsageData.to_json(force_refresh: true), + allow_local_requests: true, headers: { 'Content-type' => 'application/json' } ) store_metrics(response) true - rescue HTTParty::Error => e + rescue Gitlab::HTTP::Error => e Rails.logger.info "Unable to contact GitLab, Inc.: #{e}" false diff --git a/app/services/web_hook_service.rb b/app/services/web_hook_service.rb index 36e589d5aa8..809ce1303d8 100644 --- a/app/services/web_hook_service.rb +++ b/app/services/web_hook_service.rb @@ -3,23 +3,20 @@ class WebHookService attr_reader :body, :headers, :code def initialize - @headers = HTTParty::Response::Headers.new({}) + @headers = Gitlab::HTTP::Response::Headers.new({}) @body = '' @code = 'internal error' end end - include HTTParty - - # HTTParty timeout - default_timeout Gitlab.config.gitlab.webhook_timeout - - attr_accessor :hook, :data, :hook_name + attr_accessor :hook, :data, :hook_name, :request_options def initialize(hook, data, hook_name) @hook = hook @data = data @hook_name = hook_name.to_s + @request_options = { timeout: Gitlab.config.gitlab.webhook_timeout } + @request_options.merge!(allow_local_requests: true) if @hook.is_a?(SystemHook) end def execute @@ -73,11 +70,12 @@ class WebHookService end def make_request(url, basic_auth = false) - self.class.post(url, + Gitlab::HTTP.post(url, body: data.to_json, headers: build_headers(hook_name), verify: hook.enable_ssl_verification, - basic_auth: basic_auth) + basic_auth: basic_auth, + **request_options) end def make_request_with_auth diff --git a/app/validators/importable_url_validator.rb b/app/validators/importable_url_validator.rb index 37a314adee6..3ec1594e202 100644 --- a/app/validators/importable_url_validator.rb +++ b/app/validators/importable_url_validator.rb @@ -4,7 +4,7 @@ # protect against Server-side Request Forgery (SSRF). class ImportableUrlValidator < ActiveModel::EachValidator def validate_each(record, attribute, value) - if Gitlab::UrlBlocker.blocked_url?(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 end diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml index 81d7db04a3c..54b39df8cf3 100644 --- a/app/views/admin/application_settings/_form.html.haml +++ b/app/views/admin/application_settings/_form.html.haml @@ -860,5 +860,14 @@ .col-sm-10 = f.number_field :throttle_authenticated_web_period_in_seconds, class: 'form-control' + %fieldset + %legend Outbound requests + .form-group + .col-sm-offset-2.col-sm-10 + .checkbox + = f.label :allow_local_requests_from_hooks_and_services do + = f.check_box :allow_local_requests_from_hooks_and_services + Allow requests to the local network from hooks and services + .form-actions = f.submit 'Save', class: 'btn btn-save' diff --git a/app/views/import/gitlab_projects/new.html.haml b/app/views/import/gitlab_projects/new.html.haml index df5841d1911..dec85368d10 100644 --- a/app/views/import/gitlab_projects/new.html.haml +++ b/app/views/import/gitlab_projects/new.html.haml @@ -13,13 +13,13 @@ .form-group .input-group - if current_user.can_select_namespace? - .input-group-addon + .input-group-addon.has-tooltip{ title: root_url } = root_url = select_tag :namespace_id, namespaces_options(namespace_id_from(params) || :current_user, display_path: true, extra_group: namespace_id_from(params)), class: 'select2 js-select-namespace', tabindex: 1 - else - .input-group-addon.static-namespace - #{root_url}#{current_user.username}/ + .input-group-addon.static-namespace.has-tooltip{ title: user_url(current_user.username) + '/' } + #{user_url(current_user.username)}/ = hidden_field_tag :namespace_id, value: current_user.namespace_id .form-group.col-xs-12.col-sm-6.project-path = label_tag :path, 'Project name', class: 'label-light' diff --git a/app/views/layouts/_mailer.html.haml b/app/views/layouts/_mailer.html.haml index b50537438a9..ddc1cdb24b5 100644 --- a/app/views/layouts/_mailer.html.haml +++ b/app/views/layouts/_mailer.html.haml @@ -67,12 +67,8 @@ %td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;padding:25px 0;font-size:13px;line-height:1.6;color:#5c5c5c;" } %img{ alt: "GitLab", height: "33", src: image_url('mailers/gitlab_footer_logo.gif'), style: "display:block;margin:0 auto 1em;", width: "90" }/ %div - %a{ href: profile_notifications_url, style: "color:#3777b0;text-decoration:none;" } Manage all notifications - · - %a{ href: help_url, style: "color:#3777b0;text-decoration:none;" } Help - %div - You're receiving this email because of your account on - = succeed "." do - %a{ href: root_url, style: "color:#3777b0;text-decoration:none;" }= Gitlab.config.gitlab.host + - manage_notifications_link = link_to(_("Manage all notifications"), profile_notifications_url, style: "color:#3777b0;text-decoration:none;") + - help_link = link_to(_("Help"), help_url, style: "color:#3777b0;text-decoration:none;") + = _("You're receiving this email because of your account on %{host}. %{manage_notifications_link} · %{help_link}").html_safe % { host: Gitlab.config.gitlab.host, manage_notifications_link: manage_notifications_link, help_link: help_link } = yield :additional_footer diff --git a/app/views/peek/_bar.html.haml b/app/views/peek/_bar.html.haml index 14dafa197b5..b4d86e1601c 100644 --- a/app/views/peek/_bar.html.haml +++ b/app/views/peek/_bar.html.haml @@ -6,7 +6,7 @@ profile_url: url_for(params.merge(lineprofiler: 'true')) }, class: Peek.env } -#peek-view-performance-bar +#peek-view-performance-bar.hidden = render_server_response_time %span#serverstats %ul.performance-bar diff --git a/app/views/projects/_new_project_fields.html.haml b/app/views/projects/_new_project_fields.html.haml index f4b5ef1555e..241bc3dbca0 100644 --- a/app/views/projects/_new_project_fields.html.haml +++ b/app/views/projects/_new_project_fields.html.haml @@ -9,12 +9,12 @@ Project path .input-group - if current_user.can_select_namespace? - .input-group-addon + .input-group-addon.has-tooltip{ title: root_url } = root_url = f.select :namespace_id, namespaces_options(namespace_id_from(params) || :current_user, display_path: true, extra_group: namespace_id_from(params)), {}, { class: 'select2 js-select-namespace qa-project-namespace-select', tabindex: 1} - else - .input-group-addon.static-namespace + .input-group-addon.static-namespace.has-tooltip{ title: user_url(current_user.username) + '/' } #{user_url(current_user.username)}/ = f.hidden_field :namespace_id, value: current_user.namespace_id .form-group.project-path.col-sm-6 |