From f4e16b355c03368a758ea00f0ce42e656a22abde Mon Sep 17 00:00:00 2001 From: Luke Duncalfe Date: Fri, 22 Sep 2023 14:01:57 +1200 Subject: [PATCH] Allow actor override when Direct Transfer disabled This change allows an instance to selectively enable the Direct Transfer feature when it has been globally disabled. To override the globally disabled setting, the ops flag should be enabled for: - On the target instance: The user conducting the import - On the source instance: The user who owns the PAT used to connect the source instance to the target when setting up the transfer Changelog: added --- .../ops/override_bulk_import_disabled.yml | 8 ++++ lib/api/bulk_imports.rb | 3 +- lib/api/group_export.rb | 3 +- lib/api/project_export.rb | 3 +- spec/requests/api/bulk_imports_spec.rb | 32 ++++++++++++---- spec/requests/api/group_export_spec.rb | 21 +++++++++- spec/requests/api/project_export_spec.rb | 38 ++++++++++++++++--- 7 files changed, 91 insertions(+), 17 deletions(-) create mode 100644 config/feature_flags/ops/override_bulk_import_disabled.yml diff --git a/config/feature_flags/ops/override_bulk_import_disabled.yml b/config/feature_flags/ops/override_bulk_import_disabled.yml new file mode 100644 index 00000000000000..057170a30ad8a7 --- /dev/null +++ b/config/feature_flags/ops/override_bulk_import_disabled.yml @@ -0,0 +1,8 @@ +--- +name: override_bulk_import_disabled +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/132431 +rollout_issue_url: +milestone: '16.5' +type: ops +group: group::import and integrate +default_enabled: false diff --git a/lib/api/bulk_imports.rb b/lib/api/bulk_imports.rb index b4ace6cd6bcd27..9bcc16cf211dd7 100644 --- a/lib/api/bulk_imports.rb +++ b/lib/api/bulk_imports.rb @@ -33,7 +33,8 @@ def bulk_import_entity end before do - not_found! unless Gitlab::CurrentSettings.bulk_import_enabled? + not_found! unless Gitlab::CurrentSettings.bulk_import_enabled? || + Feature.enabled?(:override_bulk_import_disabled, current_user, type: :ops) authenticate! end diff --git a/lib/api/group_export.rb b/lib/api/group_export.rb index 4cac707ff661cc..819cc4652f6c1b 100644 --- a/lib/api/group_export.rb +++ b/lib/api/group_export.rb @@ -66,7 +66,8 @@ class GroupExport < ::API::Base resource do before do - not_found! unless Gitlab::CurrentSettings.bulk_import_enabled? + not_found! unless Gitlab::CurrentSettings.bulk_import_enabled? || + Feature.enabled?(:override_bulk_import_disabled, current_user, type: :ops) end desc 'Start relations export' do diff --git a/lib/api/project_export.rb b/lib/api/project_export.rb index 7467b8e564e1fe..25848d91550bed 100644 --- a/lib/api/project_export.rb +++ b/lib/api/project_export.rb @@ -110,7 +110,8 @@ class ProjectExport < ::API::Base resource do before do - not_found! unless Gitlab::CurrentSettings.bulk_import_enabled? + not_found! unless Gitlab::CurrentSettings.bulk_import_enabled? || + Feature.enabled?(:override_bulk_import_disabled, current_user, type: :ops) authorize_admin_project end diff --git a/spec/requests/api/bulk_imports_spec.rb b/spec/requests/api/bulk_imports_spec.rb index d9eed0737b2617..d3d4a723616452 100644 --- a/spec/requests/api/bulk_imports_spec.rb +++ b/spec/requests/api/bulk_imports_spec.rb @@ -18,8 +18,26 @@ end shared_examples 'disabled feature' do - it 'returns 404' do + before do stub_application_setting(bulk_import_enabled: false) + stub_feature_flags(override_bulk_import_disabled: false) + end + + it_behaves_like '404 response' do + let(:message) { '404 Not Found' } + end + + it 'enables the feature when override flag is enabled for the user' do + stub_feature_flags(override_bulk_import_disabled: user) + + request + + expect(response).not_to have_gitlab_http_status(:not_found) + end + + it 'does not enable the feature when override flag is enabled for another user' do + other_user = create(:user) + stub_feature_flags(override_bulk_import_disabled: other_user) request @@ -71,7 +89,7 @@ end end - include_examples 'disabled feature' + it_behaves_like 'disabled feature' end describe 'POST /bulk_imports' do @@ -328,7 +346,7 @@ end end - include_examples 'disabled feature' + it_behaves_like 'disabled feature' context 'when request exceeds rate limits' do it 'prevents user from starting a new migration' do @@ -352,7 +370,7 @@ expect(json_response.pluck('id')).to contain_exactly(entity_1.id, entity_2.id, entity_3.id) end - include_examples 'disabled feature' + it_behaves_like 'disabled feature' end describe 'GET /bulk_imports/:id' do @@ -365,7 +383,7 @@ expect(json_response['id']).to eq(import_1.id) end - include_examples 'disabled feature' + it_behaves_like 'disabled feature' end describe 'GET /bulk_imports/:id/entities' do @@ -379,7 +397,7 @@ expect(json_response.first['failures'].first['exception_class']).to eq(failure_3.exception_class) end - include_examples 'disabled feature' + it_behaves_like 'disabled feature' end describe 'GET /bulk_imports/:id/entities/:entity_id' do @@ -392,7 +410,7 @@ expect(json_response['id']).to eq(entity_2.id) end - include_examples 'disabled feature' + it_behaves_like 'disabled feature' end context 'when user is unauthenticated' do diff --git a/spec/requests/api/group_export_spec.rb b/spec/requests/api/group_export_spec.rb index ddee2081bcf42c..d0f7c000544af0 100644 --- a/spec/requests/api/group_export_spec.rb +++ b/spec/requests/api/group_export_spec.rb @@ -325,13 +325,32 @@ end context 'when bulk import is disabled' do + subject(:request) { post api(path, user) } + before do stub_application_setting(bulk_import_enabled: false) + stub_feature_flags(override_bulk_import_disabled: false) end it_behaves_like '404 response' do let(:message) { '404 Not Found' } - let(:request) { post api(path, user) } + end + + it 'enables the feature when override flag is enabled for the user' do + stub_feature_flags(override_bulk_import_disabled: user) + + request + + expect(response).to have_gitlab_http_status(:accepted) + end + + it 'does not enable the feature when override flag is enabled for another user' do + other_user = create(:user) + stub_feature_flags(override_bulk_import_disabled: other_user) + + request + + expect(response).to have_gitlab_http_status(:not_found) end end end diff --git a/spec/requests/api/project_export_spec.rb b/spec/requests/api/project_export_spec.rb index 8a47eb2dae1974..22729e068da954 100644 --- a/spec/requests/api/project_export_spec.rb +++ b/spec/requests/api/project_export_spec.rb @@ -704,37 +704,63 @@ context 'with bulk_import is disabled' do before do stub_application_setting(bulk_import_enabled: false) + stub_feature_flags(override_bulk_import_disabled: false) + end + + shared_examples 'flag override' do |expected_http_status:| + it 'enables the feature when override flag is enabled for the user' do + stub_feature_flags(override_bulk_import_disabled: user) + + request + + expect(response).to have_gitlab_http_status(expected_http_status) + end + + it 'does not enable the feature when override flag is enabled for another user' do + other_user = create(:user) + stub_feature_flags(override_bulk_import_disabled: other_user) + + request + + expect(response).to have_gitlab_http_status(:not_found) + end end describe 'POST /projects/:id/export_relations' do + subject(:request) { post api(path, user) } + it_behaves_like '404 response' do let(:message) { '404 Not Found' } - - subject(:request) { post api(path, user) } end + + it_behaves_like 'flag override', expected_http_status: :accepted end describe 'GET /projects/:id/export_relations/download' do let_it_be(:export) { create(:bulk_import_export, project: project, relation: 'labels') } let_it_be(:upload) { create(:bulk_import_export_upload, export: export) } + subject(:request) { get api(download_path, user) } + before do upload.update!(export_file: fixture_file_upload('spec/fixtures/bulk_imports/gz/labels.ndjson.gz')) end it_behaves_like '404 response' do let(:message) { '404 Not Found' } - - subject(:request) { get api(download_path, user) } end + + it_behaves_like 'flag override', expected_http_status: :ok end describe 'GET /projects/:id/export_relations/status' do + subject(:request) { get api(status_path, user) } + it_behaves_like '404 response' do let(:message) { '404 Not Found' } - - subject(:request) { get api(status_path, user) } end + + it_behaves_like 'flag override', expected_http_status: :ok end end end -- GitLab