Commit 52d10e1d authored by Imre Farkas's avatar Imre Farkas

ImportExport::ExportService to require admin_project permission

It only requires admin_project for actual exports. Creating project from
template also uses ImportExport::ExportService but users usually do not
have admin_project on the template source and it should not be required.
parent 4ac2a641
......@@ -2339,6 +2339,10 @@ class Project < ApplicationRecord
end
end
def template_source?
false
end
private
def closest_namespace_setting(name)
......
......@@ -4,6 +4,12 @@ module Projects
module ImportExport
class ExportService < BaseService
def execute(after_export_strategy = nil, options = {})
unless project.template_source? || can?(current_user, :admin_project, project)
raise ::Gitlab::ImportExport::Error.new(
"User with ID: %s does not have permission to Project %s with ID: %s." %
[current_user.id, project.name, project.id])
end
@shared = project.import_export_shared
save_all!
......
---
title: ImportExport::ExportService to require admin_project permission
merge_request:
author:
type: security
......@@ -728,6 +728,13 @@ module EE
strong_memoize(:license_compliance) { SCA::LicenseCompliance.new(self) }
end
override :template_source?
def template_source?
return true if namespace_id == ::Gitlab::CurrentSettings.current_application_settings.custom_project_templates_group_id
::Project.with_groups_level_repos_templates.exists?(id)
end
private
def set_override_pull_mirror_available
......
......@@ -2417,4 +2417,36 @@ describe Project do
project.expire_caches_before_rename('foo')
end
end
describe '#template_source?' do
let_it_be(:group) { create(:group, :private) }
let_it_be(:subgroup) { create(:group, :private, parent: group) }
let_it_be(:project_template) { create(:project, group: subgroup) }
context 'when project is not template source' do
it 'returns false' do
expect(project.template_source?).to be_falsey
end
end
context 'instance-level custom project templates' do
before do
stub_ee_application_setting(custom_project_templates_group_id: subgroup.id)
end
it 'returns true' do
expect(project_template.template_source?).to be_truthy
end
end
context 'group-level custom project templates' do
before do
group.update(custom_project_templates_group_id: subgroup.id)
end
it 'returns true' do
expect(project_template.template_source?).to be_truthy
end
end
end
end
......@@ -5,15 +5,55 @@ require 'spec_helper'
describe Projects::ImportExport::ExportService do
describe '#execute' do
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project) }
let(:shared) { project.import_export_shared }
let(:service) { described_class.new(project, user) }
let!(:after_export_strategy) { Gitlab::ImportExport::AfterExportStrategies::DownloadNotificationStrategy.new }
it 'saves the design repo' do
expect(Gitlab::ImportExport::DesignRepoSaver).to receive(:new).and_call_original
context 'user can admin project' do
let_it_be(:project) { create(:project) }
let(:shared) { project.import_export_shared }
service.execute
subject { described_class.new(project, user).execute }
before do
project.add_maintainer(user)
end
it 'saves the design repo' do
expect(Gitlab::ImportExport::DesignRepoSaver).to receive(:new).and_call_original
subject
end
end
context 'project templates' do
let_it_be(:group) { create(:group, :private) }
let_it_be(:subgroup) { create(:group, :private, parent: group) }
let_it_be(:project_template) { create(:project, group: subgroup) }
let(:shared) { project_template.import_export_shared }
subject { described_class.new(project_template, user).execute }
context 'instance-level custom project templates' do
before do
stub_ee_application_setting(custom_project_templates_group_id: subgroup.id)
end
it 'succeeds' do
expect(Gitlab::ImportExport::Saver).to receive(:save).with(exportable: project_template, shared: shared)
subject
end
end
context 'group-level custom project templates' do
before do
group.update(custom_project_templates_group_id: subgroup.id)
end
it 'succeeds' do
expect(Gitlab::ImportExport::Saver).to receive(:save).with(exportable: project_template, shared: shared)
subject
end
end
end
end
end
......@@ -10,6 +10,10 @@ describe Projects::ImportExport::ExportService do
let(:service) { described_class.new(project, user) }
let!(:after_export_strategy) { Gitlab::ImportExport::AfterExportStrategies::DownloadNotificationStrategy.new }
before do
project.add_maintainer(user)
end
it 'saves the version' do
expect(Gitlab::ImportExport::VersionSaver).to receive(:new).and_call_original
......@@ -133,5 +137,18 @@ describe Projects::ImportExport::ExportService do
expect(service).not_to receive(:execute_after_export_action)
end
end
context 'when user does not have admin_project permission' do
let!(:another_user) { create(:user) }
subject(:service) { described_class.new(project, another_user) }
it 'fails' do
expected_message =
"User with ID: %s does not have permission to Project %s with ID: %s." %
[another_user.id, project.name, project.id]
expect { service.execute }.to raise_error(Gitlab::ImportExport::Error).with_message(expected_message)
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