Class: ProjectFeature

Inherits:
ApplicationRecord show all
Extended by:
Gitlab::ConfigHelper, Gitlab::Utils::Override
Includes:
Featurable
Defined in:
app/models/project_feature.rb

Constant Summary collapse

FEATURES =

When updating this array, make sure to update rubocop/cop/gitlab/feature_available_usage.rb as well.

%i[
  issues
  forking
  merge_requests
  wiki
  snippets
  builds
  repository
  pages
  metrics_dashboard
  analytics
  operations
  security_and_compliance
  container_registry
].freeze
EXPORTABLE_FEATURES =
(FEATURES - [:security_and_compliance, :pages]).freeze
PRIVATE_FEATURES_MIN_ACCESS_LEVEL =
{
  merge_requests: Gitlab::Access::REPORTER,
  metrics_dashboard: Gitlab::Access::REPORTER,
  container_registry: Gitlab::Access::REPORTER
}.freeze
PRIVATE_FEATURES_MIN_ACCESS_LEVEL_FOR_PRIVATE_PROJECT =
{ repository: Gitlab::Access::REPORTER }.freeze

Constants included from Featurable

Featurable::DISABLED, Featurable::ENABLED, Featurable::PRIVATE, Featurable::PUBLIC, Featurable::STRING_OPTIONS

Constants inherited from ApplicationRecord

ApplicationRecord::MAX_PLUCK

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Gitlab::ConfigHelper

gitlab_config, gitlab_config_features

Methods included from Gitlab::Utils::Override

extended, extensions, included, method_added, override, prepended, queue_verification, verify!

Methods included from Featurable

#access_level, #feature_available?, #string_access_level

Methods inherited from ApplicationRecord

cached_column_list, #create_or_load_association, declarative_enum, default_select_columns, id_in, id_not_in, iid_in, pluck_primary_key, primary_key_in, #readable_by?, safe_ensure_unique, safe_find_or_create_by, safe_find_or_create_by!, #to_ability_name, underscore, where_exists, where_not_exists, with_fast_read_statement_timeout, without_order

Methods included from SensitiveSerializableHash

#serializable_hash

Class Method Details

.required_minimum_access_level(feature) ⇒ Object


37
38
39
40
41
# File 'app/models/project_feature.rb', line 37

def required_minimum_access_level(feature)
  feature = ensure_feature!(feature)

  PRIVATE_FEATURES_MIN_ACCESS_LEVEL.fetch(feature, Gitlab::Access::GUEST)
end

.required_minimum_access_level_for_private_project(feature) ⇒ Object

Guest users can perform certain features on public and internal projects, but not private projects.


44
45
46
47
48
49
50
# File 'app/models/project_feature.rb', line 44

def required_minimum_access_level_for_private_project(feature)
  feature = ensure_feature!(feature)

  PRIVATE_FEATURES_MIN_ACCESS_LEVEL_FOR_PRIVATE_PROJECT.fetch(feature) do
    required_minimum_access_level(feature)
  end
end

.with_feature_available_for_user(feature, user) ⇒ Object

project features may be “disabled”, “internal”, “enabled” or “public”. If “internal”, they are only available to team members. This scope returns features where the feature is either public, enabled, or internal with permission for the user. Note: this scope doesn't enforce that the user has access to the projects, it just checks that the user has access to the feature. It's important to use this scope with others that checks project authorizations first (e.g. `filter_by_feature_visibility`).

This method uses an optimized version of `with_feature_access_level` for logged in users to more efficiently get private projects with the given feature.


111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'app/models/project_feature.rb', line 111

def self.with_feature_available_for_user(feature, user)
  visible = [ENABLED, PUBLIC]

  if user&.can_read_all_resources?
    with_feature_enabled(feature)
  elsif user
    min_access_level = required_minimum_access_level(feature)
    column = quoted_access_level_column(feature)

    where("#{column} IS NULL OR #{column} IN (:public_visible) OR (#{column} = :private_visible AND EXISTS (:authorizations))",
         {
           public_visible: visible,
           private_visible: PRIVATE,
           authorizations: user.authorizations_for_projects(min_access_level: min_access_level, related_project_column: 'project_features.project_id')
         })
  else
    # This has to be added to include features whose value is nil in the db
    visible << nil
    with_feature_access_level(feature, visible)
  end
end

Instance Method Details

#private_pages?Boolean

Returns:

  • (Boolean)

141
142
143
# File 'app/models/project_feature.rb', line 141

def private_pages?
  !public_pages?
end

#public_pages?Boolean

Returns:

  • (Boolean)

133
134
135
136
137
138
139
# File 'app/models/project_feature.rb', line 133

def public_pages?
  return true unless Gitlab.config.pages.access_control

  return false if ::Gitlab::Pages.access_control_is_forced?

  pages_access_level == PUBLIC || pages_access_level == ENABLED && project.public?
end