Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-12-20 16:37:47 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-12-20 16:37:47 +0300
commitaee0a117a889461ce8ced6fcf73207fe017f1d99 (patch)
tree891d9ef189227a8445d83f35c1b0fc99573f4380 /app/models/concerns
parent8d46af3258650d305f53b819eabf7ab18d22f59e (diff)
Add latest changes from gitlab-org/gitlab@14-6-stable-eev14.6.0-rc42
Diffstat (limited to 'app/models/concerns')
-rw-r--r--app/models/concerns/after_commit_queue.rb50
-rw-r--r--app/models/concerns/calloutable.rb15
-rw-r--r--app/models/concerns/ci/contextable.rb27
-rw-r--r--app/models/concerns/commit_signature.rb50
-rw-r--r--app/models/concerns/diff_positionable_note.rb9
-rw-r--r--app/models/concerns/enums/ci/commit_status.rb1
-rw-r--r--app/models/concerns/import_state/sidekiq_job_tracker.rb2
-rw-r--r--app/models/concerns/incident_management/escalatable.rb2
-rw-r--r--app/models/concerns/issuable.rb18
-rw-r--r--app/models/concerns/loose_foreign_key.rb79
-rw-r--r--app/models/concerns/merge_request_reviewer_state.rb6
-rw-r--r--app/models/concerns/packages/debian/component_file.rb8
-rw-r--r--app/models/concerns/participable.rb18
-rw-r--r--app/models/concerns/partitioned_table.rb3
-rw-r--r--app/models/concerns/relative_positioning.rb18
-rw-r--r--app/models/concerns/resolvable_discussion.rb5
-rw-r--r--app/models/concerns/sha_attribute.rb5
-rw-r--r--app/models/concerns/token_authenticatable_strategies/encryption_helper.rb2
-rw-r--r--app/models/concerns/transactions.rb12
19 files changed, 189 insertions, 141 deletions
diff --git a/app/models/concerns/after_commit_queue.rb b/app/models/concerns/after_commit_queue.rb
new file mode 100644
index 00000000000..7f525bec9e9
--- /dev/null
+++ b/app/models/concerns/after_commit_queue.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+module AfterCommitQueue
+ extend ActiveSupport::Concern
+
+ included do
+ after_commit :_run_after_commit_queue
+ after_rollback :_clear_after_commit_queue
+ end
+
+ def run_after_commit(&block)
+ _after_commit_queue << block if block
+
+ true
+ end
+
+ def run_after_commit_or_now(&block)
+ if self.class.inside_transaction?
+ if connection.current_transaction.records&.include?(self)
+ run_after_commit(&block)
+ else
+ # If the current transaction does not include this record, we can run
+ # the block now, even if it queues a Sidekiq job.
+ Sidekiq::Worker.skipping_transaction_check do
+ instance_eval(&block)
+ end
+ end
+ else
+ instance_eval(&block)
+ end
+
+ true
+ end
+
+ protected
+
+ def _run_after_commit_queue
+ while action = _after_commit_queue.pop
+ self.instance_eval(&action)
+ end
+ end
+
+ def _after_commit_queue
+ @after_commit_queue ||= []
+ end
+
+ def _clear_after_commit_queue
+ _after_commit_queue.clear
+ end
+end
diff --git a/app/models/concerns/calloutable.rb b/app/models/concerns/calloutable.rb
deleted file mode 100644
index 8b9cfae6a32..00000000000
--- a/app/models/concerns/calloutable.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-module Calloutable
- extend ActiveSupport::Concern
-
- included do
- belongs_to :user
-
- validates :user, presence: true
- end
-
- def dismissed_after?(dismissed_after)
- dismissed_at > dismissed_after
- end
-end
diff --git a/app/models/concerns/ci/contextable.rb b/app/models/concerns/ci/contextable.rb
index a9589cea5e9..12ddbc2cc40 100644
--- a/app/models/concerns/ci/contextable.rb
+++ b/app/models/concerns/ci/contextable.rb
@@ -13,7 +13,6 @@ module Ci
track_duration do
variables = pipeline.variables_builder.scoped_variables(self, environment: environment, dependencies: dependencies)
- variables.concat(predefined_variables) unless pipeline.predefined_vars_in_builder_enabled?
variables.concat(project.predefined_variables)
variables.concat(pipeline.predefined_variables)
variables.concat(runner.predefined_variables) if runnable? && runner
@@ -71,24 +70,6 @@ module Ci
end
end
- def predefined_variables
- Gitlab::Ci::Variables::Collection.new.tap do |variables|
- variables.append(key: 'CI_JOB_NAME', value: name)
- variables.append(key: 'CI_JOB_STAGE', value: stage)
- variables.append(key: 'CI_JOB_MANUAL', value: 'true') if action?
- variables.append(key: 'CI_PIPELINE_TRIGGERED', value: 'true') if trigger_request
-
- variables.append(key: 'CI_NODE_INDEX', value: self.options[:instance].to_s) if self.options&.include?(:instance)
- variables.append(key: 'CI_NODE_TOTAL', value: ci_node_total_value.to_s)
-
- # legacy variables
- variables.append(key: 'CI_BUILD_NAME', value: name)
- variables.append(key: 'CI_BUILD_STAGE', value: stage)
- variables.append(key: 'CI_BUILD_TRIGGERED', value: 'true') if trigger_request
- variables.append(key: 'CI_BUILD_MANUAL', value: 'true') if action?
- end
- end
-
def kubernetes_variables
::Gitlab::Ci::Variables::Collection.new.tap do |collection|
# Should get merged with the cluster kubeconfig in deployment_variables, see
@@ -123,13 +104,5 @@ module Ci
def secret_project_variables(environment: expanded_environment_name)
project.ci_variables_for(ref: git_ref, environment: environment)
end
-
- private
-
- def ci_node_total_value
- parallel = self.options&.dig(:parallel)
- parallel = parallel.dig(:total) if parallel.is_a?(Hash)
- parallel || 1
- end
end
end
diff --git a/app/models/concerns/commit_signature.rb b/app/models/concerns/commit_signature.rb
new file mode 100644
index 00000000000..5bdfa9a2966
--- /dev/null
+++ b/app/models/concerns/commit_signature.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+module CommitSignature
+ extend ActiveSupport::Concern
+
+ included do
+ include ShaAttribute
+
+ sha_attribute :commit_sha
+
+ enum verification_status: {
+ unverified: 0,
+ verified: 1,
+ same_user_different_email: 2,
+ other_user: 3,
+ unverified_key: 4,
+ unknown_key: 5,
+ multiple_signatures: 6
+ }
+
+ belongs_to :project, class_name: 'Project', foreign_key: 'project_id', optional: false
+
+ validates :commit_sha, presence: true
+ validates :project_id, presence: true
+
+ scope :by_commit_sha, ->(shas) { where(commit_sha: shas) }
+ end
+
+ class_methods do
+ def safe_create!(attributes)
+ create_with(attributes)
+ .safe_find_or_create_by!(commit_sha: attributes[:commit_sha])
+ end
+
+ # Find commits that are lacking a signature in the database at present
+ def unsigned_commit_shas(commit_shas)
+ return [] if commit_shas.empty?
+
+ signed = by_commit_sha(commit_shas).pluck(:commit_sha)
+ commit_shas - signed
+ end
+ end
+
+ def commit
+ project.commit(commit_sha)
+ end
+
+ def user
+ commit.committer
+ end
+end
diff --git a/app/models/concerns/diff_positionable_note.rb b/app/models/concerns/diff_positionable_note.rb
index b13ca4bf06e..051158e5de5 100644
--- a/app/models/concerns/diff_positionable_note.rb
+++ b/app/models/concerns/diff_positionable_note.rb
@@ -3,7 +3,6 @@ module DiffPositionableNote
extend ActiveSupport::Concern
included do
- delegate :on_text?, :on_image?, to: :position, allow_nil: true
before_validation :set_original_position, on: :create
before_validation :update_position, on: :create, if: :on_text?, unless: :importing?
@@ -34,6 +33,14 @@ module DiffPositionableNote
end
end
+ def on_text?
+ !!position&.on_text?
+ end
+
+ def on_image?
+ !!position&.on_image?
+ end
+
def supported?
for_commit? || self.noteable.has_complete_diff_refs?
end
diff --git a/app/models/concerns/enums/ci/commit_status.rb b/app/models/concerns/enums/ci/commit_status.rb
index 1b4cc14f4a2..312b88a4d6d 100644
--- a/app/models/concerns/enums/ci/commit_status.rb
+++ b/app/models/concerns/enums/ci/commit_status.rb
@@ -28,6 +28,7 @@ module Enums
trace_size_exceeded: 19,
builds_disabled: 20,
environment_creation_failure: 21,
+ deployment_rejected: 22,
insufficient_bridge_permissions: 1_001,
downstream_bridge_project_not_found: 1_002,
invalid_bridge_trigger: 1_003,
diff --git a/app/models/concerns/import_state/sidekiq_job_tracker.rb b/app/models/concerns/import_state/sidekiq_job_tracker.rb
index b7d0ed0f51b..340bf4279bc 100644
--- a/app/models/concerns/import_state/sidekiq_job_tracker.rb
+++ b/app/models/concerns/import_state/sidekiq_job_tracker.rb
@@ -15,7 +15,7 @@ module ImportState
def refresh_jid_expiration
return unless jid
- Gitlab::SidekiqStatus.set(jid, Gitlab::Import::StuckImportJob::IMPORT_JOBS_EXPIRATION)
+ Gitlab::SidekiqStatus.set(jid, Gitlab::Import::StuckImportJob::IMPORT_JOBS_EXPIRATION, value: 2)
end
def self.jid_by(project_id:, status:)
diff --git a/app/models/concerns/incident_management/escalatable.rb b/app/models/concerns/incident_management/escalatable.rb
index 78dce63f59e..81eef50603a 100644
--- a/app/models/concerns/incident_management/escalatable.rb
+++ b/app/models/concerns/incident_management/escalatable.rb
@@ -102,3 +102,5 @@ module IncidentManagement
end
end
end
+
+::IncidentManagement::Escalatable.prepend_mod
diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb
index 4273eb331a1..dcd80201d3f 100644
--- a/app/models/concerns/issuable.rb
+++ b/app/models/concerns/issuable.rb
@@ -43,7 +43,7 @@ module Issuable
included do
cache_markdown_field :title, pipeline: :single_line
- cache_markdown_field :description, issuable_state_filter_enabled: true
+ cache_markdown_field :description, issuable_reference_expansion_enabled: true
redact_field :description
@@ -61,6 +61,16 @@ module Issuable
# We check first if we're loaded to not load unnecessarily.
loaded? && to_a.all? { |note| note.association(:award_emoji).loaded? }
end
+
+ def projects_loaded?
+ # We check first if we're loaded to not load unnecessarily.
+ loaded? && to_a.all? { |note| note.association(:project).loaded? }
+ end
+
+ def system_note_metadata_loaded?
+ # We check first if we're loaded to not load unnecessarily.
+ loaded? && to_a.all? { |note| note.association(:system_note_metadata).loaded? }
+ end
end
has_many :note_authors, -> { distinct }, through: :notes, source: :author
@@ -183,6 +193,10 @@ module Issuable
incident?
end
+ def supports_escalation?
+ incident?
+ end
+
def incident?
is_a?(Issue) && super
end
@@ -524,6 +538,8 @@ module Issuable
includes = []
includes << :author unless notes.authors_loaded?
includes << :award_emoji unless notes.award_emojis_loaded?
+ includes << :project unless notes.projects_loaded?
+ includes << :system_note_metadata unless notes.system_note_metadata_loaded?
if includes.any?
notes.includes(includes)
diff --git a/app/models/concerns/loose_foreign_key.rb b/app/models/concerns/loose_foreign_key.rb
deleted file mode 100644
index 102292672b3..00000000000
--- a/app/models/concerns/loose_foreign_key.rb
+++ /dev/null
@@ -1,79 +0,0 @@
-# frozen_string_literal: true
-
-module LooseForeignKey
- extend ActiveSupport::Concern
-
- # This concern adds loose foreign key support to ActiveRecord models.
- # Loose foreign keys allow delayed processing of associated database records
- # with similar guarantees than a database foreign key.
- #
- # Prerequisites:
- #
- # To start using the concern, you'll need to install a database trigger to the parent
- # table in a standard DB migration (not post-migration).
- #
- # > track_record_deletions(:projects)
- #
- # Usage:
- #
- # > class Ci::Build < ApplicationRecord
- # >
- # > loose_foreign_key :security_scans, :build_id, on_delete: :async_delete
- # >
- # > # associations can be still defined, the dependent options is no longer necessary:
- # > has_many :security_scans, class_name: 'Security::Scan'
- # >
- # > end
- #
- # Options for on_delete:
- #
- # - :async_delete - deletes the children rows via an asynchronous process.
- # - :async_nullify - sets the foreign key column to null via an asynchronous process.
- #
- # How it works:
- #
- # When adding loose foreign key support to the table, a DELETE trigger is installed
- # which tracks the record deletions (stores primary key value of the deleted row) in
- # a database table.
- #
- # These deletion records are processed asynchronously and records are cleaned up
- # according to the loose foreign key definitions described in the model.
- #
- # The cleanup happens in batches, which reduces the likelyhood of statement timeouts.
- #
- # When all associations related to the deleted record are cleaned up, the record itself
- # is deleted.
- included do
- class_attribute :loose_foreign_key_definitions, default: []
- end
-
- class_methods do
- def loose_foreign_key(to_table, column, options)
- symbolized_options = options.symbolize_keys
-
- unless base_class?
- raise <<~MSG
- loose_foreign_key can be only used on base classes, inherited classes are not supported.
- Please define the loose_foreign_key on the #{base_class.name} class.
- MSG
- end
-
- on_delete_options = %i[async_delete async_nullify]
-
- unless on_delete_options.include?(symbolized_options[:on_delete]&.to_sym)
- raise "Invalid on_delete option given: #{symbolized_options[:on_delete]}. Valid options: #{on_delete_options.join(', ')}"
- end
-
- definition = ActiveRecord::ConnectionAdapters::ForeignKeyDefinition.new(
- table_name.to_s,
- to_table.to_s,
- {
- column: column.to_s,
- on_delete: symbolized_options[:on_delete].to_sym
- }
- )
-
- self.loose_foreign_key_definitions += [definition]
- end
- end
-end
diff --git a/app/models/concerns/merge_request_reviewer_state.rb b/app/models/concerns/merge_request_reviewer_state.rb
index 216a3a0bd64..5859f43a70c 100644
--- a/app/models/concerns/merge_request_reviewer_state.rb
+++ b/app/models/concerns/merge_request_reviewer_state.rb
@@ -15,11 +15,5 @@ module MergeRequestReviewerState
inclusion: { in: self.states.keys }
after_initialize :set_state, unless: :persisted?
-
- def set_state
- if Feature.enabled?(:mr_attention_requests, self.merge_request&.project, default_enabled: :yaml)
- self.state = :attention_requested
- end
- end
end
end
diff --git a/app/models/concerns/packages/debian/component_file.rb b/app/models/concerns/packages/debian/component_file.rb
index 9cf66c756a0..77409549e85 100644
--- a/app/models/concerns/packages/debian/component_file.rb
+++ b/app/models/concerns/packages/debian/component_file.rb
@@ -20,13 +20,13 @@ module Packages
belongs_to :component, class_name: "Packages::Debian::#{container_type.capitalize}Component", inverse_of: :files
belongs_to :architecture, class_name: "Packages::Debian::#{container_type.capitalize}Architecture", inverse_of: :files, optional: true
- enum file_type: { packages: 1, source: 2, di_packages: 3 }
+ enum file_type: { packages: 1, sources: 2, di_packages: 3 }
enum compression_type: { gz: 1, bz2: 2, xz: 3 }
validates :component, presence: true
validates :file_type, presence: true
- validates :architecture, presence: true, unless: :source?
- validates :architecture, absence: true, if: :source?
+ validates :architecture, presence: true, unless: :sources?
+ validates :architecture, absence: true, if: :sources?
validates :file, length: { minimum: 0, allow_nil: false }
validates :size, presence: true
validates :file_store, presence: true
@@ -81,7 +81,7 @@ module Packages
case file_type
when 'packages'
"#{component.name}/binary-#{architecture.name}/#{file_name}#{extension}"
- when 'source'
+ when 'sources'
"#{component.name}/source/#{file_name}#{extension}"
when 'di_packages'
"#{component.name}/debian-installer/binary-#{architecture.name}/#{file_name}#{extension}"
diff --git a/app/models/concerns/participable.rb b/app/models/concerns/participable.rb
index 25410a859e9..1663aa6c886 100644
--- a/app/models/concerns/participable.rb
+++ b/app/models/concerns/participable.rb
@@ -60,6 +60,15 @@ module Participable
filtered_participants_hash[user]
end
+ # Returns only participants visible for the user
+ #
+ # Returns an Array of User instances.
+ def visible_participants(user)
+ return participants(user) unless Feature.enabled?(:verify_participants_access, project, default_enabled: :yaml)
+
+ filter_by_ability(raw_participants(user, verify_access: true))
+ end
+
# Checks if the user is a participant in a discussion.
#
# This method processes attributes of objects in breadth-first order.
@@ -84,8 +93,7 @@ module Participable
end
end
- def raw_participants(current_user = nil)
- current_user ||= author
+ def raw_participants(current_user = nil, verify_access: false)
ext = Gitlab::ReferenceExtractor.new(project, current_user)
participants = Set.new
process = [self]
@@ -97,6 +105,8 @@ module Participable
when User
participants << source
when Participable
+ next unless !verify_access || source_visible_to_user?(source, current_user)
+
source.class.participant_attrs.each do |attr|
if attr.respond_to?(:call)
source.instance_exec(current_user, ext, &attr)
@@ -116,6 +126,10 @@ module Participable
participants.merge(ext.users)
end
+ def source_visible_to_user?(source, user)
+ Ability.allowed?(user, "read_#{source.model_name.element}".to_sym, source)
+ end
+
def filter_by_ability(participants)
case self
when PersonalSnippet
diff --git a/app/models/concerns/partitioned_table.rb b/app/models/concerns/partitioned_table.rb
index 23d2d00b346..f95f9dd8ad7 100644
--- a/app/models/concerns/partitioned_table.rb
+++ b/app/models/concerns/partitioned_table.rb
@@ -7,7 +7,8 @@ module PartitionedTable
attr_reader :partitioning_strategy
PARTITIONING_STRATEGIES = {
- monthly: Gitlab::Database::Partitioning::MonthlyStrategy
+ monthly: Gitlab::Database::Partitioning::MonthlyStrategy,
+ sliding_list: Gitlab::Database::Partitioning::SlidingListStrategy
}.freeze
def partitioned_by(partitioning_key, strategy:, **kwargs)
diff --git a/app/models/concerns/relative_positioning.rb b/app/models/concerns/relative_positioning.rb
index c32e499c329..9069d3088cd 100644
--- a/app/models/concerns/relative_positioning.rb
+++ b/app/models/concerns/relative_positioning.rb
@@ -168,6 +168,24 @@ module RelativePositioning
self.relative_position = MIN_POSITION
end
+ def next_object_by_relative_position(ignoring: nil, order: :asc)
+ relation = relative_positioning_scoped_items(ignoring: ignoring).reorder(relative_position: order)
+
+ relation = if order == :asc
+ relation.where(self.class.arel_table[:relative_position].gt(relative_position))
+ else
+ relation.where(self.class.arel_table[:relative_position].lt(relative_position))
+ end
+
+ relation.first
+ end
+
+ def relative_positioning_scoped_items(ignoring: nil)
+ relation = self.class.relative_positioning_query_base(self)
+ relation = exclude_self(relation, excluded: ignoring) if ignoring.present?
+ relation
+ end
+
# This method is used during rebalancing - override it to customise the update
# logic:
def update_relative_siblings(relation, range, delta)
diff --git a/app/models/concerns/resolvable_discussion.rb b/app/models/concerns/resolvable_discussion.rb
index 60e1dde17b9..aae338e9759 100644
--- a/app/models/concerns/resolvable_discussion.rb
+++ b/app/models/concerns/resolvable_discussion.rb
@@ -30,11 +30,14 @@ module ResolvableDiscussion
delegate :resolved_at,
:resolved_by,
- :resolved_by_push?,
to: :last_resolved_note,
allow_nil: true
end
+ def resolved_by_push?
+ !!last_resolved_note&.resolved_by_push?
+ end
+
def resolvable?
strong_memoize(:resolvable) do
potentially_resolvable? && notes.any?(&:resolvable?)
diff --git a/app/models/concerns/sha_attribute.rb b/app/models/concerns/sha_attribute.rb
index ba7c6c0cd8b..e49f4d03bda 100644
--- a/app/models/concerns/sha_attribute.rb
+++ b/app/models/concerns/sha_attribute.rb
@@ -3,11 +3,14 @@
module ShaAttribute
extend ActiveSupport::Concern
+ # Needed for the database method
+ include DatabaseReflection
+
class_methods do
def sha_attribute(name)
return if ENV['STATIC_VERIFICATION']
- validate_binary_column_exists!(name) if Rails.env.development?
+ validate_binary_column_exists!(name) if Rails.env.development? || Rails.env.test?
attribute(name, Gitlab::Database::ShaAttribute.new)
end
diff --git a/app/models/concerns/token_authenticatable_strategies/encryption_helper.rb b/app/models/concerns/token_authenticatable_strategies/encryption_helper.rb
index 3be82ed72d3..447521ad8c1 100644
--- a/app/models/concerns/token_authenticatable_strategies/encryption_helper.rb
+++ b/app/models/concerns/token_authenticatable_strategies/encryption_helper.rb
@@ -11,7 +11,7 @@ module TokenAuthenticatableStrategies
# The pattern of the token is "#{DYNAMIC_NONCE_IDENTIFIER}#{token}#{iv_of_12_characters}"
if token.start_with?(DYNAMIC_NONCE_IDENTIFIER) && token.size > NONCE_SIZE + DYNAMIC_NONCE_IDENTIFIER.size
token_to_decrypt = token[1...-NONCE_SIZE]
- iv = token[-NONCE_SIZE..-1]
+ iv = token[-NONCE_SIZE..]
Gitlab::CryptoHelper.aes256_gcm_decrypt(token_to_decrypt, nonce: iv)
else
diff --git a/app/models/concerns/transactions.rb b/app/models/concerns/transactions.rb
index a186ebc8475..1c9bd8274f5 100644
--- a/app/models/concerns/transactions.rb
+++ b/app/models/concerns/transactions.rb
@@ -8,7 +8,7 @@ module Transactions
# transaction. Handles special cases when running inside a test environment,
# where tests may be wrapped in transactions
def inside_transaction?
- base = Rails.env.test? ? @open_transactions_baseline.to_i : 0
+ base = Rails.env.test? ? open_transactions_baseline.to_i : 0
connection.open_transactions > base
end
@@ -24,5 +24,15 @@ module Transactions
def reset_open_transactions_baseline
@open_transactions_baseline = 0
end
+
+ def open_transactions_baseline
+ return unless Rails.env.test?
+
+ if @open_transactions_baseline.nil?
+ return self == ApplicationRecord ? nil : superclass.open_transactions_baseline
+ end
+
+ @open_transactions_baseline
+ end
end
end