diff --git a/ee/app/controllers/ee/admin/application_settings_controller.rb b/ee/app/controllers/ee/admin/application_settings_controller.rb index 813c830b8494edcc5770c7b4b75640de5806512e..baae7810e9d305bead6d134f8c7aeb19cb42984c 100644 --- a/ee/app/controllers/ee/admin/application_settings_controller.rb +++ b/ee/app/controllers/ee/admin/application_settings_controller.rb @@ -176,10 +176,6 @@ def visible_application_setting_attributes attrs << :make_profile_private end - if promotion_management_available? - attrs << :enable_member_promotion_management - end - attrs << :new_user_signups_cap attrs << :namespace_storage_forks_cost_factor diff --git a/ee/app/helpers/ee/application_settings_helper.rb b/ee/app/helpers/ee/application_settings_helper.rb index edba8b35bc237f39b5cfcbeaeadf4dfc7723df0f..4f0903f7b43a5bbee9fc8e6dbf32055a863a6957 100644 --- a/ee/app/helpers/ee/application_settings_helper.rb +++ b/ee/app/helpers/ee/application_settings_helper.rb @@ -87,6 +87,7 @@ def visible_attributes :scan_execution_policies_action_limit ].tap do |settings| settings.concat(identity_verification_attributes) + settings.concat(enable_promotion_management_attributes) end end @@ -314,5 +315,11 @@ def identity_verification_attributes telesign_customer_xid ] end + + def enable_promotion_management_attributes + return [] if ::Gitlab::Saas.feature_available?(:gitlab_com_subscriptions) + + %i[enable_member_promotion_management] + end end end diff --git a/ee/app/services/ee/application_settings/update_service.rb b/ee/app/services/ee/application_settings/update_service.rb index 810fccb79185265c94379104a30c995dfbc789a1..8fd53b2d3316fc303d19e4c71f8544a5b1140bbb 100644 --- a/ee/app/services/ee/application_settings/update_service.rb +++ b/ee/app/services/ee/application_settings/update_service.rb @@ -5,6 +5,7 @@ module ApplicationSettings module UpdateService extend ::Gitlab::Utils::Override extend ActiveSupport::Concern + include ::GitlabSubscriptions::MemberManagement::PromotionManagementUtils override :execute def execute @@ -22,6 +23,8 @@ def execute elasticsearch_namespace_ids = params.delete(:elasticsearch_namespace_ids) elasticsearch_project_ids = params.delete(:elasticsearch_project_ids) + params[:enable_member_promotion_management] = get_enable_member_promotion_management + if result = super find_or_create_elasticsearch_index if params.keys.any? { |key| key.to_s.start_with?('elasticsearch') } update_elasticsearch_containers(ElasticsearchIndexedNamespace, elasticsearch_namespace_ids) @@ -120,6 +123,21 @@ def elasticsearch_helper def elasticsearch_client ::Gitlab::Elastic::Client.build(application_setting.elasticsearch_config) end + + def get_enable_member_promotion_management + param_value = ActiveRecord::Type::Boolean.new.cast(params.delete(:enable_member_promotion_management)) + + return application_setting.enable_member_promotion_management if param_value.nil? + return false unless promotion_management_available? + return true if param_value == false && pending_member_approvals? + + param_value + end + + def pending_member_approvals? + ::GitlabSubscriptions::MemberManagement::SelfManaged::MaxAccessLevelMemberApprovalsFinder + .new(current_user).execute.any? + end end end end diff --git a/ee/spec/controllers/admin/application_settings_controller_spec.rb b/ee/spec/controllers/admin/application_settings_controller_spec.rb index 0b29342e8530dfb2b14a54929bc41a7b4c39e669..da955c62e56fd50b9dd6af621a6271fef0c51deb 100644 --- a/ee/spec/controllers/admin/application_settings_controller_spec.rb +++ b/ee/spec/controllers/admin/application_settings_controller_spec.rb @@ -157,7 +157,9 @@ let(:promotion_management_available) { true } before do - allow(controller).to receive(:promotion_management_available?).and_return(promotion_management_available) + allow_next_instance_of(::ApplicationSettings::UpdateService) do |instance| + allow(instance).to receive(:promotion_management_available?).and_return(promotion_management_available) + end end context 'with promotion management available' do diff --git a/ee/spec/helpers/ee/application_settings_helper_spec.rb b/ee/spec/helpers/ee/application_settings_helper_spec.rb index 5888c11261978a7b4f72d7eb7f60a67d42baf0ba..e10b5b0fd09b7e65a2258187e9453c284fde5e86 100644 --- a/ee/spec/helpers/ee/application_settings_helper_spec.rb +++ b/ee/spec/helpers/ee/application_settings_helper_spec.rb @@ -21,6 +21,10 @@ expect(visible_attributes).to include(*expected_fields) end + it 'contains member_promotion_management parameters' do + expect(visible_attributes).to include(*%i[enable_member_promotion_management]) + end + context 'when identity verification is enabled' do before do stub_saas_features(identity_verification: true) diff --git a/ee/spec/requests/api/settings_spec.rb b/ee/spec/requests/api/settings_spec.rb index 5041b7effbf7958539e3c617e68848402f01df8d..e8cc57090773c2c0a41d16b7658604c998342713 100644 --- a/ee/spec/requests/api/settings_spec.rb +++ b/ee/spec/requests/api/settings_spec.rb @@ -3,6 +3,7 @@ require 'spec_helper' RSpec.describe API::Settings, 'EE Settings', :aggregate_failures, feature_category: :shared do + using RSpec::Parameterized::TableSyntax include StubENV let(:user) { create(:user) } @@ -238,6 +239,57 @@ end end end + + context 'with billable member management' do + context 'when the feature is not available' do + it 'does not change enable_member_promotion_management to true' do + put api('/application/settings', admin, admin_mode: true), + params: { enable_member_promotion_management: true } + + expect(json_response['enable_member_promotion_management']).to eq(false) + end + end + + context 'when the feature is available' do + before do + allow_next_instance_of(::ApplicationSettings::UpdateService) do |instance| + allow(instance).to receive(:promotion_management_available?).and_return(true) + end + end + + where(param_value: [true, false]) + + with_them do + it 'changes enable_member_promotion_management' do + ::Gitlab::CurrentSettings.update!(enable_member_promotion_management: !param_value) + + put api('/application/settings', admin, admin_mode: true), + params: { enable_member_promotion_management: param_value } + + expect(json_response['enable_member_promotion_management']).to eq(param_value) + end + end + + context 'when there are pending promotions' do + before do + allow_next_instance_of( + ::GitlabSubscriptions::MemberManagement::SelfManaged::MaxAccessLevelMemberApprovalsFinder + ) do |instance| + allow(instance).to receive(:execute).and_return(['mock_non_empty_return']) + end + end + + it 'does not change enable_member_promotion_management to false' do + ::Gitlab::CurrentSettings.update!(enable_member_promotion_management: true) + + put api('/application/settings', admin, admin_mode: true), + params: { enable_member_promotion_management: false } + + expect(json_response['enable_member_promotion_management']).to eq(true) + end + end + end + end end shared_examples 'settings for licensed features' do