diff --git a/app/models/project_feature.rb b/app/models/project_feature.rb index 11f4a3f3b6f26bd50a7e5c43ff667482ce1b6ab5..168646bbe416f751f5559818949a06d52e64f82e 100644 --- a/app/models/project_feature.rb +++ b/app/models/project_feature.rb @@ -63,32 +63,23 @@ def required_minimum_access_level_for_private_project(feature) validate :repository_children_level - default_value_for :builds_access_level, value: ENABLED, allows_nil: false - default_value_for :issues_access_level, value: ENABLED, allows_nil: false - default_value_for :forking_access_level, value: ENABLED, allows_nil: false - default_value_for :merge_requests_access_level, value: ENABLED, allows_nil: false - default_value_for :snippets_access_level, value: ENABLED, allows_nil: false - default_value_for :wiki_access_level, value: ENABLED, allows_nil: false - default_value_for :repository_access_level, value: ENABLED, allows_nil: false - default_value_for :analytics_access_level, value: ENABLED, allows_nil: false - default_value_for :metrics_dashboard_access_level, value: PRIVATE, allows_nil: false - default_value_for :operations_access_level, value: ENABLED, allows_nil: false - default_value_for :security_and_compliance_access_level, value: PRIVATE, allows_nil: false - default_value_for :monitor_access_level, value: ENABLED, allows_nil: false - default_value_for :infrastructure_access_level, value: ENABLED, allows_nil: false - default_value_for :feature_flags_access_level, value: ENABLED, allows_nil: false - default_value_for :environments_access_level, value: ENABLED, allows_nil: false - default_value_for :releases_access_level, value: ENABLED, allows_nil: false - - default_value_for(:pages_access_level, allows_nil: false) do |feature| - if ::Gitlab::Pages.access_control_is_forced? - PRIVATE - else - feature.project&.public? ? ENABLED : PRIVATE - end - end - - default_value_for(:package_registry_access_level) do |feature| + attribute :builds_access_level, default: ENABLED + attribute :issues_access_level, default: ENABLED + attribute :forking_access_level, default: ENABLED + attribute :merge_requests_access_level, default: ENABLED + attribute :snippets_access_level, default: ENABLED + attribute :wiki_access_level, default: ENABLED + attribute :repository_access_level, default: ENABLED + attribute :analytics_access_level, default: ENABLED + attribute :metrics_dashboard_access_level, default: PRIVATE + attribute :operations_access_level, default: ENABLED + attribute :security_and_compliance_access_level, default: PRIVATE + attribute :monitor_access_level, default: ENABLED + attribute :infrastructure_access_level, default: ENABLED + attribute :feature_flags_access_level, default: ENABLED + attribute :environments_access_level, default: ENABLED + + attribute :package_registry_access_level, default: -> do if ::Gitlab.config.packages.enabled ENABLED else @@ -96,7 +87,7 @@ def required_minimum_access_level_for_private_project(feature) end end - default_value_for(:container_registry_access_level) do |feature| + attribute :container_registry_access_level, default: -> do if gitlab_config_features.container_registry ENABLED else @@ -104,6 +95,9 @@ def required_minimum_access_level_for_private_project(feature) end end + after_initialize :set_pages_access_level, if: :new_record? + after_initialize :set_default_values, unless: :new_record? + # "enabled" here means "not disabled". It includes private features! scope :with_feature_enabled, ->(feature) { feature_access_level_attribute = arel_table[access_level_attribute(feature)] @@ -170,6 +164,23 @@ def package_registry_access_level=(value) private + def set_pages_access_level + self.pages_access_level ||= if ::Gitlab::Pages.access_control_is_forced? + PRIVATE + else + self.project&.public? ? ENABLED : PRIVATE + end + end + + def set_default_values + self.class.column_names.each do |column_name| + next unless has_attribute?(column_name) + next unless read_attribute(column_name).nil? + + write_attribute(column_name, self.class.column_defaults[column_name]) + end + end + # Validates builds and merge requests access level # which cannot be higher than repository access level def repository_children_level diff --git a/ee/app/models/ee/project_feature.rb b/ee/app/models/ee/project_feature.rb index 15f110ccb03a2cdb079037ba2915a56ceab9aedf..963b2ff69c3085454da3ccdf5ce21c2218b06ffb 100644 --- a/ee/app/models/ee/project_feature.rb +++ b/ee/app/models/ee/project_feature.rb @@ -30,7 +30,7 @@ module ProjectFeature end end - default_value_for :requirements_access_level, value: Featurable::ENABLED, allows_nil: false + attribute :requirements_access_level, default: Featurable::ENABLED private diff --git a/ee/spec/models/project_feature_spec.rb b/ee/spec/models/project_feature_spec.rb index 43545fec41f93f49531fb9b137c1e8d9aa3a8b45..446e0438432f59f3ff524aae44316cff29183fdb 100644 --- a/ee/spec/models/project_feature_spec.rb +++ b/ee/spec/models/project_feature_spec.rb @@ -6,6 +6,12 @@ let(:project) { create(:project, :public) } let(:user) { create(:user) } + describe 'default values' do + subject { Project.new.project_feature } + + specify { expect(subject.requirements_access_level).to eq(Featurable::ENABLED) } + end + describe '#feature_available?' do let(:features) { %w(issues wiki builds merge_requests snippets repository pages) } diff --git a/spec/models/project_feature_spec.rb b/spec/models/project_feature_spec.rb index fb6aaffdf223de070bfbc303c4952f1bd9b6c2d1..fe0b46c31172cb0e4f8eaf882750818cee54d018 100644 --- a/spec/models/project_feature_spec.rb +++ b/spec/models/project_feature_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe ProjectFeature do +RSpec.describe ProjectFeature, feature_category: :projects do using RSpec::Parameterized::TableSyntax let_it_be_with_reload(:project) { create(:project) } @@ -10,6 +10,28 @@ it { is_expected.to belong_to(:project) } + describe 'default values' do + subject { Project.new.project_feature } + + specify { expect(subject.builds_access_level).to eq(ProjectFeature::ENABLED) } + specify { expect(subject.issues_access_level).to eq(ProjectFeature::ENABLED) } + specify { expect(subject.forking_access_level).to eq(ProjectFeature::ENABLED) } + specify { expect(subject.merge_requests_access_level).to eq(ProjectFeature::ENABLED) } + specify { expect(subject.snippets_access_level).to eq(ProjectFeature::ENABLED) } + specify { expect(subject.wiki_access_level).to eq(ProjectFeature::ENABLED) } + specify { expect(subject.repository_access_level).to eq(ProjectFeature::ENABLED) } + specify { expect(subject.metrics_dashboard_access_level).to eq(ProjectFeature::PRIVATE) } + specify { expect(subject.operations_access_level).to eq(ProjectFeature::ENABLED) } + specify { expect(subject.security_and_compliance_access_level).to eq(ProjectFeature::PRIVATE) } + specify { expect(subject.monitor_access_level).to eq(ProjectFeature::ENABLED) } + specify { expect(subject.infrastructure_access_level).to eq(ProjectFeature::ENABLED) } + specify { expect(subject.feature_flags_access_level).to eq(ProjectFeature::ENABLED) } + specify { expect(subject.environments_access_level).to eq(ProjectFeature::ENABLED) } + specify { expect(subject.releases_access_level).to eq(ProjectFeature::ENABLED) } + specify { expect(subject.package_registry_access_level).to eq(ProjectFeature::ENABLED) } + specify { expect(subject.container_registry_access_level).to eq(ProjectFeature::ENABLED) } + end + describe 'PRIVATE_FEATURES_MIN_ACCESS_LEVEL_FOR_PRIVATE_PROJECT' do it 'has higher level than that of PRIVATE_FEATURES_MIN_ACCESS_LEVEL' do described_class::PRIVATE_FEATURES_MIN_ACCESS_LEVEL_FOR_PRIVATE_PROJECT.each do |feature, level|