Commit cbb6329b authored by David Kim's avatar David Kim

Restrict mirroring changes to admins only when mirroring is disabled

When admin disables mirroring from admin settings, we say only admin can
make changes to mirroring setting, but it seems that maintainers are
able to make changes currently. This commit fixes that and only admin
can make changes to project mirroring settings.
parent fb49bdbb
...@@ -67,7 +67,7 @@ class Projects::MirrorsController < Projects::ApplicationController ...@@ -67,7 +67,7 @@ class Projects::MirrorsController < Projects::ApplicationController
end end
def check_mirror_available! def check_mirror_available!
Gitlab::CurrentSettings.current_application_settings.mirror_available || current_user&.admin? render_404 unless can?(current_user, :admin_remote_mirror, project)
end end
def mirror_params_attributes def mirror_params_attributes
......
- expanded = expanded_by_default? - expanded = expanded_by_default?
- protocols = Gitlab::UrlSanitizer::ALLOWED_SCHEMES.join('|') - protocols = Gitlab::UrlSanitizer::ALLOWED_SCHEMES.join('|')
- mirror_settings_enabled = can?(current_user, :admin_remote_mirror, @project)
- mirror_settings_class = "#{'expanded' if expanded} #{'js-mirror-settings' if mirror_settings_enabled}".strip
%section.settings.project-mirror-settings.js-mirror-settings.no-animate#js-push-remote-settings{ class: ('expanded' if expanded), data: { qa_selector: 'mirroring_repositories_settings_section' } } %section.settings.project-mirror-settings.no-animate#js-push-remote-settings{ class: mirror_settings_class, data: { qa_selector: 'mirroring_repositories_settings_section' } }
.settings-header .settings-header
%h4= _('Mirroring repositories') %h4= _('Mirroring repositories')
%button.btn.js-settings-toggle %button.btn.js-settings-toggle
...@@ -11,6 +13,7 @@ ...@@ -11,6 +13,7 @@
= link_to _('Read more'), help_page_path('workflow/repository_mirroring'), target: '_blank' = link_to _('Read more'), help_page_path('workflow/repository_mirroring'), target: '_blank'
.settings-content .settings-content
- if mirror_settings_enabled
= form_for @project, url: project_mirror_path(@project), html: { class: 'gl-show-field-errors js-mirror-form', autocomplete: 'new-password', data: mirrors_form_data_attributes } do |f| = form_for @project, url: project_mirror_path(@project), html: { class: 'gl-show-field-errors js-mirror-form', autocomplete: 'new-password', data: mirrors_form_data_attributes } do |f|
.panel.panel-default .panel.panel-default
.panel-body .panel-body
...@@ -31,6 +34,11 @@ ...@@ -31,6 +34,11 @@
.panel-footer .panel-footer
= f.submit _('Mirror repository'), class: 'btn btn-success js-mirror-submit qa-mirror-repository-button', name: :update_remote_mirror = f.submit _('Mirror repository'), class: 'btn btn-success js-mirror-submit qa-mirror-repository-button', name: :update_remote_mirror
- else
.gl-alert.gl-alert-info{ role: 'alert' }
= sprite_icon('information-o', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
.gl-alert-body
= _('Mirror settings are only available to GitLab administrators.')
.panel.panel-default .panel.panel-default
.table-responsive .table-responsive
...@@ -61,8 +69,10 @@ ...@@ -61,8 +69,10 @@
- if mirror.last_error.present? - if mirror.last_error.present?
.badge.mirror-error-badge{ data: { toggle: 'tooltip', html: 'true', qa_selector: 'mirror_error_badge' }, title: html_escape(mirror.last_error.try(:strip)) }= _('Error') .badge.mirror-error-badge{ data: { toggle: 'tooltip', html: 'true', qa_selector: 'mirror_error_badge' }, title: html_escape(mirror.last_error.try(:strip)) }= _('Error')
%td %td
- if mirror_settings_enabled
.btn-group.mirror-actions-group.pull-right{ role: 'group' } .btn-group.mirror-actions-group.pull-right{ role: 'group' }
- if mirror.ssh_key_auth? - if mirror.ssh_key_auth?
= clipboard_button(text: mirror.ssh_public_key, class: 'btn btn-default', title: _('Copy SSH public key'), qa_selector: 'copy_public_key_button') = clipboard_button(text: mirror.ssh_public_key, class: 'btn btn-default', title: _('Copy SSH public key'), qa_selector: 'copy_public_key_button')
= render 'shared/remote_mirror_update_button', remote_mirror: mirror = render 'shared/remote_mirror_update_button', remote_mirror: mirror
%button.js-delete-mirror.qa-delete-mirror.rspec-delete-mirror.btn.btn-danger{ type: 'button', data: { mirror_id: mirror.id, toggle: 'tooltip', container: 'body' }, title: _('Remove') }= icon('trash-o') %button.js-delete-mirror.qa-delete-mirror.rspec-delete-mirror.btn.btn-danger{ type: 'button', data: { mirror_id: mirror.id, toggle: 'tooltip', container: 'body' }, title: _('Remove') }= icon('trash-o')
---
title: Restrict mirroring changes to admins only when mirroring is disabled
merge_request:
author:
type: security
...@@ -12699,6 +12699,9 @@ msgstr "" ...@@ -12699,6 +12699,9 @@ msgstr ""
msgid "Mirror repository" msgid "Mirror repository"
msgstr "" msgstr ""
msgid "Mirror settings are only available to GitLab administrators."
msgstr ""
msgid "Mirror user" msgid "Mirror user"
msgstr "" msgstr ""
......
...@@ -5,6 +5,72 @@ require 'spec_helper' ...@@ -5,6 +5,72 @@ require 'spec_helper'
describe Projects::MirrorsController do describe Projects::MirrorsController do
include ReactiveCachingHelpers include ReactiveCachingHelpers
shared_examples 'only admin is allowed when mirroring is disabled' do
let(:subject_action) { raise 'subject_action is required' }
let(:user) { project.owner }
let(:project_settings_path) { project_settings_repository_path(project, anchor: 'js-push-remote-settings') }
context 'when project mirroring is enabled' do
it 'allows requests from a maintainer' do
sign_in(user)
subject_action
expect(response).to redirect_to(project_settings_path)
end
it 'allows requests from an admin user' do
user.update!(admin: true)
sign_in(user)
subject_action
expect(response).to redirect_to(project_settings_path)
end
end
context 'when project mirroring is disabled' do
before do
stub_application_setting(mirror_available: false)
end
it 'disallows requests from a maintainer' do
sign_in(user)
subject_action
expect(response).to have_gitlab_http_status(:not_found)
end
it 'allows requests from an admin user' do
user.update!(admin: true)
sign_in(user)
subject_action
expect(response).to redirect_to(project_settings_path)
end
end
end
describe 'Access control' do
let(:project) { create(:project, :repository) }
describe '#update' do
include_examples 'only admin is allowed when mirroring is disabled' do
let(:subject_action) do
do_put(project, remote_mirrors_attributes: { '0' => { 'enabled' => 1, 'url' => 'http://foo.com' } })
end
end
end
describe '#update_now' do
include_examples 'only admin is allowed when mirroring is disabled' do
let(:options) { { namespace_id: project.namespace, project_id: project } }
let(:subject_action) do
get :update_now, params: options.merge(sync_remote: true)
end
end
end
end
describe 'setting up a remote mirror' do describe 'setting up a remote mirror' do
let_it_be(:project) { create(:project, :repository) } let_it_be(:project) { create(:project, :repository) }
......
...@@ -26,11 +26,7 @@ describe 'Projects > Settings > Repository settings' do ...@@ -26,11 +26,7 @@ describe 'Projects > Settings > Repository settings' do
let(:role) { :maintainer } let(:role) { :maintainer }
context 'remote mirror settings' do context 'remote mirror settings' do
let(:user2) { create(:user) }
before do before do
project.add_maintainer(user2)
visit project_settings_repository_path(project) visit project_settings_repository_path(project)
end end
...@@ -90,6 +86,18 @@ describe 'Projects > Settings > Repository settings' do ...@@ -90,6 +86,18 @@ describe 'Projects > Settings > Repository settings' do
expect(page).to have_selector('[title="Copy SSH public key"]') expect(page).to have_selector('[title="Copy SSH public key"]')
end end
context 'when project mirroring is disabled' do
before do
stub_application_setting(mirror_available: false)
visit project_settings_repository_path(project)
end
it 'hides remote mirror settings' do
expect(page.find('.project-mirror-settings')).not_to have_selector('form')
expect(page).to have_content('Mirror settings are only available to GitLab administrators.')
end
end
def select_direction(direction = 'push') def select_direction(direction = 'push')
direction_select = find('#mirror_direction') direction_select = find('#mirror_direction')
...@@ -154,4 +162,31 @@ describe 'Projects > Settings > Repository settings' do ...@@ -154,4 +162,31 @@ describe 'Projects > Settings > Repository settings' do
expect(mirror).not_to have_selector('.rspec-update-now-button') expect(mirror).not_to have_selector('.rspec-update-now-button')
end end
end end
context 'for admin' do
shared_examples_for 'shows mirror settings' do
it 'shows mirror settings' do
expect(page.find('.project-mirror-settings')).to have_selector('form')
expect(page).not_to have_content('Changing mirroring setting is disabled for non-admin users.')
end
end
before do
stub_application_setting(mirror_available: mirror_available)
user.update!(admin: true)
visit project_settings_repository_path(project)
end
context 'when project mirroring is enabled' do
let(:mirror_available) { true }
include_examples 'shows mirror settings'
end
context 'when project mirroring is disabled' do
let(:mirror_available) { false }
include_examples 'shows mirror settings'
end
end
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