summaryrefslogtreecommitdiff
path: root/app/models
diff options
context:
space:
mode:
Diffstat (limited to 'app/models')
-rw-r--r--app/models/ci/build.rb2
-rw-r--r--app/models/ci/pipeline.rb2
-rw-r--r--app/models/concerns/cache_markdown_field.rb15
-rw-r--r--app/models/concerns/ci/contextable.rb1
-rw-r--r--app/models/concerns/from_union.rb6
-rw-r--r--app/models/concerns/has_status.rb66
-rw-r--r--app/models/concerns/mentionable.rb3
-rw-r--r--app/models/concerns/relative_positioning.rb2
-rw-r--r--app/models/concerns/routable.rb2
-rw-r--r--app/models/concerns/token_authenticatable.rb2
-rw-r--r--app/models/email.rb3
-rw-r--r--app/models/merge_requests_closing_issues.rb2
-rw-r--r--app/models/namespace.rb3
-rw-r--r--app/models/pages_domain.rb10
-rw-r--r--app/models/project.rb12
-rw-r--r--app/models/project_services/ci_service.rb2
-rw-r--r--app/models/project_services/slash_commands_service.rb2
-rw-r--r--app/models/user.rb5
18 files changed, 78 insertions, 62 deletions
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index ae7a1108841..635fcc86166 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -578,7 +578,7 @@ module Ci
end
def valid_token?(token)
- self.token && ActiveSupport::SecurityUtils.variable_size_secure_compare(token, self.token)
+ self.token && ActiveSupport::SecurityUtils.secure_compare(token, self.token)
end
def has_tags?
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index 20ca4a9ab24..2262282e647 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -196,7 +196,7 @@ module Ci
sql = 'CASE ci_pipelines.source WHEN (?) THEN 0 ELSE 1 END, ci_pipelines.id DESC'
query = ApplicationRecord.send(:sanitize_sql_array, [sql, sources[:merge_request_event]]) # rubocop:disable GitlabSecurity/PublicSend
- order(query)
+ order(Arel.sql(query))
end
scope :for_user, -> (user) { where(user: user) }
diff --git a/app/models/concerns/cache_markdown_field.rb b/app/models/concerns/cache_markdown_field.rb
index 42203a5f214..9713e79f525 100644
--- a/app/models/concerns/cache_markdown_field.rb
+++ b/app/models/concerns/cache_markdown_field.rb
@@ -87,6 +87,16 @@ module CacheMarkdownField
__send__(cached_markdown_fields.html_field(markdown_field)) # rubocop:disable GitlabSecurity/PublicSend
end
+ # Updates the markdown cache if necessary, then returns the field
+ # Unlike `cached_html_for` it returns `nil` if the field does not exist
+ def updated_cached_html_for(markdown_field)
+ return unless cached_markdown_fields.markdown_fields.include?(markdown_field)
+
+ refresh_markdown_cache if attribute_invalidated?(cached_markdown_fields.html_field(markdown_field))
+
+ cached_html_for(markdown_field)
+ end
+
def latest_cached_markdown_version
@latest_cached_markdown_version ||= (Gitlab::MarkdownCache::CACHE_COMMONMARK_VERSION << 16) | local_version
end
@@ -139,8 +149,9 @@ module CacheMarkdownField
# The HTML becomes invalid if any dependent fields change. For now, assume
# author and project invalidate the cache in all circumstances.
define_method(invalidation_method) do
- invalidations = changed_markdown_fields & [markdown_field.to_s, *INVALIDATED_BY]
- invalidations.delete(markdown_field.to_s) if changed_markdown_fields.include?("#{markdown_field}_html")
+ changed_fields = changed_attributes.keys
+ invalidations = changed_fields & [markdown_field.to_s, *INVALIDATED_BY]
+ invalidations.delete(markdown_field.to_s) if changed_fields.include?("#{markdown_field}_html")
!invalidations.empty? || !cached_html_up_to_date?(markdown_field)
end
end
diff --git a/app/models/concerns/ci/contextable.rb b/app/models/concerns/ci/contextable.rb
index e1d5ce7f7d4..91dda803031 100644
--- a/app/models/concerns/ci/contextable.rb
+++ b/app/models/concerns/ci/contextable.rb
@@ -59,6 +59,7 @@ module Ci
variables.append(key: 'CI', value: 'true')
variables.append(key: 'GITLAB_CI', value: 'true')
variables.append(key: 'GITLAB_FEATURES', value: project.licensed_features.join(','))
+ variables.append(key: 'CI_SERVER_HOST', value: Gitlab.config.gitlab.host)
variables.append(key: 'CI_SERVER_NAME', value: 'GitLab')
variables.append(key: 'CI_SERVER_VERSION', value: Gitlab::VERSION)
variables.append(key: 'CI_SERVER_VERSION_MAJOR', value: Gitlab.version_info.major.to_s)
diff --git a/app/models/concerns/from_union.rb b/app/models/concerns/from_union.rb
index 9b8595b1211..e28dee34815 100644
--- a/app/models/concerns/from_union.rb
+++ b/app/models/concerns/from_union.rb
@@ -40,11 +40,7 @@ module FromUnion
.new(members, remove_duplicates: remove_duplicates)
.to_sql
- # This pattern is necessary as a bug in Rails 4 can cause the use of
- # `from("string here").includes(:foo)` to break ActiveRecord. This is
- # fixed in https://github.com/rails/rails/pull/25374, which is released as
- # part of Rails 5.
- from([Arel.sql("(#{union}) #{alias_as}")])
+ from(Arel.sql("(#{union}) #{alias_as}"))
end
# rubocop: enable Gitlab/Union
end
diff --git a/app/models/concerns/has_status.rb b/app/models/concerns/has_status.rb
index 78bcce2f592..27a5c3d5286 100644
--- a/app/models/concerns/has_status.rb
+++ b/app/models/concerns/has_status.rb
@@ -33,22 +33,24 @@ module HasStatus
canceled = scope_relevant.canceled.select('count(*)').to_sql
warnings = scope_warnings.select('count(*) > 0').to_sql.presence || 'false'
- "(CASE
- WHEN (#{builds})=(#{skipped}) AND (#{warnings}) THEN 'success'
- WHEN (#{builds})=(#{skipped}) THEN 'skipped'
- WHEN (#{builds})=(#{success}) THEN 'success'
- WHEN (#{builds})=(#{created}) THEN 'created'
- WHEN (#{builds})=(#{preparing}) THEN 'preparing'
- WHEN (#{builds})=(#{success})+(#{skipped}) THEN 'success'
- WHEN (#{builds})=(#{success})+(#{skipped})+(#{canceled}) THEN 'canceled'
- WHEN (#{builds})=(#{created})+(#{skipped})+(#{pending}) THEN 'pending'
- WHEN (#{running})+(#{pending})>0 THEN 'running'
- WHEN (#{manual})>0 THEN 'manual'
- WHEN (#{scheduled})>0 THEN 'scheduled'
- WHEN (#{preparing})>0 THEN 'preparing'
- WHEN (#{created})>0 THEN 'running'
- ELSE 'failed'
- END)"
+ Arel.sql(
+ "(CASE
+ WHEN (#{builds})=(#{skipped}) AND (#{warnings}) THEN 'success'
+ WHEN (#{builds})=(#{skipped}) THEN 'skipped'
+ WHEN (#{builds})=(#{success}) THEN 'success'
+ WHEN (#{builds})=(#{created}) THEN 'created'
+ WHEN (#{builds})=(#{preparing}) THEN 'preparing'
+ WHEN (#{builds})=(#{success})+(#{skipped}) THEN 'success'
+ WHEN (#{builds})=(#{success})+(#{skipped})+(#{canceled}) THEN 'canceled'
+ WHEN (#{builds})=(#{created})+(#{skipped})+(#{pending}) THEN 'pending'
+ WHEN (#{running})+(#{pending})>0 THEN 'running'
+ WHEN (#{manual})>0 THEN 'manual'
+ WHEN (#{scheduled})>0 THEN 'scheduled'
+ WHEN (#{preparing})>0 THEN 'preparing'
+ WHEN (#{created})>0 THEN 'running'
+ ELSE 'failed'
+ END)"
+ )
end
def status
@@ -88,22 +90,22 @@ module HasStatus
state :scheduled, value: 'scheduled'
end
- scope :created, -> { where(status: 'created') }
- scope :preparing, -> { where(status: 'preparing') }
- scope :relevant, -> { where(status: AVAILABLE_STATUSES - ['created']) }
- scope :running, -> { where(status: 'running') }
- scope :pending, -> { where(status: 'pending') }
- scope :success, -> { where(status: 'success') }
- scope :failed, -> { where(status: 'failed') }
- scope :canceled, -> { where(status: 'canceled') }
- scope :skipped, -> { where(status: 'skipped') }
- scope :manual, -> { where(status: 'manual') }
- scope :scheduled, -> { where(status: 'scheduled') }
- scope :alive, -> { where(status: [:created, :preparing, :pending, :running]) }
- scope :created_or_pending, -> { where(status: [:created, :pending]) }
- scope :running_or_pending, -> { where(status: [:running, :pending]) }
- scope :finished, -> { where(status: [:success, :failed, :canceled]) }
- scope :failed_or_canceled, -> { where(status: [:failed, :canceled]) }
+ scope :created, -> { with_status(:created) }
+ scope :preparing, -> { with_status(:preparing) }
+ scope :relevant, -> { without_status(:created) }
+ scope :running, -> { with_status(:running) }
+ scope :pending, -> { with_status(:pending) }
+ scope :success, -> { with_status(:success) }
+ scope :failed, -> { with_status(:failed) }
+ scope :canceled, -> { with_status(:canceled) }
+ scope :skipped, -> { with_status(:skipped) }
+ scope :manual, -> { with_status(:manual) }
+ scope :scheduled, -> { with_status(:scheduled) }
+ scope :alive, -> { with_status(:created, :preparing, :pending, :running) }
+ scope :created_or_pending, -> { with_status(:created, :pending) }
+ scope :running_or_pending, -> { with_status(:running, :pending) }
+ scope :finished, -> { with_status(:success, :failed, :canceled) }
+ scope :failed_or_canceled, -> { with_status(:failed, :canceled) }
scope :cancelable, -> do
where(status: [:running, :preparing, :pending, :created, :scheduled])
diff --git a/app/models/concerns/mentionable.rb b/app/models/concerns/mentionable.rb
index 0d88b34fb48..2f3f9b399d9 100644
--- a/app/models/concerns/mentionable.rb
+++ b/app/models/concerns/mentionable.rb
@@ -63,6 +63,9 @@ module Mentionable
skip_project_check: skip_project_check?
).merge(mentionable_params)
+ cached_html = self.try(:updated_cached_html_for, attr.to_sym)
+ options[:rendered] = cached_html if cached_html
+
extractor.analyze(text, options)
end
diff --git a/app/models/concerns/relative_positioning.rb b/app/models/concerns/relative_positioning.rb
index 22b6b1d720c..e4fe46d722a 100644
--- a/app/models/concerns/relative_positioning.rb
+++ b/app/models/concerns/relative_positioning.rb
@@ -179,7 +179,7 @@ module RelativePositioning
relation = yield relation if block_given?
relation
- .pluck(self.class.parent_column, "#{calculation}(relative_position) AS position")
+ .pluck(self.class.parent_column, Arel.sql("#{calculation}(relative_position) AS position"))
.first&.
last
end
diff --git a/app/models/concerns/routable.rb b/app/models/concerns/routable.rb
index b9ffc64e4a9..9becab632f3 100644
--- a/app/models/concerns/routable.rb
+++ b/app/models/concerns/routable.rb
@@ -46,7 +46,7 @@ module Routable
# See https://gitlab.com/gitlab-org/gitlab-ce/issues/18603. Also note that
# our unique index is case-sensitive in Postgres.
binary = Gitlab::Database.mysql? ? 'BINARY' : ''
- order_sql = "(CASE WHEN #{binary} routes.path = #{connection.quote(path)} THEN 0 ELSE 1 END)"
+ order_sql = Arel.sql("(CASE WHEN #{binary} routes.path = #{connection.quote(path)} THEN 0 ELSE 1 END)")
found = where_full_path_in([path]).reorder(order_sql).take
return found if found
diff --git a/app/models/concerns/token_authenticatable.rb b/app/models/concerns/token_authenticatable.rb
index 8c769be0489..1293df571a3 100644
--- a/app/models/concerns/token_authenticatable.rb
+++ b/app/models/concerns/token_authenticatable.rb
@@ -52,7 +52,7 @@ module TokenAuthenticatable
mod.define_method("#{token_field}_matches?") do |other_token|
token = read_attribute(token_field)
- token.present? && ActiveSupport::SecurityUtils.variable_size_secure_compare(other_token, token)
+ token.present? && ActiveSupport::SecurityUtils.secure_compare(other_token, token)
end
end
diff --git a/app/models/email.rb b/app/models/email.rb
index 0ddaa049c3b..580633d3232 100644
--- a/app/models/email.rb
+++ b/app/models/email.rb
@@ -4,9 +4,8 @@ class Email < ApplicationRecord
include Sortable
include Gitlab::SQL::Pattern
- belongs_to :user
+ belongs_to :user, optional: false
- validates :user_id, presence: true
validates :email, presence: true, uniqueness: true, devise_email: true
validate :unique_email, if: ->(email) { email.email_changed? }
diff --git a/app/models/merge_requests_closing_issues.rb b/app/models/merge_requests_closing_issues.rb
index 22cedf57b86..5c53cfd8c27 100644
--- a/app/models/merge_requests_closing_issues.rb
+++ b/app/models/merge_requests_closing_issues.rb
@@ -25,7 +25,7 @@ class MergeRequestsClosingIssues < ApplicationRecord
class << self
def count_for_collection(ids, current_user)
- closing_merge_requests(ids, current_user).group(:issue_id).pluck('issue_id', 'COUNT(*) as count')
+ closing_merge_requests(ids, current_user).group(:issue_id).pluck('issue_id', Arel.sql('COUNT(*) as count'))
end
def count_for_issue(id, current_user)
diff --git a/app/models/namespace.rb b/app/models/namespace.rb
index af50293a179..1d95590bac9 100644
--- a/app/models/namespace.rb
+++ b/app/models/namespace.rb
@@ -41,8 +41,7 @@ class Namespace < ApplicationRecord
validates :owner, presence: true, unless: ->(n) { n.type == "Group" }
validates :name,
presence: true,
- length: { maximum: 255 },
- namespace_name: true
+ length: { maximum: 255 }
validates :description, length: { maximum: 255 }
validates :path,
diff --git a/app/models/pages_domain.rb b/app/models/pages_domain.rb
index d6d879c6d89..e6e491634ab 100644
--- a/app/models/pages_domain.rb
+++ b/app/models/pages_domain.rb
@@ -12,9 +12,11 @@ class PagesDomain < ApplicationRecord
validates :domain, hostname: { allow_numeric_hostname: true }
validates :domain, uniqueness: { case_sensitive: false }
- validates :certificate, presence: { message: 'must be present if HTTPS-only is enabled' }, if: ->(domain) { domain.project&.pages_https_only? }
+ validates :certificate, presence: { message: 'must be present if HTTPS-only is enabled' },
+ if: :certificate_should_be_present?
validates :certificate, certificate: true, if: ->(domain) { domain.certificate.present? }
- validates :key, presence: { message: 'must be present if HTTPS-only is enabled' }, if: ->(domain) { domain.project&.pages_https_only? }
+ validates :key, presence: { message: 'must be present if HTTPS-only is enabled' },
+ if: :certificate_should_be_present?
validates :key, certificate_key: true, if: ->(domain) { domain.key.present? }
validates :verification_code, presence: true, allow_blank: false
@@ -249,4 +251,8 @@ class PagesDomain < ApplicationRecord
rescue OpenSSL::PKey::PKeyError, OpenSSL::Cipher::CipherError
nil
end
+
+ def certificate_should_be_present?
+ !auto_ssl_enabled? && project&.pages_https_only?
+ end
end
diff --git a/app/models/project.rb b/app/models/project.rb
index a6e0b5722b6..2a29cb1ae09 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -357,7 +357,7 @@ class Project < ApplicationRecord
scope :with_unmigrated_storage, -> { where('storage_version < :version OR storage_version IS NULL', version: LATEST_STORAGE_VERSION) }
# last_activity_at is throttled every minute, but last_repository_updated_at is updated with every push
- scope :sorted_by_activity, -> { reorder("GREATEST(COALESCE(last_activity_at, '1970-01-01'), COALESCE(last_repository_updated_at, '1970-01-01')) DESC") }
+ scope :sorted_by_activity, -> { reorder(Arel.sql("GREATEST(COALESCE(last_activity_at, '1970-01-01'), COALESCE(last_repository_updated_at, '1970-01-01')) DESC")) }
scope :sorted_by_stars_desc, -> { reorder(star_count: :desc) }
scope :sorted_by_stars_asc, -> { reorder(star_count: :asc) }
@@ -612,7 +612,7 @@ class Project < ApplicationRecord
end
end
- def initialize(attributes = {})
+ def initialize(attributes = nil)
# We can't use default_value_for because the database has a default
# value of 0 for visibility_level. If someone attempts to create a
# private project, default_value_for will assume that the
@@ -622,6 +622,8 @@ class Project < ApplicationRecord
#
# To fix the problem, we assign the actual default in the application if
# no explicit visibility has been initialized.
+ attributes ||= {}
+
unless visibility_attribute_present?(attributes)
attributes[:visibility_level] = Gitlab::CurrentSettings.default_project_visibility
end
@@ -688,10 +690,6 @@ class Project < ApplicationRecord
{ scope: :project, status: auto_devops&.enabled || Feature.enabled?(:force_autodevops_on_by_default, self) }
end
- def multiple_mr_assignees_enabled?
- Feature.enabled?(:multiple_merge_request_assignees, self)
- end
-
def daily_statistics_enabled?
Feature.enabled?(:project_daily_statistics, self, default_enabled: true)
end
@@ -1557,7 +1555,7 @@ class Project < ApplicationRecord
end
def valid_runners_token?(token)
- self.runners_token && ActiveSupport::SecurityUtils.variable_size_secure_compare(token, self.runners_token)
+ self.runners_token && ActiveSupport::SecurityUtils.secure_compare(token, self.runners_token)
end
# rubocop: disable CodeReuse/ServiceClass
diff --git a/app/models/project_services/ci_service.rb b/app/models/project_services/ci_service.rb
index f0ef2d925ab..47106d7bdbb 100644
--- a/app/models/project_services/ci_service.rb
+++ b/app/models/project_services/ci_service.rb
@@ -7,7 +7,7 @@ class CiService < Service
default_value_for :category, 'ci'
def valid_token?(token)
- self.respond_to?(:token) && self.token.present? && ActiveSupport::SecurityUtils.variable_size_secure_compare(token, self.token)
+ self.respond_to?(:token) && self.token.present? && ActiveSupport::SecurityUtils.secure_compare(token, self.token)
end
def self.supported_events
diff --git a/app/models/project_services/slash_commands_service.rb b/app/models/project_services/slash_commands_service.rb
index bfabc6d262c..5f5cff97808 100644
--- a/app/models/project_services/slash_commands_service.rb
+++ b/app/models/project_services/slash_commands_service.rb
@@ -12,7 +12,7 @@ class SlashCommandsService < Service
def valid_token?(token)
self.respond_to?(:token) &&
self.token.present? &&
- ActiveSupport::SecurityUtils.variable_size_secure_compare(token, self.token)
+ ActiveSupport::SecurityUtils.secure_compare(token, self.token)
end
def self.supported_events
diff --git a/app/models/user.rb b/app/models/user.rb
index 26be197209a..02637b70f03 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -1117,9 +1117,10 @@ class User < ApplicationRecord
def ensure_namespace_correct
if namespace
- namespace.path = namespace.name = username if username_changed?
+ namespace.path = username if username_changed?
+ namespace.name = name if name_changed?
else
- build_namespace(path: username, name: username)
+ build_namespace(path: username, name: name)
end
end