diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb index 827f8bc93bef8fa41657c598f6cff3eda1ba9888..c1fbfd2d638cccab1fc3d82eeef7af1179362c03 100644 --- a/app/models/application_setting.rb +++ b/app/models/application_setting.rb @@ -498,6 +498,10 @@ def self.kroki_formats_attributes end end + validates :default_project_visibility, :default_group_visibility, + exclusion: { in: :restricted_visibility_levels, message: "cannot be set to a restricted visibility level" }, + if: :should_prevent_visibility_restriction? + validates_each :import_sources do |record, attr, value| value&.each do |source| unless Gitlab::ImportSources.options.value?(source) @@ -951,6 +955,13 @@ def validate_url(parsed_url, name, error_message) def reset_deletion_warning_redis_key Gitlab::InactiveProjectsDeletionWarningTracker.reset_all end + + def should_prevent_visibility_restriction? + Feature.enabled?(:prevent_visibility_restriction) && + (default_project_visibility_changed? || + default_group_visibility_changed? || + restricted_visibility_levels_changed?) + end end ApplicationSetting.prepend(ApplicationSettingMaskedAttrs) diff --git a/config/feature_flags/development/prevent_visibility_restriction.yml b/config/feature_flags/development/prevent_visibility_restriction.yml new file mode 100644 index 0000000000000000000000000000000000000000..9f5b82b6f6954b70a04547e2620dad2b893e63f5 --- /dev/null +++ b/config/feature_flags/development/prevent_visibility_restriction.yml @@ -0,0 +1,8 @@ +--- +name: prevent_visibility_restriction +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/124649 +rollout_issue_url: +milestone: '16.3' +type: development +group: group::acquisition +default_enabled: false diff --git a/spec/features/projects/new_project_spec.rb b/spec/features/projects/new_project_spec.rb index d05b7649f94a17354cf4ce193bc13173d0e10816..6e6d9ff4af9f7c91929a4f3f84f8c2fba8d5f616 100644 --- a/spec/features/projects/new_project_spec.rb +++ b/spec/features/projects/new_project_spec.rb @@ -46,7 +46,8 @@ end it 'shows a message if multiple levels are restricted' do - Gitlab::CurrentSettings.update!( + stub_application_setting(default_project_visibility: Gitlab::VisibilityLevel::PUBLIC) + stub_application_setting( restricted_visibility_levels: [Gitlab::VisibilityLevel::PRIVATE, Gitlab::VisibilityLevel::INTERNAL] ) @@ -56,15 +57,21 @@ expect(page).to have_content 'Other visibility settings have been disabled by the administrator.' end - it 'shows a message if all levels are restricted' do - Gitlab::CurrentSettings.update!( - restricted_visibility_levels: Gitlab::VisibilityLevel.values - ) + context 'with prevent_visibility_restriction feature flag off' do + before do + stub_feature_flags(prevent_visibility_restriction: false) + end - visit new_project_path - click_link 'Create blank project' + it 'shows a message if all levels are restricted' do + Gitlab::CurrentSettings.update!( + restricted_visibility_levels: Gitlab::VisibilityLevel.values + ) - expect(page).to have_content 'Visibility settings have been disabled by the administrator.' + visit new_project_path + click_link 'Create blank project' + + expect(page).to have_content 'Visibility settings have been disabled by the administrator.' + end end end diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb index 8dcafaa90a07211630ac45444be8e4cc5ae2db98..076836cfcefb3bda98faf713aeb285c331a930dc 100644 --- a/spec/models/application_setting_spec.rb +++ b/spec/models/application_setting_spec.rb @@ -1272,6 +1272,37 @@ def expect_invalid it { is_expected.to allow_value({ name: value }).for(:default_branch_protection_defaults) } end end + + context 'default_project_visibility, default_group_visibility and restricted_visibility_levels validations' do + before do + subject.restricted_visibility_levels = [10] + end + + it { is_expected.not_to allow_value(10).for(:default_group_visibility) } + it { is_expected.not_to allow_value(10).for(:default_project_visibility) } + it { is_expected.to allow_value(20).for(:default_group_visibility) } + it { is_expected.to allow_value(20).for(:default_project_visibility) } + + it 'sets error messages when default visibility settings are not valid' do + subject.default_group_visibility = 10 + subject.default_project_visibility = 10 + + expect(subject).not_to be_valid + expect(subject.errors.messages[:default_group_visibility].first).to eq("cannot be set to a restricted visibility level") + expect(subject.errors.messages[:default_project_visibility].first).to eq("cannot be set to a restricted visibility level") + end + + context 'when prevent_visibility_restriction FF is disabled' do + before do + stub_feature_flags(prevent_visibility_restriction: false) + end + + it { is_expected.to allow_value(10).for(:default_group_visibility) } + it { is_expected.to allow_value(10).for(:default_project_visibility) } + it { is_expected.to allow_value(20).for(:default_group_visibility) } + it { is_expected.to allow_value(20).for(:default_project_visibility) } + end + end end context 'restrict creating duplicates' do