Commit 7c0a0e25 authored by Clement Ho's avatar Clement Ho

Merge branch 'ce-to-ee-2018-03-22' into 'master'

CE upstream - 2018-03-22 14:48 UTC

Closes #4642 and gitaly#1095

See merge request gitlab-org/gitlab-ee!5079
parents 28a53e89 d4ff35c3
...@@ -38,7 +38,7 @@ gem 'devise', '~> 4.2' ...@@ -38,7 +38,7 @@ gem 'devise', '~> 4.2'
gem 'doorkeeper', '~> 4.3' gem 'doorkeeper', '~> 4.3'
gem 'doorkeeper-openid_connect', '~> 1.3' gem 'doorkeeper-openid_connect', '~> 1.3'
gem 'omniauth', '~> 1.8' gem 'omniauth', '~> 1.8'
gem 'omniauth-auth0', '~> 1.4.1' gem 'omniauth-auth0', '~> 2.0.0'
gem 'omniauth-azure-oauth2', '~> 0.0.9' gem 'omniauth-azure-oauth2', '~> 0.0.9'
gem 'omniauth-cas3', '~> 1.1.4' gem 'omniauth-cas3', '~> 1.1.4'
gem 'omniauth-facebook', '~> 4.0.0' gem 'omniauth-facebook', '~> 4.0.0'
......
...@@ -557,8 +557,8 @@ GEM ...@@ -557,8 +557,8 @@ GEM
omniauth (1.8.1) omniauth (1.8.1)
hashie (>= 3.4.6, < 3.6.0) hashie (>= 3.4.6, < 3.6.0)
rack (>= 1.6.2, < 3) rack (>= 1.6.2, < 3)
omniauth-auth0 (1.4.1) omniauth-auth0 (2.0.0)
omniauth-oauth2 (~> 1.1) omniauth-oauth2 (~> 1.4)
omniauth-authentiq (0.3.1) omniauth-authentiq (0.3.1)
omniauth-oauth2 (~> 1.3, >= 1.3.1) omniauth-oauth2 (~> 1.3, >= 1.3.1)
omniauth-azure-oauth2 (0.0.9) omniauth-azure-oauth2 (0.0.9)
...@@ -1143,7 +1143,7 @@ DEPENDENCIES ...@@ -1143,7 +1143,7 @@ DEPENDENCIES
oauth2 (~> 1.4) oauth2 (~> 1.4)
octokit (~> 4.8) octokit (~> 4.8)
omniauth (~> 1.8) omniauth (~> 1.8)
omniauth-auth0 (~> 1.4.1) omniauth-auth0 (~> 2.0.0)
omniauth-authentiq (~> 0.3.1) omniauth-authentiq (~> 0.3.1)
omniauth-azure-oauth2 (~> 0.0.9) omniauth-azure-oauth2 (~> 0.0.9)
omniauth-cas3 (~> 1.1.4) omniauth-cas3 (~> 1.1.4)
......
10.6.0-pre 10.7.0-pre
...@@ -1727,6 +1727,7 @@ export default class Notes { ...@@ -1727,6 +1727,7 @@ export default class Notes {
// Get Form metadata // Get Form metadata
const $submitBtn = $(e.target); const $submitBtn = $(e.target);
$submitBtn.prop('disabled', true);
let $form = $submitBtn.parents('form'); let $form = $submitBtn.parents('form');
const $closeBtn = $form.find('.js-note-target-close'); const $closeBtn = $form.find('.js-note-target-close');
const isDiscussionNote = const isDiscussionNote =
...@@ -1761,7 +1762,6 @@ export default class Notes { ...@@ -1761,7 +1762,6 @@ export default class Notes {
// If comment is to resolve discussion, disable submit buttons while // If comment is to resolve discussion, disable submit buttons while
// comment posting is finished. // comment posting is finished.
if (isDiscussionResolve) { if (isDiscussionResolve) {
$submitBtn.disable();
$form.find('.js-comment-submit-button').disable(); $form.find('.js-comment-submit-button').disable();
} }
...@@ -1816,6 +1816,7 @@ export default class Notes { ...@@ -1816,6 +1816,7 @@ export default class Notes {
.then(res => { .then(res => {
const note = res.data; const note = res.data;
$submitBtn.prop('disabled', false);
// Submission successful! remove placeholder // Submission successful! remove placeholder
$notesContainer.find(`#${noteUniqueId}`).remove(); $notesContainer.find(`#${noteUniqueId}`).remove();
...@@ -1899,7 +1900,7 @@ export default class Notes { ...@@ -1899,7 +1900,7 @@ export default class Notes {
.catch(() => { .catch(() => {
// Submission failed, remove placeholder note and show Flash error message // Submission failed, remove placeholder note and show Flash error message
$notesContainer.find(`#${noteUniqueId}`).remove(); $notesContainer.find(`#${noteUniqueId}`).remove();
$submitBtn.prop('disabled', false);
const blurEvent = new CustomEvent('blur.imageDiff', { const blurEvent = new CustomEvent('blur.imageDiff', {
detail: e, detail: e,
}); });
......
...@@ -27,12 +27,21 @@ export default { ...@@ -27,12 +27,21 @@ export default {
required: true, required: true,
}, },
}, },
computed: {
metricDetails() {
return this.currentRequest.details[this.metric];
},
detailsList() {
return this.metricDetails[this.details];
},
},
}; };
</script> </script>
<template> <template>
<div <div
:id="`peek-view-${metric}`" :id="`peek-view-${metric}`"
class="view" class="view"
v-if="currentRequest.details"
> >
<button <button
:data-target="`#modal-peek-${metric}-details`" :data-target="`#modal-peek-${metric}-details`"
...@@ -40,34 +49,40 @@ export default { ...@@ -40,34 +49,40 @@ export default {
type="button" type="button"
data-toggle="modal" data-toggle="modal"
> >
<span {{ metricDetails.duration }}
v-if="currentRequest.details" /
class="bold" {{ metricDetails.calls }}
>
{{ currentRequest.details[metric].duration }}
/
{{ currentRequest.details[metric].calls }}
</span>
</button> </button>
<gl-modal <gl-modal
v-if="currentRequest.details"
:id="`modal-peek-${metric}-details`" :id="`modal-peek-${metric}-details`"
:header-title-text="header" :header-title-text="header"
class="performance-bar-modal" class="performance-bar-modal"
> >
<table class="table"> <table
<tr class="table"
v-for="(item, index) in currentRequest.details[metric][details]" >
:key="index" <template v-if="detailsList.length">
> <tr
<td><strong>{{ item.duration }}ms</strong></td> v-for="(item, index) in detailsList"
<td :key="index"
v-for="key in keys"
:key="key"
> >
{{ item[key] }} <td><strong>{{ item.duration }}ms</strong></td>
</td> <td
</tr> 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> </table>
<div slot="footer"> <div slot="footer">
......
...@@ -113,27 +113,21 @@ export default { ...@@ -113,27 +113,21 @@ export default {
id="js-peek" id="js-peek"
:class="env" :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 <div
v-if="currentRequest" 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 <upstream-performance-bar
v-if="initialRequest && currentRequest.details" v-if="initialRequest && currentRequest.details"
/> />
...@@ -186,6 +180,12 @@ export default { ...@@ -186,6 +180,12 @@ export default {
gc gc
</span> </span>
</div> </div>
<request-selector
v-if="currentRequest"
:current-request="currentRequest"
:requests="requests"
@change-current-request="changeCurrentRequest"
/>
</div> </div>
</div> </div>
</template> </template>
...@@ -37,7 +37,7 @@ export default { ...@@ -37,7 +37,7 @@ export default {
<template> <template>
<div <div
id="peek-request-selector" id="peek-request-selector"
class="append-right-5 pull-right" class="pull-right"
> >
<select v-model="currentRequestId"> <select v-model="currentRequestId">
<option <option
......
...@@ -5,6 +5,8 @@ export default { ...@@ -5,6 +5,8 @@ export default {
.getElementById('peek-view-performance-bar') .getElementById('peek-view-performance-bar')
.cloneNode(true); .cloneNode(true);
upstreamPerformanceBar.classList.remove('hidden');
this.$refs.wrapper.appendChild(upstreamPerformanceBar); this.$refs.wrapper.appendChild(upstreamPerformanceBar);
}, },
}; };
......
...@@ -4,9 +4,9 @@ import Vue from 'vue'; ...@@ -4,9 +4,9 @@ import Vue from 'vue';
import performanceBarApp from './components/performance_bar_app.vue'; import performanceBarApp from './components/performance_bar_app.vue';
import PerformanceBarStore from './stores/performance_bar_store'; import PerformanceBarStore from './stores/performance_bar_store';
export default () => export default ({ container }) =>
new Vue({ new Vue({
el: '#js-peek', el: container,
components: { components: {
performanceBarApp, performanceBarApp,
}, },
......
...@@ -454,6 +454,10 @@ img.emoji { ...@@ -454,6 +454,10 @@ img.emoji {
opacity: .5; opacity: .5;
} }
.break-word {
word-wrap: break-word;
}
/** COMMON CLASSES **/ /** COMMON CLASSES **/
.prepend-top-0 { margin-top: 0; } .prepend-top-0 { margin-top: 0; }
.prepend-top-5 { margin-top: 5px; } .prepend-top-5 { margin-top: 5px; }
......
...@@ -9,7 +9,6 @@ ...@@ -9,7 +9,6 @@
.new_project, .new_project,
.edit-project, .edit-project,
.import-project { .import-project {
.help-block { .help-block {
margin-bottom: 10px; margin-bottom: 10px;
} }
...@@ -18,10 +17,20 @@ ...@@ -18,10 +17,20 @@
border-radius: $border-radius-base; border-radius: $border-radius-base;
} }
.input-group > div { .input-group {
display: flex;
&:last-child { .select2-container {
padding-right: 0; display: unset;
max-width: unset;
width: unset !important;
flex-grow: 1;
}
> div {
&:last-child {
padding-right: 0;
}
} }
} }
...@@ -49,17 +58,24 @@ ...@@ -49,17 +58,24 @@
} }
.input-group-addon { .input-group-addon {
overflow: hidden;
text-overflow: ellipsis;
line-height: unset;
width: unset;
max-width: 50%;
text-align: left;
&.static-namespace { &.static-namespace {
height: 35px; height: 35px;
border-radius: 3px; border-radius: 3px;
border: 1px solid $border-color; border: 1px solid $border-color;
max-width: 100%;
flex-grow: 1;
} }
+ .select2 a, + .select2 a,
+ .btn-default { + .btn-default {
border-top-left-radius: 0; border-radius: 0 $border-radius-base $border-radius-base 0;
border-bottom-left-radius: 0;
} }
} }
} }
...@@ -298,7 +314,7 @@ ...@@ -298,7 +314,7 @@
font-size: 13px; font-size: 13px;
font-weight: $gl-font-weight-bold; font-weight: $gl-font-weight-bold;
line-height: 13px; line-height: 13px;
letter-spacing: .4px; letter-spacing: 0.4px;
padding: 6px 14px; padding: 6px 14px;
text-align: center; text-align: center;
vertical-align: middle; vertical-align: middle;
...@@ -451,7 +467,7 @@ a.deploy-project-label { ...@@ -451,7 +467,7 @@ a.deploy-project-label {
text-decoration: none; text-decoration: none;
&.disabled { &.disabled {
opacity: .3; opacity: 0.3;
cursor: not-allowed; cursor: not-allowed;
} }
} }
...@@ -607,26 +623,26 @@ a.deploy-project-label { ...@@ -607,26 +623,26 @@ a.deploy-project-label {
} }
.first-column { .first-column {
@media(min-width: $screen-xs-min) { @media (min-width: $screen-xs-min) {
max-width: 50%; max-width: 50%;
padding-right: 30px; padding-right: 30px;
} }
@media(max-width: $screen-xs-max) { @media (max-width: $screen-xs-max) {
max-width: 100%; max-width: 100%;
width: 100%; width: 100%;
} }
} }
.second-column { .second-column {
@media(min-width: $screen-xs-min) { @media (min-width: $screen-xs-min) {
width: 50%; width: 50%;
flex: 1; flex: 1;
padding-left: 30px; padding-left: 30px;
position: relative; position: relative;
} }
@media(max-width: $screen-xs-max) { @media (max-width: $screen-xs-max) {
max-width: 100%; max-width: 100%;
width: 100%; width: 100%;
padding-left: 0; padding-left: 0;
...@@ -639,7 +655,7 @@ a.deploy-project-label { ...@@ -639,7 +655,7 @@ a.deploy-project-label {
} }
&::before { &::before {
content: "OR"; content: 'OR';
position: absolute; position: absolute;
left: -10px; left: -10px;
top: 50%; top: 50%;
...@@ -663,7 +679,7 @@ a.deploy-project-label { ...@@ -663,7 +679,7 @@ a.deploy-project-label {
} }
&::after { &::after {
content: ""; content: '';
position: absolute; position: absolute;
background-color: $border-color; background-color: $border-color;
bottom: 0; bottom: 0;
...@@ -938,6 +954,11 @@ a.allowed-to-push { ...@@ -938,6 +954,11 @@ a.allowed-to-push {
} }
} }
.dropdown-menu-toggle {
width: 100%;
max-width: 300px;
}
.flash-container { .flash-container {
padding: 0; padding: 0;
} }
...@@ -947,13 +968,6 @@ a.allowed-to-push { ...@@ -947,13 +968,6 @@ a.allowed-to-push {
@extend .btn.disabled; @extend .btn.disabled;
} }
.protected-tags-list {
.dropdown-menu-toggle {
width: 100%;
max-width: 300px;
}
}
.custom-notifications-form { .custom-notifications-form {
.is-loading { .is-loading {
.custom-notification-event-loading { .custom-notification-event-loading {
......
...@@ -43,12 +43,6 @@ ...@@ -43,12 +43,6 @@
} }
} }
.wrapper {
width: 80%;
height: $performance-bar-height;
margin: 0 auto;
}
// UI Elements // UI Elements
.bucket { .bucket {
background: $perf-bar-bucket-bg; background: $perf-bar-bucket-bg;
...@@ -108,8 +102,14 @@ ...@@ -108,8 +102,14 @@
} }
} }
.performance-bar-modal .modal-footer { .performance-bar-modal {
display: none; .modal-footer {
display: none;
}
.modal-dialog {
width: 860px;
}
} }
} }
......
...@@ -108,6 +108,14 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController ...@@ -108,6 +108,14 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
handle_omniauth handle_omniauth
end end
def auth0
if oauth['uid'].blank?
fail_auth0_login
else
handle_omniauth
end
end
private private
def handle_omniauth def handle_omniauth
...@@ -183,6 +191,12 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController ...@@ -183,6 +191,12 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
redirect_to new_user_session_path redirect_to new_user_session_path
end 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 def handle_disabled_provider
label = Gitlab::Auth::OAuth::Provider.label_for(oauth['provider']) label = Gitlab::Auth::OAuth::Provider.label_for(oauth['provider'])
flash[:alert] = "Signing in using #{label} has been disabled" flash[:alert] = "Signing in using #{label} has been disabled"
......
...@@ -26,7 +26,7 @@ module Ci ...@@ -26,7 +26,7 @@ module Ci
has_many :stages has_many :stages
has_many :statuses, class_name: 'CommitStatus', foreign_key: :commit_id, inverse_of: :pipeline 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 :trigger_requests, dependent: :destroy, foreign_key: :commit_id # rubocop:disable Cop/ActiveRecordDependent
has_many :variables, class_name: 'Ci::PipelineVariable' has_many :variables, class_name: 'Ci::PipelineVariable'
......
...@@ -937,6 +937,15 @@ ...@@ -937,6 +937,15 @@
.col-sm-10 .col-sm-10
= f.number_field :throttle_authenticated_web_period_in_seconds, class: 'form-control' = 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
- if License.feature_available?(:external_authorization_service) - if License.feature_available?(:external_authorization_service)
= render partial: 'external_authorization_service_form', locals: { f: f } = render partial: 'external_authorization_service_form', locals: { f: f }
......
...@@ -13,13 +13,13 @@ ...@@ -13,13 +13,13 @@
.form-group .form-group
.input-group .input-group
- if current_user.can_select_namespace? - if current_user.can_select_namespace?
.input-group-addon .input-group-addon.has-tooltip{ title: root_url }
= 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 = 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 - else
.input-group-addon.static-namespace .input-group-addon.static-namespace.has-tooltip{ title: user_url(current_user.username) + '/' }
#{root_url}#{current_user.username}/ #{user_url(current_user.username)}/
= hidden_field_tag :namespace_id, value: current_user.namespace_id = hidden_field_tag :namespace_id, value: current_user.namespace_id
.form-group.col-xs-12.col-sm-6.project-path .form-group.col-xs-12.col-sm-6.project-path
= label_tag :path, 'Project name', class: 'label-light' = label_tag :path, 'Project name', class: 'label-light'
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
profile_url: url_for(params.merge(lineprofiler: 'true')) }, profile_url: url_for(params.merge(lineprofiler: 'true')) },
class: Peek.env } class: Peek.env }
#peek-view-performance-bar #peek-view-performance-bar.hidden
= render_server_response_time = render_server_response_time
%span#serverstats %span#serverstats
%ul.performance-bar %ul.performance-bar
...@@ -9,12 +9,12 @@ ...@@ -9,12 +9,12 @@
Project path Project path
.input-group .input-group
- if current_user.can_select_namespace? - if current_user.can_select_namespace?
.input-group-addon .input-group-addon.has-tooltip{ title: root_url }
= 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} = 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 - else
.input-group-addon.static-namespace .input-group-addon.static-namespace.has-tooltip{ title: user_url(current_user.username) + '/' }
#{user_url(current_user.username)}/ #{user_url(current_user.username)}/
= f.hidden_field :namespace_id, value: current_user.namespace_id = f.hidden_field :namespace_id, value: current_user.namespace_id
.form-group.project-path.col-sm-6 .form-group.project-path.col-sm-6
......
---
title: Long instance urls do not overflow anymore during project creation
merge_request: 17717
author:
type: fixed
---
title: Add query counts to profiler output
merge_request:
author:
type: other
---
title: Fix GitLab Auth0 integration signing in the wrong user
merge_request:
author:
type: security
---
title: Fixed some SSRF vulnerabilities in services, hooks and integrations
merge_request: 2337
author:
type: security
---
title: 'Remove unecessary validate: true from belongs_to :project'
merge_request:
author:
type: fixed
...@@ -219,49 +219,5 @@ Devise.setup do |config| ...@@ -219,49 +219,5 @@ Devise.setup do |config|
end end
end end
Gitlab.config.omniauth.providers.each do |provider| Gitlab::OmniauthInitializer.new(config).execute(Gitlab.config.omniauth.providers)
provider_arguments = []
%w[app_id app_secret].each do |argument|
provider_arguments << provider[argument] if provider[argument]
end
case provider['args']
when Array
# An Array from the configuration will be expanded.
provider_arguments.concat provider['args']
when Hash
# Add procs for handling SLO
if provider['name'] == 'cas3'
provider['args'][:on_single_sign_out] = lambda do |request|
ticket = request.params[:session_index]
raise "Service Ticket not found." unless Gitlab::Auth::OAuth::Session.valid?(:cas3, ticket)
Gitlab::Auth::OAuth::Session.destroy(:cas3, ticket)
true
end
end
if provider['name'] == 'authentiq'
provider['args'][:remote_sign_out_handler] = lambda do |request|
authentiq_session = request.params['sid']
if Gitlab::Auth::OAuth::Session.valid?(:authentiq, authentiq_session)
Gitlab::Auth::OAuth::Session.destroy(:authentiq, authentiq_session)
true
else
false
end
end
end
if provider['name'] == 'shibboleth'
provider['args'][:fail_with_empty_uid] = true
end
# A Hash from the configuration will be passed as is.
provider_arguments << provider['args'].symbolize_keys
end
config.omniauth provider['name'].to_sym, *provider_arguments
end
end end
class RemoveEmptyExternUidAuth0Identities < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
class Identity < ActiveRecord::Base
self.table_name = 'identities'
include EachBatch
end
def up
broken_auth0_identities.each_batch do |identity|
identity.delete_all
end
end
def broken_auth0_identities
Identity.where(provider: 'auth0', extern_uid: [nil, ''])
end
def down
end
end
...@@ -454,17 +454,19 @@ next run of the pipeline, the cache will be stored in a different location. ...@@ -454,17 +454,19 @@ next run of the pipeline, the cache will be stored in a different location.
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/41249) in GitLab 10.4. > [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/41249) in GitLab 10.4.
If you want to avoid editing `.gitlab-ci.yml`, you can easily clear the cache If you want to avoid editing `.gitlab-ci.yml`, you can easily clear the cache
via GitLab's UI. This will have an impact on all caches of your project as via GitLab's UI:
name of the cache directory will be renamed by appending an integer to it
(`-1`, `-2`, etc.):
1. Navigate to your project's **CI/CD > Pipelines** page. 1. Navigate to your project's **CI/CD > Pipelines** page
1. Click on the **Clear Runner caches** to clean up the cache. 1. Click on the **Clear Runner caches** button to clean up the cache
1. On the next push, your CI/CD job will use a new cache.
![Clear Runners cache](img/clear_runners_cache.png)
1. On the next push, your CI/CD job will use a new cache
Behind the scenes, this works by increasing a counter in the database, and the Behind the scenes, this works by increasing a counter in the database, and the
value of that counter is used to create the key for the cache. After a push, a value of that counter is used to create the key for the cache by appending an
new key is generated and the old cache is not valid anymore. integer to it: `-1`, `-2`, etc. After a push, a new key is generated and the
old cache is not valid anymore.
## Cache vs artifacts ## Cache vs artifacts
......
...@@ -1132,7 +1132,7 @@ job1: ...@@ -1132,7 +1132,7 @@ job1:
## `retry` ## `retry`
> [Introduced][ce-3442] in GitLab 9.5. > [Introduced][ce-12909] in GitLab 9.5.
`retry` allows you to configure how many times a job is going to be retried in `retry` allows you to configure how many times a job is going to be retried in
case of a failure. case of a failure.
...@@ -1688,7 +1688,7 @@ CI with various languages. ...@@ -1688,7 +1688,7 @@ CI with various languages.
[variables]: ../variables/README.md [variables]: ../variables/README.md
[ce-7983]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7983 [ce-7983]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7983
[ce-7447]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7447 [ce-7447]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7447
[ce-3442]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/3442 [ce-12909]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/12909
[schedules]: ../../user/project/pipelines/schedules.md [schedules]: ../../user/project/pipelines/schedules.md
[ee]: https://about.gitlab.com/gitlab-ee/ [ee]: https://about.gitlab.com/gitlab-ee/
[gitlab-versions]: https://about.gitlab.com/products/ [gitlab-versions]: https://about.gitlab.com/products/
...@@ -56,7 +56,8 @@ for initial settings. ...@@ -56,7 +56,8 @@ for initial settings.
"name" => "auth0", "name" => "auth0",
"args" => { client_id: 'YOUR_AUTH0_CLIENT_ID', "args" => { client_id: 'YOUR_AUTH0_CLIENT_ID',
client_secret: 'YOUR_AUTH0_CLIENT_SECRET', client_secret: 'YOUR_AUTH0_CLIENT_SECRET',
namespace: 'YOUR_AUTH0_DOMAIN' domain: 'YOUR_AUTH0_DOMAIN',
scope: 'openid profile email'
} }
} }
] ]
...@@ -69,8 +70,8 @@ for initial settings. ...@@ -69,8 +70,8 @@ for initial settings.
args: { args: {
client_id: 'YOUR_AUTH0_CLIENT_ID', client_id: 'YOUR_AUTH0_CLIENT_ID',
client_secret: 'YOUR_AUTH0_CLIENT_SECRET', client_secret: 'YOUR_AUTH0_CLIENT_SECRET',
namespace: 'YOUR_AUTH0_DOMAIN' domain: 'YOUR_AUTH0_DOMAIN',
} scope: 'openid profile email' }
} }
``` ```
......
...@@ -29,7 +29,6 @@ module Gitlab ...@@ -29,7 +29,6 @@ module Gitlab
@repository.gitaly_migrate(:wiki_write_page) do |is_enabled| @repository.gitaly_migrate(:wiki_write_page) do |is_enabled|
if is_enabled if is_enabled
gitaly_write_page(name, format, content, commit_details) gitaly_write_page(name, format, content, commit_details)
gollum_wiki.clear_cache
else else
gollum_write_page(name, format, content, commit_details) gollum_write_page(name, format, content, commit_details)
end end
...@@ -40,7 +39,6 @@ module Gitlab ...@@ -40,7 +39,6 @@ module Gitlab
@repository.gitaly_migrate(:wiki_delete_page) do |is_enabled| @repository.gitaly_migrate(:wiki_delete_page) do |is_enabled|
if is_enabled if is_enabled
gitaly_delete_page(page_path, commit_details) gitaly_delete_page(page_path, commit_details)
gollum_wiki.clear_cache
else else
gollum_delete_page(page_path, commit_details) gollum_delete_page(page_path, commit_details)
end end
...@@ -51,7 +49,6 @@ module Gitlab ...@@ -51,7 +49,6 @@ module Gitlab
@repository.gitaly_migrate(:wiki_update_page) do |is_enabled| @repository.gitaly_migrate(:wiki_update_page) do |is_enabled|
if is_enabled if is_enabled
gitaly_update_page(page_path, title, format, content, commit_details) gitaly_update_page(page_path, title, format, content, commit_details)
gollum_wiki.clear_cache
else else
gollum_update_page(page_path, title, format, content, commit_details) gollum_update_page(page_path, title, format, content, commit_details)
end end
......
...@@ -13,7 +13,7 @@ module Gitlab ...@@ -13,7 +13,7 @@ module Gitlab
end end
def call(env) def call(env)
ReadOnly::Controller.new(@app, env).call ::Gitlab::Middleware::ReadOnly::Controller.new(@app, env).call
end end
end end
end end
......
module Gitlab
class OmniauthInitializer
def initialize(devise_config)
@devise_config = devise_config
end
def execute(providers)
providers.each do |provider|
add_provider(provider['name'].to_sym, *arguments_for(provider))
end
end
private
def add_provider(*args)
@devise_config.omniauth(*args)
end
def arguments_for(provider)
provider_arguments = []
%w[app_id app_secret].each do |argument|
provider_arguments << provider[argument] if provider[argument]
end
case provider['args']
when Array
# An Array from the configuration will be expanded.
provider_arguments.concat provider['args']
when Hash
hash_arguments = provider['args'].merge(provider_defaults(provider))
# A Hash from the configuration will be passed as is.
provider_arguments << hash_arguments.symbolize_keys
end
provider_arguments
end
def provider_defaults(provider)
case provider['name']
when 'cas3'
{ on_single_sign_out: cas3_signout_handler }
when 'authentiq'
{ remote_sign_out_handler: authentiq_signout_handler }
when 'shibboleth'
{ fail_with_empty_uid: true }
else
{}
end
end
def cas3_signout_handler
lambda do |request|
ticket = request.params[:session_index]
raise "Service Ticket not found." unless Gitlab::Auth::OAuth::Session.valid?(:cas3, ticket)
Gitlab::Auth::OAuth::Session.destroy(:cas3, ticket)
true
end
end
def authentiq_signout_handler
lambda do |request|
authentiq_session = request.params['sid']
if Gitlab::Auth::OAuth::Session.valid?(:authentiq, authentiq_session)
Gitlab::Auth::OAuth::Session.destroy(:authentiq, authentiq_session)
true
else
false
end
end
end
end
end
...@@ -92,8 +92,8 @@ module Gitlab ...@@ -92,8 +92,8 @@ module Gitlab
if type && time if type && time
@load_times_by_model ||= {} @load_times_by_model ||= {}
@load_times_by_model[type] ||= 0 @load_times_by_model[type] ||= []
@load_times_by_model[type] += time.to_f @load_times_by_model[type] << time.to_f
end end
super super
...@@ -135,8 +135,12 @@ module Gitlab ...@@ -135,8 +135,12 @@ module Gitlab
def self.log_load_times_by_model(logger) def self.log_load_times_by_model(logger)
return unless logger.respond_to?(:load_times_by_model) return unless logger.respond_to?(:load_times_by_model)
logger.load_times_by_model.to_a.sort_by(&:last).reverse.each do |(model, time)| summarised_load_times = logger.load_times_by_model.to_a.map do |(model, times)|
logger.info("#{model} total: #{time.round(2)}ms") [model, times.count, times.sum]
end
summarised_load_times.sort_by(&:last).reverse.each do |(model, query_count, time)|
logger.info("#{model} total (#{query_count}): #{time.round(2)}ms")
end end
end end
end end
......
...@@ -3,73 +3,90 @@ require 'spec_helper' ...@@ -3,73 +3,90 @@ require 'spec_helper'
describe OmniauthCallbacksController do describe OmniauthCallbacksController do
include LoginHelpers include LoginHelpers
let(:user) { create(:omniauth_user, extern_uid: 'my-uid', provider: provider) } let(:user) { create(:omniauth_user, extern_uid: extern_uid, provider: provider) }
let(:provider) { :github }
before do before do
mock_auth_hash(provider.to_s, 'my-uid', user.email) mock_auth_hash(provider.to_s, extern_uid, user.email)
stub_omniauth_provider(provider, context: request) stub_omniauth_provider(provider, context: request)
end end
it 'allows sign in' do context 'github' do
post provider let(:extern_uid) { 'my-uid' }
let(:provider) { :github }
expect(request.env['warden']).to be_authenticated it 'allows sign in' do
end post provider
expect(request.env['warden']).to be_authenticated
end
shared_context 'sign_up' do shared_context 'sign_up' do
let(:user) { double(email: 'new@example.com') } let(:user) { double(email: 'new@example.com') }
before do before do
stub_omniauth_setting(block_auto_created_users: false) stub_omniauth_setting(block_auto_created_users: false)
end
end end
end
context 'sign up' do context 'sign up' do
include_context 'sign_up' include_context 'sign_up'
it 'is allowed' do it 'is allowed' do
post provider post provider
expect(request.env['warden']).to be_authenticated expect(request.env['warden']).to be_authenticated
end
end end
end
context 'when OAuth is disabled' do context 'when OAuth is disabled' do
before do before do
stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false') stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
settings = Gitlab::CurrentSettings.current_application_settings settings = Gitlab::CurrentSettings.current_application_settings
settings.update(disabled_oauth_sign_in_sources: [provider.to_s]) settings.update(disabled_oauth_sign_in_sources: [provider.to_s])
end end
it 'prevents login via POST' do it 'prevents login via POST' do
post provider post provider
expect(request.env['warden']).not_to be_authenticated expect(request.env['warden']).not_to be_authenticated
end end
it 'shows warning when attempting login' do it 'shows warning when attempting login' do
post provider post provider
expect(response).to redirect_to new_user_session_path expect(response).to redirect_to new_user_session_path
expect(flash[:alert]).to eq('Signing in using GitHub has been disabled') expect(flash[:alert]).to eq('Signing in using GitHub has been disabled')
end end
it 'allows linking the disabled provider' do it 'allows linking the disabled provider' do
user.identities.destroy_all user.identities.destroy_all
sign_in(user) sign_in(user)
expect { post provider }.to change { user.reload.identities.count }.by(1) expect { post provider }.to change { user.reload.identities.count }.by(1)
end end
context 'sign up' do context 'sign up' do
include_context 'sign_up' include_context 'sign_up'
it 'is prevented' do it 'is prevented' do
post provider post provider
expect(request.env['warden']).not_to be_authenticated expect(request.env['warden']).not_to be_authenticated
end
end end
end end
end end
context 'auth0' do
let(:extern_uid) { '' }
let(:provider) { :auth0 }
it 'does not allow sign in without extern_uid' do
post 'auth0'
expect(request.env['warden']).not_to be_authenticated
expect(response.status).to eq(302)
expect(controller).to set_flash[:alert].to('Wrong extern UID provided. Make sure Auth0 is configured correctly.')
end
end
end end
...@@ -549,6 +549,20 @@ import timeoutPromise from './helpers/set_timeout_promise_helper'; ...@@ -549,6 +549,20 @@ import timeoutPromise from './helpers/set_timeout_promise_helper';
}); });
}); });
it('should disable the submit button when comment button is clicked', (done) => {
expect($form.find('.js-comment-submit-button').is(':disabled')).toEqual(false);
mockNotesPost();
$('.js-comment-button').click();
expect($form.find('.js-comment-submit-button').is(':disabled')).toEqual(true);
setTimeout(() => {
expect($form.find('.js-comment-submit-button').is(':disabled')).toEqual(false);
done();
});
});
it('should show actual note element when new comment is done posting', (done) => { it('should show actual note element when new comment is done posting', (done) => {
mockNotesPost(); mockNotesPost();
......
...@@ -20,16 +20,8 @@ describe('detailedMetric', () => { ...@@ -20,16 +20,8 @@ describe('detailedMetric', () => {
}); });
}); });
it('does not display details', () => { it('does not render the element', () => {
expect(vm.$el.innerText).not.toContain('/'); expect(vm.$el.innerHTML).toEqual(undefined);
});
it('does not display the modal', () => {
expect(vm.$el.querySelector('.performance-bar-modal')).toBeNull();
});
it('displays the metric name', () => {
expect(vm.$el.innerText).toContain('gitaly');
}); });
}); });
......
require 'spec_helper'
describe Gitlab::OmniauthInitializer do
let(:devise_config) { class_double(Devise) }
subject { described_class.new(devise_config) }
describe '#execute' do
it 'configures providers from array' do
generic_config = { 'name' => 'generic' }
expect(devise_config).to receive(:omniauth).with(:generic)
subject.execute([generic_config])
end
it 'allows "args" array for app_id and app_secret' do
legacy_config = { 'name' => 'legacy', 'args' => %w(123 abc) }
expect(devise_config).to receive(:omniauth).with(:legacy, '123', 'abc')
subject.execute([legacy_config])
end
it 'passes app_id and app_secret as additional arguments' do
twitter_config = { 'name' => 'twitter', 'app_id' => '123', 'app_secret' => 'abc' }
expect(devise_config).to receive(:omniauth).with(:twitter, '123', 'abc')
subject.execute([twitter_config])
end
it 'passes "args" hash as symbolized hash argument' do
hash_config = { 'name' => 'hash', 'args' => { 'custom' => 'format' } }
expect(devise_config).to receive(:omniauth).with(:hash, custom: 'format')
subject.execute([hash_config])
end
it 'configures fail_with_empty_uid for shibboleth' do
shibboleth_config = { 'name' => 'shibboleth', 'args' => {} }
expect(devise_config).to receive(:omniauth).with(:shibboleth, fail_with_empty_uid: true)
subject.execute([shibboleth_config])
end
it 'configures remote_sign_out_handler proc for authentiq' do
authentiq_config = { 'name' => 'authentiq', 'args' => {} }
expect(devise_config).to receive(:omniauth).with(:authentiq, remote_sign_out_handler: an_instance_of(Proc))
subject.execute([authentiq_config])
end
it 'configures on_single_sign_out proc for cas3' do
cas3_config = { 'name' => 'cas3', 'args' => {} }
expect(devise_config).to receive(:omniauth).with(:cas3, on_single_sign_out: an_instance_of(Proc))
subject.execute([cas3_config])
end
end
end
...@@ -110,8 +110,8 @@ describe Gitlab::Profiler do ...@@ -110,8 +110,8 @@ describe Gitlab::Profiler do
custom_logger.debug('User Load (1.3ms)') custom_logger.debug('User Load (1.3ms)')
custom_logger.debug('Project Load (10.4ms)') custom_logger.debug('Project Load (10.4ms)')
expect(custom_logger.load_times_by_model).to eq('User' => 2.5, expect(custom_logger.load_times_by_model).to eq('User' => [1.2, 1.3],
'Project' => 10.4) 'Project' => [10.4])
end end
it 'logs the backtrace, ignoring lines as appropriate' do it 'logs the backtrace, ignoring lines as appropriate' do
...@@ -164,4 +164,24 @@ describe Gitlab::Profiler do ...@@ -164,4 +164,24 @@ describe Gitlab::Profiler do
end end
end end
end end
describe '.log_load_times_by_model' do
it 'logs the model, query count, and time by slowest first' do
expect(null_logger).to receive(:load_times_by_model).and_return(
'User' => [1.2, 1.3],
'Project' => [10.4]
)
expect(null_logger).to receive(:info).with('Project total (1): 10.4ms')
expect(null_logger).to receive(:info).with('User total (2): 2.5ms')
described_class.log_load_times_by_model(null_logger)
end
it 'does nothing when called with a logger that does not have load times' do
expect(null_logger).not_to receive(:info)
expect(described_class.log_load_times_by_model(null_logger)).to be_nil
end
end
end end
require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20180220150310_remove_empty_extern_uid_auth0_identities.rb')
describe RemoveEmptyExternUidAuth0Identities, :migration do
let(:identities) { table(:identities) }
before do
identities.create(provider: 'auth0', extern_uid: '')
identities.create(provider: 'auth0', extern_uid: 'valid')
identities.create(provider: 'github', extern_uid: '')
migrate!
end
it 'leaves the correct auth0 identity' do
expect(identities.where(provider: 'auth0').pluck(:extern_uid)).to eq(['valid'])
end
it 'leaves the correct github identity' do
expect(identities.where(provider: 'github').count).to eq(1)
end
end
...@@ -2,13 +2,15 @@ require 'spec_helper' ...@@ -2,13 +2,15 @@ require 'spec_helper'
describe Ci::ProcessPipelineService, '#execute' do describe Ci::ProcessPipelineService, '#execute' do
let(:user) { create(:user) } let(:user) { create(:user) }
let(:project) { create(:project) } let(:project) { create(:project, :repository) }
let(:pipeline) do let(:pipeline) do
create(:ci_empty_pipeline, ref: 'master', project: project) create(:ci_empty_pipeline, ref: 'master', project: project)
end end
before do before do
stub_ci_pipeline_to_return_yaml_file
stub_not_protect_default_branch stub_not_protect_default_branch
project.add_developer(user) project.add_developer(user)
......
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