Commit d3c29eae authored by GitLab Bot's avatar GitLab Bot

Add latest changes from gitlab-org/gitlab@master

parent ad4dbe36
......@@ -2,29 +2,6 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
## 12.8.3
### Fixed (8 changes)
- Fix Group Import API file upload when object storage is disabled. !25715
- Fix Web IDE fork modal showing no text. !25842
- Fixed regression when URL was encoded in a loop. !25849
- Fixed repository browsing for folders with non-ascii characters. !25877
- Fix search for Sentry error list. !26129
- Send credentials with GraphQL fetch requests. !26386
- Show CI status in project dashboards. !26403
- Rescue invalid URLs during badge retrieval in asset proxy. !26524
### Performance (2 changes)
- Disable Marginalia line backtrace in production. !26199
- Remove unnecessary Redis deletes for broadcast messages. !26541
### Other (1 change, 1 of them is from the community)
- Fix fixtures for Error Tracking Web UI. !26233 (Takuya Noguchi)
## 12.8.2
### Security (17 changes)
......
......@@ -179,18 +179,19 @@ export default {
<div v-if="errorMessage" class="diff-viewer">
<div class="nothing-here-block" v-html="errorMessage"></div>
</div>
<div v-else-if="isCollapsed" class="nothing-here-block diff-collapsed">
{{ __('This diff is collapsed.') }}
<a class="click-to-expand js-click-to-expand" href="#" @click.prevent="handleToggle">{{
__('Click to expand it.')
}}</a>
</div>
<diff-content
v-else
:class="{ hidden: isCollapsed || isFileTooLarge }"
:diff-file="file"
:help-page-path="helpPagePath"
/>
<template v-else>
<div v-show="isCollapsed" class="nothing-here-block diff-collapsed">
{{ __('This diff is collapsed.') }}
<a class="click-to-expand js-click-to-expand" href="#" @click.prevent="handleToggle">{{
__('Click to expand it.')
}}</a>
</div>
<diff-content
v-show="!isCollapsed && !isFileTooLarge"
:diff-file="file"
:help-page-path="helpPagePath"
/>
</template>
</div>
</template>
</div>
......
......@@ -16,10 +16,18 @@ module AuthHelper
Gitlab::Auth.omniauth_enabled?
end
def provider_has_icon?(name)
def provider_has_custom_icon?(name)
icon_for_provider(name.to_s)
end
def provider_has_builtin_icon?(name)
PROVIDERS_WITH_ICONS.include?(name.to_s)
end
def provider_has_icon?(name)
provider_has_builtin_icon?(name) || provider_has_custom_icon?(name)
end
def qa_class_for_provider(provider)
{
saml: 'qa-saml-login-button',
......@@ -35,6 +43,10 @@ module AuthHelper
Gitlab::Auth::OAuth::Provider.label_for(name)
end
def icon_for_provider(name)
Gitlab::Auth::OAuth::Provider.icon_for(name)
end
def form_based_provider_priority
['crowd', /^ldap/, 'kerberos']
end
......@@ -109,7 +121,9 @@ module AuthHelper
def provider_image_tag(provider, size = 64)
label = label_for_provider(provider)
if provider_has_icon?(provider)
if provider_has_custom_icon?(provider)
image_tag(icon_for_provider(provider), alt: label, title: "Sign in with #{label}")
elsif provider_has_builtin_icon?(provider)
file_name = "#{provider.to_s.split('_').first}_#{size}.png"
image_tag("auth_buttons/#{file_name}", alt: label, title: "Sign in with #{label}")
......
......@@ -88,7 +88,9 @@ class PrometheusService < MonitoringService
return false if template?
return false unless project
project.all_clusters.enabled.any? { |cluster| cluster.application_prometheus_available? }
project.all_clusters.enabled.eager_load(:application_prometheus).any? do |cluster|
cluster.application_prometheus&.available?
end
end
def allow_local_api_url?
......
......@@ -98,6 +98,7 @@ module Projects
setup_authorizations
current_user.invalidate_personal_projects_count
create_prometheus_service
create_readme if @initialize_with_readme
end
......@@ -169,6 +170,20 @@ module Projects
end
# rubocop: enable CodeReuse/ActiveRecord
def create_prometheus_service
service = @project.find_or_initialize_service(::PrometheusService.to_param)
if service.prometheus_available?
service.save!
else
@project.prometheus_service = nil
end
rescue ActiveRecord::RecordInvalid => e
Gitlab::ErrorTracking.track_exception(e, extra: { project_id: project.id })
@project.prometheus_service = nil
end
def set_project_name_from_path
# Set project name from path
if @project.name.present? && @project.path.present?
......
---
title: Fixed regression when URL was encoded in a loop
merge_request: 25849
author:
type: fixed
---
title: Fix Web IDE fork modal showing no text
merge_request: 25842
author:
type: fixed
---
title: Fix fixtures for Error Tracking Web UI
merge_request: 26233
author: Takuya Noguchi
type: other
---
title: Optional custom icon in the OmniAuth login labels
merge_request: 25744
author: Tobias Wawryniuk, Luca Leonardo Scorcia
type: added
---
title: Fix Group Import API file upload when object storage is disabled
merge_request: 25715
author:
type: fixed
---
title: Improved MR toggle file performance by hiding instead of removing
merge_request: 26181
author:
type: performance
---
title: Fix search for Sentry error list
merge_request: 26129
author:
type: fixed
---
title: Activate Prometheus integration service for newly created project if this project
has access to shared Prometheus application.
merge_request: 24676
author:
type: fixed
---
title: Fixed repository browsing for folders with non-ascii characters
merge_request: 25877
author:
type: fixed
---
title: Show CI status in project dashboards
merge_request: 26403
author:
type: fixed
---
title: Disable Marginalia line backtrace in production
merge_request: 26199
author:
type: performance
---
title: Remove unnecessary Redis deletes for broadcast messages
merge_request: 26541
author:
type: performance
---
title: Rescue invalid URLs during badge retrieval in asset proxy
merge_request: 26524
author:
type: fixed
---
title: Send credentials with GraphQL fetch requests
merge_request: 26386
author:
type: fixed
......@@ -34,6 +34,7 @@ The OpenID Connect will provide you with a client details and secret for you to
gitlab_rails['omniauth_providers'] = [
{ 'name' => 'openid_connect',
'label' => '<your_oidc_label>',
'icon' => '<custom_provider_icon>',
'args' => {
'name' => 'openid_connect',
'scope' => ['openid','profile'],
......@@ -58,6 +59,7 @@ The OpenID Connect will provide you with a client details and secret for you to
```yaml
- { name: 'openid_connect',
label: '<your_oidc_label>',
icon: '<custom_provider_icon>',
args: {
name: 'openid_connect',
scope: ['openid','profile'],
......@@ -82,6 +84,8 @@ The OpenID Connect will provide you with a client details and secret for you to
1. For the configuration above, change the values for the provider to match your OpenID Connect client setup. Use the following as a guide:
- `<your_oidc_label>` is the label that will be displayed on the login page.
- `<custom_provider_icon>` (optional) is the icon that will be displayed on the login page. Icons for the major social login platforms are built-in into GitLab,
but can be overridden by specifying this parameter. Both local paths and absolute URLs are accepted.
- `<your_oidc_url>` (optional) is the URL that points to the OpenID Connect provider. For example, `https://example.com/auth/realms/your-realm`.
If this value is not provided, the URL is constructed from the `client_options` in the following format: `<client_options.scheme>://<client_options.host>:<client_options.port>`.
- If `discovery` is set to `true`, the OpenID Connect provider will try to auto discover the client options using `<your_oidc_url>/.well-known/openid-configuration`. Defaults to `false`.
......
......@@ -484,6 +484,7 @@ Parameters:
| `name` | string | yes | The name of the group. |
| `path` | string | yes | The path of the group. |
| `description` | string | no | The group's description. |
| `membership_lock` | boolean | no | **(STARTER)** Prevent adding new members to project membership within this group. |
| `visibility` | string | no | The group's visibility. Can be `private`, `internal`, or `public`. |
| `share_with_group_lock` | boolean | no | Prevent sharing a project with another group within this group. |
| `require_two_factor_authentication` | boolean | no | Require all users in this group to setup Two-factor authentication. |
......
# Vuex
To manage the state of an application you should use [Vuex][vuex-docs].
When there's a clear benefit to separating state management from components (e.g. due to state complexity) we recommend using [Vuex][vuex-docs] over any other Flux pattern. Otherwise, feel free to manage state within the components.
Vuex should be strongly considered when:
- You expect multiple parts of the application to react to state changes
- There's a need to share data between multiple components
- There are complex interactions with Backend, e.g. multiple API calls
- The app involves interacting with backend via both traditional REST API and GraphQL (especially when moving the REST API over to GraphQL is a pending backend task)
_Note:_ All of the below is explained in more detail in the official [Vuex documentation][vuex-docs].
......
......@@ -177,6 +177,7 @@ module API
use :create_params
end
post do
Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab/issues/21139')
attrs = declared_params(include_missing: false)
attrs = translate_params_for_compatibility(attrs)
filter_attributes_using_license!(attrs)
......@@ -209,6 +210,7 @@ module API
end
# rubocop: disable CodeReuse/ActiveRecord
post "user/:user_id" do
Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab/issues/21139')
authenticated_as_admin!
user = User.find_by(id: params.delete(:user_id))
not_found!('User') unless user
......
......@@ -75,6 +75,12 @@ module Gitlab
config = config_for(name)
(config && config['label']) || LABELS[name] || name.titleize
end
def self.icon_for(name)
name = name.to_s
config = config_for(name)
config && config['icon']
end
end
end
end
......
......@@ -141,6 +141,20 @@ module Gitlab
# kwargs.merge(deadline: Time.now + 10)
# end
#
# The optional remote_storage keyword argument is used to enable
# inter-gitaly calls. Say you have an RPC that needs to pull data from
# one repository to another. For example, to fetch a branch from a
# (non-deduplicated) fork into the fork parent. In that case you would
# send an RPC call to the Gitaly server hosting the fork parent, and in
# the request, you would tell that Gitaly server to pull Git data from
# the fork. How does that Gitaly server connect to the Gitaly server the
# forked repo lives on? This is the problem `remote_storage:` solves: it
# adds address and authentication information to the call, as gRPC
# metadata (under the `gitaly-servers` header). The request would say
# "pull from repo X on gitaly-2". In the Ruby code you pass
# `remote_storage: 'gitaly-2'`. And then the metadata would say
# "gitaly-2 is at network address tcp://10.0.1.2:8075".
#
def self.call(storage, service, rpc, request, remote_storage: nil, timeout: default_timeout, &block)
self.measure_timings(service, rpc, request) do
self.execute(storage, service, rpc, request, remote_storage: remote_storage, timeout: timeout, &block)
......
......@@ -153,16 +153,6 @@ describe Projects::ServicesController do
expect(flash[:notice]).to eq 'Jira settings saved, but not activated.'
end
end
context 'when activating Jira service from a template' do
let(:service) do
create(:jira_service, project: project, template: true)
end
it 'activate Jira service from template' do
expect(flash[:notice]).to eq 'Jira activated.'
end
end
end
describe 'as JSON' do
......
......@@ -16,6 +16,8 @@ describe 'User manages subscription', :js do
it 'toggles subscription' do
page.within('.js-issuable-subscribe-button') do
wait_for_requests
expect(page).to have_css 'button:not(.is-checked)'
find('button:not(.is-checked)').click
......
......@@ -154,4 +154,34 @@ describe AuthHelper do
expect(helper.unlink_provider_allowed?(provider)).to eq 'policy_unlink_result'
end
end
describe '#provider_has_icon?' do
it 'returns true for defined providers' do
expect(helper.provider_has_icon?(described_class::PROVIDERS_WITH_ICONS.sample)).to eq true
end
it 'returns false for undefined providers' do
expect(helper.provider_has_icon?('test')).to be_falsey
end
context 'when provider is defined by config' do
before do
allow(Gitlab::Auth::OAuth::Provider).to receive(:icon_for).with('test').and_return('icon')
end
it 'returns true' do
expect(helper.provider_has_icon?('test')).to be_truthy
end
end
context 'when provider is not defined by config' do
before do
allow(Gitlab::Auth::OAuth::Provider).to receive(:icon_for).with('test').and_return(nil)
end
it 'returns true' do
expect(helper.provider_has_icon?('test')).to be_falsey
end
end
end
end
......@@ -23,6 +23,9 @@ describe('DiffFile', () => {
vm.$destroy();
});
const findDiffContent = () => vm.$el.querySelector('.diff-content');
const isVisible = el => el.style.display !== 'none';
describe('template', () => {
it('should render component with file header, file content components', done => {
const el = vm.$el;
......@@ -69,13 +72,13 @@ describe('DiffFile', () => {
describe('collapsed', () => {
it('should not have file content', done => {
expect(vm.$el.querySelectorAll('.diff-content').length).toEqual(1);
expect(isVisible(findDiffContent())).toBe(true);
expect(vm.isCollapsed).toEqual(false);
vm.isCollapsed = true;
vm.file.renderIt = true;
vm.$nextTick(() => {
expect(vm.$el.querySelectorAll('.diff-content').length).toEqual(0);
expect(isVisible(findDiffContent())).toBe(false);
done();
});
......
......@@ -176,6 +176,15 @@ describe PrometheusService, :use_clean_rails_memory_store_caching do
it 'returns true' do
expect(service.prometheus_available?).to be(true)
end
it 'avoids N+1 queries' do
service
5.times do |i|
other_cluster = create(:cluster_for_group, :with_installed_helm, groups: [group], environment_scope: i)
create(:clusters_applications_prometheus, :installing, cluster: other_cluster)
end
expect { service.prometheus_available? }.not_to exceed_query_limit(1)
end
end
context 'cluster belongs to gitlab instance' do
......
......@@ -344,7 +344,7 @@ describe Projects::CreateService, '#execute' do
context 'when there is an active service template' do
before do
create(:service, project: nil, template: true, active: true)
create(:prometheus_service, project: nil, template: true, active: true)
end
it 'creates a service from this template' do
......@@ -394,6 +394,67 @@ describe Projects::CreateService, '#execute' do
expect(rugged.config['gitlab.fullpath']).to eq project.full_path
end
context 'when project has access to shared service' do
context 'Prometheus application is shared via group cluster' do
let(:cluster) { create(:cluster, :group, groups: [group]) }
let(:group) do
create(:group).tap do |group|
group.add_owner(user)
end
end
before do
create(:clusters_applications_prometheus, :installed, cluster: cluster)
end
it 'creates PrometheusService record', :aggregate_failures do
project = create_project(user, opts.merge!(namespace_id: group.id))
service = project.prometheus_service
expect(service.active).to be true
expect(service.manual_configuration?).to be false
expect(service.persisted?).to be true
end
end
context 'Prometheus application is shared via instance cluster' do
let(:cluster) { create(:cluster, :instance) }
before do
create(:clusters_applications_prometheus, :installed, cluster: cluster)
end
it 'creates PrometheusService record', :aggregate_failures do
project = create_project(user, opts)
service = project.prometheus_service
expect(service.active).to be true
expect(service.manual_configuration?).to be false
expect(service.persisted?).to be true
end
it 'cleans invalid record and logs warning', :aggregate_failures do
invalid_service_record = build(:prometheus_service, properties: { api_url: nil, manual_configuration: true }.to_json)
allow_next_instance_of(Project) do |instance|
allow(instance).to receive(:build_prometheus_service).and_return(invalid_service_record)
end
expect(Gitlab::ErrorTracking).to receive(:track_exception).with(an_instance_of(ActiveRecord::RecordInvalid), include(extra: { project_id: a_kind_of(Integer) }))
project = create_project(user, opts)
expect(project.prometheus_service).to be_nil
end
end
context 'shared Prometheus application is not available' do
it 'does not persist PrometheusService record', :aggregate_failures do
project = create_project(user, opts)
expect(project.prometheus_service).to be_nil
end
end
end
context 'with external authorization enabled' do
before do
enable_external_authorization_service_check
......
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