diff options
Diffstat (limited to 'app/models/concerns')
62 files changed, 240 insertions, 264 deletions
diff --git a/app/models/concerns/analytics/cycle_analytics/stage.rb b/app/models/concerns/analytics/cycle_analytics/stage.rb index f1c39dda49d..90d48aa81d0 100644 --- a/app/models/concerns/analytics/cycle_analytics/stage.rb +++ b/app/models/concerns/analytics/cycle_analytics/stage.rb @@ -27,6 +27,7 @@ module Analytics scope :default_stages, -> { where(custom: false) } scope :ordered, -> { order(:relative_position, :id) } scope :for_list, -> { includes(:start_event_label, :end_event_label).ordered } + scope :by_value_stream, -> (value_stream) { where(value_stream_id: value_stream.id) } end def parent=(_) diff --git a/app/models/concerns/atomic_internal_id.rb b/app/models/concerns/atomic_internal_id.rb index bbf9ecbcfe9..80cf6260b0b 100644 --- a/app/models/concerns/atomic_internal_id.rb +++ b/app/models/concerns/atomic_internal_id.rb @@ -214,9 +214,9 @@ module AtomicInternalId def self.project_init(klass, column_name = :iid) ->(instance, scope) do if instance - klass.where(project_id: instance.project_id).maximum(column_name) + klass.default_scoped.where(project_id: instance.project_id).maximum(column_name) elsif scope.present? - klass.where(**scope).maximum(column_name) + klass.default_scoped.where(**scope).maximum(column_name) end end end diff --git a/app/models/concerns/board_recent_visit.rb b/app/models/concerns/board_recent_visit.rb new file mode 100644 index 00000000000..fd4d574ac58 --- /dev/null +++ b/app/models/concerns/board_recent_visit.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +module BoardRecentVisit + extend ActiveSupport::Concern + + class_methods do + def visited!(user, board) + find_or_create_by( + "user" => user, + board_parent_relation => board.resource_parent, + board_relation => board + ).tap do |visit| + visit.touch + end + rescue ActiveRecord::RecordNotUnique + retry + end + + def latest(user, parent, count: nil) + visits = by_user_parent(user, parent).order(updated_at: :desc) + visits = visits.preload(board_relation) + + visits.first(count) + end + + def board_relation + :board + end + + def board_parent_relation + raise NotImplementedError + end + end +end diff --git a/app/models/concerns/cache_markdown_field.rb b/app/models/concerns/cache_markdown_field.rb index 34c1b6d25a4..a5cf947ba07 100644 --- a/app/models/concerns/cache_markdown_field.rb +++ b/app/models/concerns/cache_markdown_field.rb @@ -26,7 +26,7 @@ module CacheMarkdownField # Returns the default Banzai render context for the cached markdown field. def banzai_render_context(field) - raise ArgumentError.new("Unknown field: #{field.inspect}") unless + raise ArgumentError, "Unknown field: #{field.inspect}" unless cached_markdown_fields.markdown_fields.include?(field) # Always include a project key, or Banzai complains @@ -99,7 +99,7 @@ module CacheMarkdownField end def cached_html_for(markdown_field) - raise ArgumentError.new("Unknown field: #{markdown_field}") unless + raise ArgumentError, "Unknown field: #{markdown_field}" unless cached_markdown_fields.markdown_fields.include?(markdown_field) __send__(cached_markdown_fields.html_field(markdown_field)) # rubocop:disable GitlabSecurity/PublicSend diff --git a/app/models/concerns/cacheable_attributes.rb b/app/models/concerns/cacheable_attributes.rb index ee56322cce7..f3b47047c55 100644 --- a/app/models/concerns/cacheable_attributes.rb +++ b/app/models/concerns/cacheable_attributes.rb @@ -53,7 +53,7 @@ module CacheableAttributes return cached_record if cached_record.present? current_without_cache.tap { |current_record| current_record&.cache! } - rescue => e + rescue StandardError => e if Rails.env.production? Gitlab::AppLogger.warn("Cached record for #{name} couldn't be loaded, falling back to uncached record: #{e}") else @@ -66,7 +66,7 @@ module CacheableAttributes def expire Gitlab::SafeRequestStore.delete(request_store_cache_key) cache_backend.delete(cache_key) - rescue + rescue StandardError # Gracefully handle when Redis is not available. For example, # omnibus may fail here during gitlab:assets:compile. end diff --git a/app/models/concerns/cascading_namespace_setting_attribute.rb b/app/models/concerns/cascading_namespace_setting_attribute.rb index 2b4a108a9a0..9efd90756b1 100644 --- a/app/models/concerns/cascading_namespace_setting_attribute.rb +++ b/app/models/concerns/cascading_namespace_setting_attribute.rb @@ -55,6 +55,7 @@ module CascadingNamespaceSettingAttribute # public methods define_attr_reader(attribute) define_attr_writer(attribute) + define_lock_attr_writer(attribute) define_lock_methods(attribute) alias_boolean(attribute) @@ -84,7 +85,7 @@ module CascadingNamespaceSettingAttribute next self[attribute] unless self.class.cascading_settings_feature_enabled? next self[attribute] if will_save_change_to_attribute?(attribute) - next locked_value(attribute) if cascading_attribute_locked?(attribute) + next locked_value(attribute) if cascading_attribute_locked?(attribute, include_self: false) next self[attribute] unless self[attribute].nil? cascaded_value = cascaded_ancestor_value(attribute) @@ -97,15 +98,25 @@ module CascadingNamespaceSettingAttribute def define_attr_writer(attribute) define_method("#{attribute}=") do |value| + return value if value == cascaded_ancestor_value(attribute) + clear_memoization(attribute) + super(value) + end + end + + def define_lock_attr_writer(attribute) + define_method("lock_#{attribute}=") do |value| + attr_value = public_send(attribute) # rubocop:disable GitlabSecurity/PublicSend + write_attribute(attribute, attr_value) if self[attribute].nil? super(value) end end def define_lock_methods(attribute) - define_method("#{attribute}_locked?") do - cascading_attribute_locked?(attribute) + define_method("#{attribute}_locked?") do |include_self: false| + cascading_attribute_locked?(attribute, include_self: include_self) end define_method("#{attribute}_locked_by_ancestor?") do @@ -133,7 +144,7 @@ module CascadingNamespaceSettingAttribute def define_validator_methods(attribute) define_method("#{attribute}_changeable?") do return unless cascading_attribute_changed?(attribute) - return unless cascading_attribute_locked?(attribute) + return unless cascading_attribute_locked?(attribute, include_self: false) errors.add(attribute, s_('CascadingSettings|cannot be changed because it is locked by an ancestor')) end @@ -141,7 +152,7 @@ module CascadingNamespaceSettingAttribute define_method("lock_#{attribute}_changeable?") do return unless cascading_attribute_changed?("lock_#{attribute}") - if cascading_attribute_locked?(attribute) + if cascading_attribute_locked?(attribute, include_self: false) return errors.add(:"lock_#{attribute}", s_('CascadingSettings|cannot be changed because it is locked by an ancestor')) end @@ -202,8 +213,9 @@ module CascadingNamespaceSettingAttribute Gitlab::CurrentSettings.public_send("lock_#{attribute}") # rubocop:disable GitlabSecurity/PublicSend end - def cascading_attribute_locked?(attribute) - locked_by_ancestor?(attribute) || locked_by_application_setting?(attribute) + def cascading_attribute_locked?(attribute, include_self:) + locked_by_self = include_self ? public_send("lock_#{attribute}?") : false # rubocop:disable GitlabSecurity/PublicSend + locked_by_self || locked_by_ancestor?(attribute) || locked_by_application_setting?(attribute) end def cascading_attribute_changed?(attribute) diff --git a/app/models/concerns/ci/artifactable.rb b/app/models/concerns/ci/artifactable.rb index 0d29955268f..27040a677ff 100644 --- a/app/models/concerns/ci/artifactable.rb +++ b/app/models/concerns/ci/artifactable.rb @@ -43,4 +43,4 @@ module Ci end end -Ci::Artifactable.prepend_ee_mod +Ci::Artifactable.prepend_mod diff --git a/app/models/concerns/ci/has_status.rb b/app/models/concerns/ci/has_status.rb index c990da5873a..f3c254053b5 100644 --- a/app/models/concerns/ci/has_status.rb +++ b/app/models/concerns/ci/has_status.rb @@ -122,12 +122,10 @@ module Ci private - def calculate_duration - if started_at && finished_at - finished_at - started_at - elsif started_at - Time.current - started_at - end + def calculate_duration(start_time, end_time) + return unless start_time + + (end_time || Time.current) - start_time end end end diff --git a/app/models/concerns/ci/maskable.rb b/app/models/concerns/ci/maskable.rb index 4e0ee72f18f..e1ef4531845 100644 --- a/app/models/concerns/ci/maskable.rb +++ b/app/models/concerns/ci/maskable.rb @@ -9,9 +9,9 @@ module Ci # * No variables # * No spaces # * Minimal length of 8 characters - # * Characters must be from the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.' + # * Characters must be from the Base64 alphabet (RFC4648) with the addition of '@', ':', '.', and '~' # * Absolutely no fun is allowed - REGEX = /\A[a-zA-Z0-9_+=\/@:.-]{8,}\z/.freeze + REGEX = /\A[a-zA-Z0-9_+=\/@:.~-]{8,}\z/.freeze included do validates :masked, inclusion: { in: [true, false] } diff --git a/app/models/concerns/ci/metadatable.rb b/app/models/concerns/ci/metadatable.rb index 26e644646b4..601637ea32a 100644 --- a/app/models/concerns/ci/metadatable.rb +++ b/app/models/concerns/ci/metadatable.rb @@ -88,4 +88,4 @@ module Ci end end -Ci::Metadatable.prepend_if_ee('EE::Ci::Metadatable') +Ci::Metadatable.prepend_mod_with('Ci::Metadatable') diff --git a/app/models/concerns/cron_schedulable.rb b/app/models/concerns/cron_schedulable.rb new file mode 100644 index 00000000000..beb3a09c119 --- /dev/null +++ b/app/models/concerns/cron_schedulable.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +module CronSchedulable + extend ActiveSupport::Concern + include Schedulable + + ## + # The `next_run_at` column is set to the actual execution date of worker that + # triggers the schedule. This way, a schedule like `*/1 * * * *` won't be triggered + # in a short interval when the worker runs irregularly by Sidekiq Memory Killer. + def set_next_run_at + now = Time.zone.now + ideal_next_run = ideal_next_run_from(now) + + self.next_run_at = if ideal_next_run == cron_worker_next_run_from(now) + ideal_next_run + else + cron_worker_next_run_from(ideal_next_run) + end + end + + private + + def ideal_next_run_from(start_time) + next_time_from(start_time, cron, cron_timezone) + end + + def cron_worker_next_run_from(start_time) + next_time_from(start_time, worker_cron_expression, Time.zone.name) + end + + def next_time_from(start_time, cron, cron_timezone) + Gitlab::Ci::CronParser + .new(cron, cron_timezone) + .next_time_from(start_time) + end + + def worker_cron_expression + raise NotImplementedError + end +end diff --git a/app/models/concerns/enums/ci/commit_status.rb b/app/models/concerns/enums/ci/commit_status.rb index de17f50cd29..2e368b12cb7 100644 --- a/app/models/concerns/enums/ci/commit_status.rb +++ b/app/models/concerns/enums/ci/commit_status.rb @@ -22,6 +22,8 @@ module Enums forward_deployment_failure: 13, user_blocked: 14, project_deleted: 15, + ci_quota_exceeded: 16, + pipeline_loop_detected: 17, insufficient_bridge_permissions: 1_001, downstream_bridge_project_not_found: 1_002, invalid_bridge_trigger: 1_003, @@ -35,4 +37,4 @@ module Enums end end -Enums::Ci::CommitStatus.prepend_if_ee('EE::Enums::Ci::CommitStatus') +Enums::Ci::CommitStatus.prepend_mod_with('Enums::Ci::CommitStatus') diff --git a/app/models/concerns/enums/ci/pipeline.rb b/app/models/concerns/enums/ci/pipeline.rb index fdc48d09db2..c42b046592f 100644 --- a/app/models/concerns/enums/ci/pipeline.rb +++ b/app/models/concerns/enums/ci/pipeline.rb @@ -10,6 +10,7 @@ module Enums unknown_failure: 0, config_error: 1, external_validation_failure: 2, + user_not_verified: 3, activity_limit_exceeded: 20, size_limit_exceeded: 21, job_activity_limit_exceeded: 22, diff --git a/app/models/concerns/enums/internal_id.rb b/app/models/concerns/enums/internal_id.rb index b08c05b1934..71c86bab136 100644 --- a/app/models/concerns/enums/internal_id.rb +++ b/app/models/concerns/enums/internal_id.rb @@ -22,4 +22,4 @@ module Enums end end -Enums::InternalId.prepend_if_ee('EE::Enums::InternalId') +Enums::InternalId.prepend_mod_with('Enums::InternalId') diff --git a/app/models/concerns/enums/vulnerability.rb b/app/models/concerns/enums/vulnerability.rb index 4b2e9e9e0b2..55360eb92e6 100644 --- a/app/models/concerns/enums/vulnerability.rb +++ b/app/models/concerns/enums/vulnerability.rb @@ -43,4 +43,4 @@ module Enums end end -Enums::Vulnerability.prepend_if_ee('EE::Enums::Vulnerability') +Enums::Vulnerability.prepend_mod_with('Enums::Vulnerability') diff --git a/app/models/concerns/from_set_operator.rb b/app/models/concerns/from_set_operator.rb index 593fd251c5c..c6d63631c84 100644 --- a/app/models/concerns/from_set_operator.rb +++ b/app/models/concerns/from_set_operator.rb @@ -10,8 +10,8 @@ module FromSetOperator raise "Trying to redefine method '#{method(method_name)}'" if methods.include?(method_name) - define_method(method_name) do |members, remove_duplicates: true, alias_as: table_name| - operator_sql = operator.new(members, remove_duplicates: remove_duplicates).to_sql + define_method(method_name) do |members, remove_duplicates: true, remove_order: true, alias_as: table_name| + operator_sql = operator.new(members, remove_duplicates: remove_duplicates, remove_order: remove_order).to_sql from(Arel.sql("(#{operator_sql}) #{alias_as}")) end diff --git a/app/models/concerns/group_descendant.rb b/app/models/concerns/group_descendant.rb index 67953105bed..b376537a418 100644 --- a/app/models/concerns/group_descendant.rb +++ b/app/models/concerns/group_descendant.rb @@ -22,7 +22,7 @@ module GroupDescendant return [] if descendants.empty? unless descendants.all? { |hierarchy| hierarchy.is_a?(GroupDescendant) } - raise ArgumentError.new(_('element is not a hierarchy')) + raise ArgumentError, _('element is not a hierarchy') end all_hierarchies = descendants.map do |descendant| @@ -56,7 +56,7 @@ module GroupDescendant end if parent.nil? && hierarchy_top.present? - raise ArgumentError.new(_('specified top is not part of the tree')) + raise ArgumentError, _('specified top is not part of the tree') end if parent && parent != hierarchy_top diff --git a/app/models/concerns/integration.rb b/app/models/concerns/has_integrations.rb index 5e53f13be95..b2775f4cbb2 100644 --- a/app/models/concerns/integration.rb +++ b/app/models/concerns/has_integrations.rb @@ -1,11 +1,11 @@ # frozen_string_literal: true -module Integration +module HasIntegrations extend ActiveSupport::Concern class_methods do def with_custom_integration_for(integration, page = nil, per = nil) - custom_integration_project_ids = Service + custom_integration_project_ids = Integration .select(:project_id) .where(type: integration.type) .where(inherit_from_id: nil) @@ -17,13 +17,13 @@ module Integration end def without_integration(integration) - services = Service + integrations = Integration .select('1') .where('services.project_id = projects.id') .where(type: integration.type) Project - .where('NOT EXISTS (?)', services) + .where('NOT EXISTS (?)', integrations) .where(pending_delete: false) .where(archived: false) end diff --git a/app/models/concerns/has_repository.rb b/app/models/concerns/has_repository.rb index 774cda2c3e8..33f6904bc91 100644 --- a/app/models/concerns/has_repository.rb +++ b/app/models/concerns/has_repository.rb @@ -17,7 +17,7 @@ module HasRepository def valid_repo? repository.exists? - rescue + rescue StandardError errors.add(:base, _('Invalid repository path')) false end @@ -25,7 +25,7 @@ module HasRepository def repo_exists? strong_memoize(:repo_exists) do repository.exists? - rescue + rescue StandardError false end end diff --git a/app/models/concerns/has_timelogs_report.rb b/app/models/concerns/has_timelogs_report.rb index 90f9876de95..3af063438bf 100644 --- a/app/models/concerns/has_timelogs_report.rb +++ b/app/models/concerns/has_timelogs_report.rb @@ -15,6 +15,6 @@ module HasTimelogsReport private def timelogs_for(start_time, end_time) - Timelog.between_times(start_time, end_time).for_issues_in_group(self) + Timelog.between_times(start_time, end_time).in_group(self) end end diff --git a/app/models/concerns/has_wiki_page_meta_attributes.rb b/app/models/concerns/has_wiki_page_meta_attributes.rb index 136f2d00ce3..55681bc91a5 100644 --- a/app/models/concerns/has_wiki_page_meta_attributes.rb +++ b/app/models/concerns/has_wiki_page_meta_attributes.rb @@ -59,7 +59,7 @@ module HasWikiPageMetaAttributes if conflict.present? meta.errors.add(:canonical_slug, 'Duplicate value found') - raise CanonicalSlugConflictError.new(meta) + raise CanonicalSlugConflictError, meta end meta diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb index 1e44321e148..f5c70f10dc5 100644 --- a/app/models/concerns/issuable.rb +++ b/app/models/concerns/issuable.rb @@ -63,7 +63,7 @@ module Issuable has_many :note_authors, -> { distinct }, through: :notes, source: :author - has_many :label_links, as: :target, dependent: :destroy, inverse_of: :target # rubocop:disable Cop/ActiveRecordDependent + has_many :label_links, as: :target, inverse_of: :target has_many :labels, through: :label_links has_many :todos, as: :target @@ -103,7 +103,7 @@ module Issuable end scope :assigned_to, ->(u) do assignees_table = Arel::Table.new("#{to_ability_name}_assignees") - sql = assignees_table.project('true').where(assignees_table[:user_id].in(u)).where(Arel::Nodes::SqlLiteral.new("#{to_ability_name}_id = #{to_ability_name}s.id")) + sql = assignees_table.project('true').where(assignees_table[:user_id].in(u.id)).where(Arel::Nodes::SqlLiteral.new("#{to_ability_name}_id = #{to_ability_name}s.id")) where("EXISTS (#{sql.to_sql})") end # rubocop:enable GitlabSecurity/SqlInjection @@ -564,4 +564,4 @@ module Issuable end end -Issuable.prepend_if_ee('EE::Issuable') +Issuable.prepend_mod_with('Issuable') diff --git a/app/models/concerns/issue_available_features.rb b/app/models/concerns/issue_available_features.rb index a5ffa959174..28d12a033a6 100644 --- a/app/models/concerns/issue_available_features.rb +++ b/app/models/concerns/issue_available_features.rb @@ -29,5 +29,5 @@ module IssueAvailableFeatures end end -IssueAvailableFeatures.prepend_if_ee('EE::IssueAvailableFeatures') -IssueAvailableFeatures::ClassMethods.prepend_if_ee('EE::IssueAvailableFeatures::ClassMethods') +IssueAvailableFeatures.prepend_mod_with('IssueAvailableFeatures') +IssueAvailableFeatures::ClassMethods.prepend_mod_with('IssueAvailableFeatures::ClassMethods') diff --git a/app/models/concerns/limitable.rb b/app/models/concerns/limitable.rb index 3cb0bd85936..672bcdbbb1b 100644 --- a/app/models/concerns/limitable.rb +++ b/app/models/concerns/limitable.rb @@ -7,6 +7,7 @@ module Limitable included do class_attribute :limit_scope class_attribute :limit_name + class_attribute :limit_feature_flag self.limit_name = self.name.demodulize.tableize validate :validate_plan_limit_not_exceeded, on: :create @@ -25,6 +26,7 @@ module Limitable def validate_scoped_plan_limit_not_exceeded scope_relation = self.public_send(limit_scope) # rubocop:disable GitlabSecurity/PublicSend return unless scope_relation + return if limit_feature_flag && ::Feature.disabled?(limit_feature_flag, scope_relation, default_enabled: :yaml) relation = self.class.where(limit_scope => scope_relation) limits = scope_relation.actual_limits diff --git a/app/models/concerns/loaded_in_group_list.rb b/app/models/concerns/loaded_in_group_list.rb index 59e0ed75d2d..848ef63f1c2 100644 --- a/app/models/concerns/loaded_in_group_list.rb +++ b/app/models/concerns/loaded_in_group_list.rb @@ -79,4 +79,4 @@ module LoadedInGroupList end end -LoadedInGroupList::ClassMethods.prepend_if_ee('EE::LoadedInGroupList::ClassMethods') +LoadedInGroupList::ClassMethods.prepend_mod_with('LoadedInGroupList::ClassMethods') diff --git a/app/models/concerns/mentionable.rb b/app/models/concerns/mentionable.rb index 5db077c178d..f1baa923ec5 100644 --- a/app/models/concerns/mentionable.rb +++ b/app/models/concerns/mentionable.rb @@ -211,4 +211,4 @@ module Mentionable end end -Mentionable.prepend_if_ee('EE::Mentionable') +Mentionable.prepend_mod_with('Mentionable') diff --git a/app/models/concerns/mentionable/reference_regexes.rb b/app/models/concerns/mentionable/reference_regexes.rb index 5a5ce1809d0..e33b6db0103 100644 --- a/app/models/concerns/mentionable/reference_regexes.rb +++ b/app/models/concerns/mentionable/reference_regexes.rb @@ -37,4 +37,4 @@ module Mentionable end end -Mentionable::ReferenceRegexes.prepend_if_ee('EE::Mentionable::ReferenceRegexes') +Mentionable::ReferenceRegexes.prepend_mod_with('Mentionable::ReferenceRegexes') diff --git a/app/models/concerns/milestoneable.rb b/app/models/concerns/milestoneable.rb index d42417bb6c1..c4f810ab9b1 100644 --- a/app/models/concerns/milestoneable.rb +++ b/app/models/concerns/milestoneable.rb @@ -28,7 +28,7 @@ module Milestoneable scope :without_release, -> do joins("LEFT OUTER JOIN milestone_releases ON #{table_name}.milestone_id = milestone_releases.milestone_id") - .where('milestone_releases.release_id IS NULL') + .where(milestone_releases: { release_id: nil }) end scope :joins_milestone_releases, -> do @@ -57,4 +57,4 @@ module Milestoneable end end -Milestoneable.prepend_if_ee('EE::Milestoneable') +Milestoneable.prepend_mod_with('Milestoneable') diff --git a/app/models/concerns/noteable.rb b/app/models/concerns/noteable.rb index f3cc68e4b85..f6d4e5bd27b 100644 --- a/app/models/concerns/noteable.rb +++ b/app/models/concerns/noteable.rb @@ -183,5 +183,5 @@ end Noteable.extend(Noteable::ClassMethods) -Noteable::ClassMethods.prepend_if_ee('EE::Noteable::ClassMethods') -Noteable.prepend_if_ee('EE::Noteable') +Noteable::ClassMethods.prepend_mod_with('Noteable::ClassMethods') +Noteable.prepend_mod_with('Noteable') diff --git a/app/models/concerns/optimized_issuable_label_filter.rb b/app/models/concerns/optimized_issuable_label_filter.rb index c7af841e450..19d2ac620f3 100644 --- a/app/models/concerns/optimized_issuable_label_filter.rb +++ b/app/models/concerns/optimized_issuable_label_filter.rb @@ -28,7 +28,6 @@ module OptimizedIssuableLabelFilter # Taken from IssuableFinder def count_by_state - return super if root_namespace.nil? return super if Feature.disabled?(:optimized_issuable_label_filter, default_enabled: :yaml) count_params = params.merge(state: nil, sort: nil, force_cte: true) @@ -40,7 +39,11 @@ module OptimizedIssuableLabelFilter .group(:state_id) .count - counts = state_counts.transform_keys { |key| count_key(key) } + counts = Hash.new(0) + + state_counts.each do |key, value| + counts[count_key(key)] += value + end counts[:all] = counts.values.sum counts.with_indifferent_access diff --git a/app/models/concerns/packages/debian/architecture.rb b/app/models/concerns/packages/debian/architecture.rb index 760ebb49980..e2fa0ceb0f6 100644 --- a/app/models/concerns/packages/debian/architecture.rb +++ b/app/models/concerns/packages/debian/architecture.rb @@ -23,6 +23,7 @@ module Packages uniqueness: { scope: %i[distribution_id] }, format: { with: Gitlab::Regex.debian_architecture_regex } + scope :ordered_by_name, -> { order(:name) } scope :with_distribution, ->(distribution) { where(distribution: distribution) } scope :with_name, ->(name) { where(name: name) } end diff --git a/app/models/concerns/packages/debian/component.rb b/app/models/concerns/packages/debian/component.rb index 7b342c7b684..5ea686faec2 100644 --- a/app/models/concerns/packages/debian/component.rb +++ b/app/models/concerns/packages/debian/component.rb @@ -23,6 +23,7 @@ module Packages uniqueness: { scope: %i[distribution_id] }, format: { with: Gitlab::Regex.debian_component_regex } + scope :ordered_by_name, -> { order(:name) } scope :with_distribution, ->(distribution) { where(distribution: distribution) } scope :with_name, ->(name) { where(name: name) } end diff --git a/app/models/concerns/packages/debian/component_file.rb b/app/models/concerns/packages/debian/component_file.rb index 3cc2c291e96..c41635a0d16 100644 --- a/app/models/concerns/packages/debian/component_file.rb +++ b/app/models/concerns/packages/debian/component_file.rb @@ -60,6 +60,8 @@ module Packages scope :preload_distribution, -> { includes(component: :distribution) } + scope :created_before, ->(reference) { where("#{table_name}.created_at < ?", reference) } + mount_file_store_uploader Packages::Debian::ComponentFileUploader before_validation :update_size_from_file diff --git a/app/models/concerns/packages/debian/distribution.rb b/app/models/concerns/packages/debian/distribution.rb index 08fb9ccf3ea..267c7a4d201 100644 --- a/app/models/concerns/packages/debian/distribution.rb +++ b/app/models/concerns/packages/debian/distribution.rb @@ -84,7 +84,7 @@ module Packages attr_encrypted :signing_keys, mode: :per_attribute_iv, - key: Settings.attr_encrypted_db_key_base_truncated, + key: Settings.attr_encrypted_db_key_base_32, algorithm: 'aes-256-gcm', encode: false, encode_iv: false diff --git a/app/models/concerns/participable.rb b/app/models/concerns/participable.rb index acd654bd229..25410a859e9 100644 --- a/app/models/concerns/participable.rb +++ b/app/models/concerns/participable.rb @@ -135,4 +135,4 @@ module Participable end end -Participable.prepend_if_ee('EE::Participable') +Participable.prepend_mod_with('Participable') diff --git a/app/models/concerns/project_features_compatibility.rb b/app/models/concerns/project_features_compatibility.rb index 7c774d8bad7..484c91e0833 100644 --- a/app/models/concerns/project_features_compatibility.rb +++ b/app/models/concerns/project_features_compatibility.rb @@ -109,4 +109,4 @@ module ProjectFeaturesCompatibility end end -ProjectFeaturesCompatibility.prepend_if_ee('EE::ProjectFeaturesCompatibility') +ProjectFeaturesCompatibility.prepend_mod_with('ProjectFeaturesCompatibility') diff --git a/app/models/concerns/prometheus_adapter.rb b/app/models/concerns/prometheus_adapter.rb index 55c2bf96a94..afebc426762 100644 --- a/app/models/concerns/prometheus_adapter.rb +++ b/app/models/concerns/prometheus_adapter.rb @@ -26,9 +26,14 @@ module PrometheusAdapter } end + # Overridden in app/models/clusters/applications/prometheus.rb + def managed_prometheus? + false + end + # This is a light-weight check if a prometheus client is properly configured. def configured? - raise NotImplemented + raise NotImplementedError end # This is a heavy-weight check if a prometheus is properly configured and accessible from GitLab. diff --git a/app/models/concerns/protected_ref.rb b/app/models/concerns/protected_ref.rb index 2828ae4a3a9..ec56f4a32af 100644 --- a/app/models/concerns/protected_ref.rb +++ b/app/models/concerns/protected_ref.rb @@ -78,4 +78,4 @@ end # since these are defined in a ClassMethods constant. As such, we prepend the # module directly into ProtectedRef::ClassMethods, instead of prepending it into # ProtectedRef. -ProtectedRef::ClassMethods.prepend_if_ee('EE::ProtectedRef') +ProtectedRef::ClassMethods.prepend_mod_with('ProtectedRef') diff --git a/app/models/concerns/protected_ref_access.rb b/app/models/concerns/protected_ref_access.rb index 5e38ce7cad8..618ad96905d 100644 --- a/app/models/concerns/protected_ref_access.rb +++ b/app/models/concerns/protected_ref_access.rb @@ -53,12 +53,12 @@ module ProtectedRefAccess end end -ProtectedRefAccess.include_if_ee('EE::ProtectedRefAccess::Scopes') -ProtectedRefAccess.prepend_if_ee('EE::ProtectedRefAccess') +ProtectedRefAccess.include_mod_with('ProtectedRefAccess::Scopes') +ProtectedRefAccess.prepend_mod_with('ProtectedRefAccess') # When using `prepend` (or `include` for that matter), the `ClassMethods` # constants are not merged. This means that `class_methods` in # `EE::ProtectedRefAccess` would be ignored. # # To work around this, we prepend the `ClassMethods` constant manually. -ProtectedRefAccess::ClassMethods.prepend_if_ee('EE::ProtectedRefAccess::ClassMethods') +ProtectedRefAccess::ClassMethods.prepend_mod_with('ProtectedRefAccess::ClassMethods') diff --git a/app/models/concerns/reactive_caching.rb b/app/models/concerns/reactive_caching.rb index dbc70ac2218..9ed2070d11c 100644 --- a/app/models/concerns/reactive_caching.rb +++ b/app/models/concerns/reactive_caching.rb @@ -168,7 +168,7 @@ module ReactiveCaching data_deep_size = Gitlab::Utils::DeepSize.new(data, max_size: self.class.reactive_cache_hard_limit) - raise ExceededReactiveCacheLimit.new unless data_deep_size.valid? + raise ExceededReactiveCacheLimit unless data_deep_size.valid? end end end diff --git a/app/models/concerns/relative_positioning.rb b/app/models/concerns/relative_positioning.rb index 7f559f0a7ed..75dfed6d58f 100644 --- a/app/models/concerns/relative_positioning.rb +++ b/app/models/concerns/relative_positioning.rb @@ -53,13 +53,13 @@ module RelativePositioning return [size, starting_from] if size >= MIN_GAP + terminus = context.at_position(starting_from) + if at_end - terminus = context.max_sibling terminus.shift_left max_relative_position = terminus.relative_position [[(MAX_POSITION - max_relative_position) / gaps, IDEAL_DISTANCE].min, max_relative_position] else - terminus = context.min_sibling terminus.shift_right min_relative_position = terminus.relative_position [[(min_relative_position - MIN_POSITION) / gaps, IDEAL_DISTANCE].min, min_relative_position] @@ -79,6 +79,8 @@ module RelativePositioning objects = objects.reject(&:relative_position) return 0 if objects.empty? + objects.first.check_repositioning_allowed! + number_of_gaps = objects.size # 1 to the nearest neighbour, and one between each representative = RelativePositioning.mover.context(objects.first) @@ -123,6 +125,12 @@ module RelativePositioning ::Gitlab::RelativePositioning::Mover.new(START_POSITION, (MIN_POSITION..MAX_POSITION)) end + # To be overriden on child classes whenever + # blocking position updates is necessary. + def check_repositioning_allowed! + nil + end + def move_between(before, after) before, after = [before, after].sort_by(&:relative_position) if before && after diff --git a/app/models/concerns/repository_storage_movable.rb b/app/models/concerns/repository_storage_movable.rb index 8607f0d94f4..1dd8eebeff3 100644 --- a/app/models/concerns/repository_storage_movable.rb +++ b/app/models/concerns/repository_storage_movable.rb @@ -50,7 +50,7 @@ module RepositoryStorageMovable begin storage_move.container.set_repository_read_only!(skip_git_transfer_check: true) - rescue => err + rescue StandardError => err storage_move.add_error(err.message) next false end @@ -114,7 +114,7 @@ module RepositoryStorageMovable private def container_repository_writable - add_error(_('is read only')) if container&.repository_read_only? + add_error(_('is read-only')) if container&.repository_read_only? end def error_key diff --git a/app/models/concerns/routable.rb b/app/models/concerns/routable.rb index 71d8e06de76..847abdc1b6d 100644 --- a/app/models/concerns/routable.rb +++ b/app/models/concerns/routable.rb @@ -96,11 +96,49 @@ module Routable end def full_name - route&.name || build_full_name + # We have to test for persistence as the cache key uses #updated_at + return (route&.name || build_full_name) unless persisted? && Feature.enabled?(:cached_route_lookups, self, type: :ops, default_enabled: :yaml) + + # Return the name as-is if the parent is missing + return name if route.nil? && parent.nil? && name.present? + + # If the route is already preloaded, return directly, preventing an extra load + return route.name if route_loaded? && route.present? + + # Similarly, we can allow the build if the parent is loaded + return build_full_name if parent_loaded? + + Gitlab::Cache.fetch_once([cache_key, :full_name]) do + route&.name || build_full_name + end end def full_path - route&.path || build_full_path + # We have to test for persistence as the cache key uses #updated_at + return (route&.path || build_full_path) unless persisted? && Feature.enabled?(:cached_route_lookups, self, type: :ops, default_enabled: :yaml) + + # Return the path as-is if the parent is missing + return path if route.nil? && parent.nil? && path.present? + + # If the route is already preloaded, return directly, preventing an extra load + return route.path if route_loaded? && route.present? + + # Similarly, we can allow the build if the parent is loaded + return build_full_path if parent_loaded? + + Gitlab::Cache.fetch_once([cache_key, :full_path]) do + route&.path || build_full_path + end + end + + # Overriden in the Project model + # parent_id condition prevents issues with parent reassignment + def parent_loaded? + association(:parent).loaded? + end + + def route_loaded? + association(:route).loaded? end def full_path_components @@ -124,7 +162,9 @@ module Routable def set_path_errors route_path_errors = self.errors.delete(:"route.path") - self.errors[:path].concat(route_path_errors) if route_path_errors + route_path_errors&.each do |msg| + self.errors.add(:path, msg) + end end def full_name_changed? diff --git a/app/models/concerns/services/data_fields.rb b/app/models/concerns/services/data_fields.rb index 10963e4e7d8..fd56af449bc 100644 --- a/app/models/concerns/services/data_fields.rb +++ b/app/models/concerns/services/data_fields.rb @@ -5,11 +5,11 @@ module Services extend ActiveSupport::Concern included do - belongs_to :service + belongs_to :integration, inverse_of: self.name.underscore.to_sym, foreign_key: :service_id - delegate :activated?, to: :service, allow_nil: true + delegate :activated?, to: :integration, allow_nil: true - validates :service, presence: true + validates :integration, presence: true end class_methods do diff --git a/app/models/concerns/sha256_attribute.rb b/app/models/concerns/sha256_attribute.rb index 9dfe1b77829..4921f7f1a7e 100644 --- a/app/models/concerns/sha256_attribute.rb +++ b/app/models/concerns/sha256_attribute.rb @@ -31,9 +31,9 @@ module Sha256Attribute end unless column.type == :binary - raise ArgumentError.new("sha256_attribute #{name.inspect} is invalid since the column type is not :binary") + raise ArgumentError, "sha256_attribute #{name.inspect} is invalid since the column type is not :binary" end - rescue => error + rescue StandardError => error Gitlab::AppLogger.error "Sha256Attribute initialization: #{error.message}" raise end diff --git a/app/models/concerns/sha_attribute.rb b/app/models/concerns/sha_attribute.rb index cbac6a210c7..f6f5dbce4b6 100644 --- a/app/models/concerns/sha_attribute.rb +++ b/app/models/concerns/sha_attribute.rb @@ -24,9 +24,9 @@ module ShaAttribute return unless column unless column.type == :binary - raise ArgumentError.new("sha_attribute #{name.inspect} is invalid since the column type is not :binary") + raise ArgumentError, "sha_attribute #{name.inspect} is invalid since the column type is not :binary" end - rescue => error + rescue StandardError => error Gitlab::AppLogger.error "ShaAttribute initialization: #{error.message}" raise end @@ -37,4 +37,4 @@ module ShaAttribute end end -ShaAttribute::ClassMethods.prepend_if_ee('EE::ShaAttribute') +ShaAttribute::ClassMethods.prepend_mod_with('ShaAttribute') diff --git a/app/models/concerns/sidebars/container_with_html_options.rb b/app/models/concerns/sidebars/container_with_html_options.rb deleted file mode 100644 index 12ea366c66a..00000000000 --- a/app/models/concerns/sidebars/container_with_html_options.rb +++ /dev/null @@ -1,42 +0,0 @@ -# frozen_string_literal: true - -module Sidebars - module ContainerWithHtmlOptions - # The attributes returned from this method - # will be applied to helper methods like - # `link_to` or the div containing the container. - def container_html_options - { - aria: { label: title } - }.merge(extra_container_html_options) - end - - # Classes will override mostly this method - # and not `container_html_options`. - def extra_container_html_options - {} - end - - # Attributes to pass to the html_options attribute - # in the helper method that sets the active class - # on each element. - def nav_link_html_options - {} - end - - def title - raise NotImplementedError - end - - # The attributes returned from this method - # will be applied right next to the title, - # for example in the span that renders the title. - def title_html_options - {} - end - - def link - raise NotImplementedError - end - end -end diff --git a/app/models/concerns/sidebars/has_active_routes.rb b/app/models/concerns/sidebars/has_active_routes.rb deleted file mode 100644 index e7a153f067a..00000000000 --- a/app/models/concerns/sidebars/has_active_routes.rb +++ /dev/null @@ -1,16 +0,0 @@ -# frozen_string_literal: true - -module Sidebars - module HasActiveRoutes - # This method will indicate for which paths or - # controllers, the menu or menu item should - # be set as active. - # - # The returned values are passed to the `nav_link` helper method, - # so the params can be either `path`, `page`, `controller`. - # Param 'action' is not supported. - def active_routes - {} - end - end -end diff --git a/app/models/concerns/sidebars/has_hint.rb b/app/models/concerns/sidebars/has_hint.rb deleted file mode 100644 index 21dca39dca0..00000000000 --- a/app/models/concerns/sidebars/has_hint.rb +++ /dev/null @@ -1,16 +0,0 @@ -# frozen_string_literal: true - -# This module has the necessary methods to store -# hints for menus. Hints are elements displayed -# when the user hover the menu item. -module Sidebars - module HasHint - def show_hint? - false - end - - def hint_html_options - {} - end - end -end diff --git a/app/models/concerns/sidebars/has_icon.rb b/app/models/concerns/sidebars/has_icon.rb deleted file mode 100644 index d1a87918285..00000000000 --- a/app/models/concerns/sidebars/has_icon.rb +++ /dev/null @@ -1,27 +0,0 @@ -# frozen_string_literal: true - -# This module has the necessary methods to show -# sprites or images next to the menu item. -module Sidebars - module HasIcon - def sprite_icon - nil - end - - def sprite_icon_html_options - {} - end - - def image_path - nil - end - - def image_html_options - {} - end - - def icon_or_image? - sprite_icon || image_path - end - end -end diff --git a/app/models/concerns/sidebars/has_pill.rb b/app/models/concerns/sidebars/has_pill.rb deleted file mode 100644 index ad7064fe63d..00000000000 --- a/app/models/concerns/sidebars/has_pill.rb +++ /dev/null @@ -1,21 +0,0 @@ -# frozen_string_literal: true - -# This module introduces the logic to show the "pill" element -# next to the menu item, indicating the a count. -module Sidebars - module HasPill - def has_pill? - false - end - - # In this method we will need to provide the query - # to retrieve the elements count - def pill_count - raise NotImplementedError - end - - def pill_html_options - {} - end - end -end diff --git a/app/models/concerns/sidebars/positionable_list.rb b/app/models/concerns/sidebars/positionable_list.rb deleted file mode 100644 index 30830d547f3..00000000000 --- a/app/models/concerns/sidebars/positionable_list.rb +++ /dev/null @@ -1,37 +0,0 @@ -# frozen_string_literal: true - -# This module handles elements in a list. All elements -# must have a different class -module Sidebars - module PositionableList - def add_element(list, element) - list << element - end - - def insert_element_before(list, before_element, new_element) - index = index_of(list, before_element) - - if index - list.insert(index, new_element) - else - list.unshift(new_element) - end - end - - def insert_element_after(list, after_element, new_element) - index = index_of(list, after_element) - - if index - list.insert(index + 1, new_element) - else - add_element(list, new_element) - end - end - - private - - def index_of(list, element) - list.index { |e| e.is_a?(element) } - end - end -end diff --git a/app/models/concerns/sidebars/renderable.rb b/app/models/concerns/sidebars/renderable.rb deleted file mode 100644 index a3976af8515..00000000000 --- a/app/models/concerns/sidebars/renderable.rb +++ /dev/null @@ -1,12 +0,0 @@ -# frozen_string_literal: true - -module Sidebars - module Renderable - # This method will control whether the menu or menu_item - # should be rendered. It will be overriden by specific - # classes. - def render? - true - end - end -end diff --git a/app/models/concerns/storage/legacy_namespace.rb b/app/models/concerns/storage/legacy_namespace.rb index a82cf338039..948190dfadf 100644 --- a/app/models/concerns/storage/legacy_namespace.rb +++ b/app/models/concerns/storage/legacy_namespace.rb @@ -10,7 +10,7 @@ module Storage proj_with_tags = first_project_with_container_registry_tags if proj_with_tags - raise Gitlab::UpdatePathError.new("Namespace #{name} (#{id}) cannot be moved because at least one project (e.g. #{proj_with_tags.name} (#{proj_with_tags.id})) has tags in container registry") + raise Gitlab::UpdatePathError, "Namespace #{name} (#{id}) cannot be moved because at least one project (e.g. #{proj_with_tags.name} (#{proj_with_tags.id})) has tags in container registry" end parent_was = if saved_change_to_parent? && parent_id_before_last_save.present? @@ -48,7 +48,7 @@ module Storage begin send_update_instructions write_projects_repository_config - rescue => e + rescue StandardError => e Gitlab::ErrorTracking.track_and_raise_for_dev_exception(e, full_path_before_last_save: full_path_before_last_save, full_path: full_path, @@ -83,7 +83,7 @@ module Storage # if we cannot move namespace directory we should rollback # db changes in order to prevent out of sync between db and fs - raise Gitlab::UpdatePathError.new('namespace directory cannot be moved') + raise Gitlab::UpdatePathError, 'namespace directory cannot be moved' end end end diff --git a/app/models/concerns/taskable.rb b/app/models/concerns/taskable.rb index d8867177059..4d1c1d44af7 100644 --- a/app/models/concerns/taskable.rb +++ b/app/models/concerns/taskable.rb @@ -12,7 +12,7 @@ module Taskable COMPLETED = 'completed' INCOMPLETE = 'incomplete' COMPLETE_PATTERN = /(\[[xX]\])/.freeze - INCOMPLETE_PATTERN = /(\[[\s]\])/.freeze + INCOMPLETE_PATTERN = /(\[\s\])/.freeze ITEM_PATTERN = %r{ ^ (?:(?:>\s{0,4})*) # optional blockquote characters diff --git a/app/models/concerns/throttled_touch.rb b/app/models/concerns/throttled_touch.rb index 797c46f6cc5..b5682abb229 100644 --- a/app/models/concerns/throttled_touch.rb +++ b/app/models/concerns/throttled_touch.rb @@ -6,7 +6,7 @@ module ThrottledTouch # The amount of time to wait before "touch" can update a record again. TOUCH_INTERVAL = 1.minute - def touch(*args) + def touch(*args, **kwargs) super if (Time.zone.now - updated_at) > TOUCH_INTERVAL end end diff --git a/app/models/concerns/timebox.rb b/app/models/concerns/timebox.rb index 8273059b30c..fb9a8cd312d 100644 --- a/app/models/concerns/timebox.rb +++ b/app/models/concerns/timebox.rb @@ -72,11 +72,7 @@ module Timebox groups = groups.compact if groups.is_a? Array groups = [] if groups.nil? - if Feature.enabled?(:optimized_timebox_queries, default_enabled: true) - from_union([where(project_id: projects), where(group_id: groups)], remove_duplicates: false) - else - where(project_id: projects).or(where(group_id: groups)) - end + from_union([where(project_id: projects), where(group_id: groups)], remove_duplicates: false) end # A timebox is within the timeframe (start_date, end_date) if it overlaps diff --git a/app/models/concerns/token_authenticatable.rb b/app/models/concerns/token_authenticatable.rb index 535cf25eb9d..34c8630bb90 100644 --- a/app/models/concerns/token_authenticatable.rb +++ b/app/models/concerns/token_authenticatable.rb @@ -12,7 +12,7 @@ module TokenAuthenticatable def add_authentication_token_field(token_field, options = {}) if token_authenticatable_fields.include?(token_field) - raise ArgumentError.new("#{token_field} already configured via add_authentication_token_field") + raise ArgumentError, "#{token_field} already configured via add_authentication_token_field" end token_authenticatable_fields.push(token_field) diff --git a/app/models/concerns/triggerable_hooks.rb b/app/models/concerns/triggerable_hooks.rb index db5df6c2c9f..8fe34632430 100644 --- a/app/models/concerns/triggerable_hooks.rb +++ b/app/models/concerns/triggerable_hooks.rb @@ -29,11 +29,11 @@ module TriggerableHooks callable_scopes = triggers.keys + [:all] return none unless callable_scopes.include?(trigger) - public_send(trigger) # rubocop:disable GitlabSecurity/PublicSend + executable.public_send(trigger) # rubocop:disable GitlabSecurity/PublicSend end def select_active(hooks_scope, data) - select do |hook| + executable.select do |hook| ActiveHookFilter.new(hook).matches?(hooks_scope, data) end end diff --git a/app/models/concerns/vulnerability_finding_helpers.rb b/app/models/concerns/vulnerability_finding_helpers.rb index cf50305faab..f0e5e010e70 100644 --- a/app/models/concerns/vulnerability_finding_helpers.rb +++ b/app/models/concerns/vulnerability_finding_helpers.rb @@ -4,4 +4,4 @@ module VulnerabilityFindingHelpers extend ActiveSupport::Concern end -VulnerabilityFindingHelpers.prepend_if_ee('EE::VulnerabilityFindingHelpers') +VulnerabilityFindingHelpers.prepend_mod_with('VulnerabilityFindingHelpers') diff --git a/app/models/concerns/vulnerability_finding_signature_helpers.rb b/app/models/concerns/vulnerability_finding_signature_helpers.rb index f57e3cb0bfb..f98c1e93aaf 100644 --- a/app/models/concerns/vulnerability_finding_signature_helpers.rb +++ b/app/models/concerns/vulnerability_finding_signature_helpers.rb @@ -4,4 +4,4 @@ module VulnerabilityFindingSignatureHelpers extend ActiveSupport::Concern end -VulnerabilityFindingSignatureHelpers.prepend_if_ee('EE::VulnerabilityFindingSignatureHelpers') +VulnerabilityFindingSignatureHelpers.prepend_mod_with('VulnerabilityFindingSignatureHelpers') diff --git a/app/models/concerns/x509_serial_number_attribute.rb b/app/models/concerns/x509_serial_number_attribute.rb index d2a5c736604..dbba80eff53 100644 --- a/app/models/concerns/x509_serial_number_attribute.rb +++ b/app/models/concerns/x509_serial_number_attribute.rb @@ -31,9 +31,9 @@ module X509SerialNumberAttribute end unless column.type == :binary - raise ArgumentError.new("x509_serial_number_attribute #{name.inspect} is invalid since the column type is not :binary") + raise ArgumentError, "x509_serial_number_attribute #{name.inspect} is invalid since the column type is not :binary" end - rescue => error + rescue StandardError => error Gitlab::AppLogger.error "X509SerialNumberAttribute initialization: #{error.message}" raise end |