diff options
Diffstat (limited to 'app/models')
-rw-r--r-- | app/models/application_setting.rb | 5 | ||||
-rw-r--r-- | app/models/application_setting_implementation.rb | 57 | ||||
-rw-r--r-- | app/models/commit.rb | 2 | ||||
-rw-r--r-- | app/models/concerns/relative_positioning.rb | 52 | ||||
-rw-r--r-- | app/models/container_repository.rb | 5 | ||||
-rw-r--r-- | app/models/issue.rb | 6 | ||||
-rw-r--r-- | app/models/label.rb | 2 | ||||
-rw-r--r-- | app/models/note.rb | 2 | ||||
-rw-r--r-- | app/models/project.rb | 32 | ||||
-rw-r--r-- | app/models/project_auto_devops.rb | 4 | ||||
-rw-r--r-- | app/models/user_preference.rb | 2 |
11 files changed, 113 insertions, 56 deletions
diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb index 8e558487c1c..a769a8f07fd 100644 --- a/app/models/application_setting.rb +++ b/app/models/application_setting.rb @@ -41,6 +41,11 @@ class ApplicationSetting < ApplicationRecord validates :uuid, presence: true + validates :outbound_local_requests_whitelist, + length: { maximum: 1_000, message: N_('is too long (maximum is 1000 entries)') } + + validates :outbound_local_requests_whitelist, qualified_domain_array: true, allow_blank: true + validates :session_expire_delay, presence: true, numericality: { only_integer: true, greater_than_or_equal_to: 0 } diff --git a/app/models/application_setting_implementation.rb b/app/models/application_setting_implementation.rb index df4caed175d..1e612bd0e78 100644 --- a/app/models/application_setting_implementation.rb +++ b/app/models/application_setting_implementation.rb @@ -2,6 +2,7 @@ module ApplicationSettingImplementation extend ActiveSupport::Concern + include Gitlab::Utils::StrongMemoize DOMAIN_LIST_SEPARATOR = %r{\s*[,;]\s* # comma or semicolon, optionally surrounded by whitespace | # or @@ -96,7 +97,9 @@ module ApplicationSettingImplementation diff_max_patch_bytes: Gitlab::Git::Diff::DEFAULT_MAX_PATCH_BYTES, commit_email_hostname: default_commit_email_hostname, protected_ci_variables: false, - local_markdown_version: 0 + local_markdown_version: 0, + outbound_local_requests_whitelist: [], + raw_blob_request_limit: 300 } end @@ -131,31 +134,52 @@ module ApplicationSettingImplementation end def domain_whitelist_raw - self.domain_whitelist&.join("\n") + array_to_string(self.domain_whitelist) end def domain_blacklist_raw - self.domain_blacklist&.join("\n") + array_to_string(self.domain_blacklist) end def domain_whitelist_raw=(values) - self.domain_whitelist = [] - self.domain_whitelist = values.split(DOMAIN_LIST_SEPARATOR) - self.domain_whitelist.reject! { |d| d.empty? } - self.domain_whitelist + self.domain_whitelist = domain_strings_to_array(values) end def domain_blacklist_raw=(values) - self.domain_blacklist = [] - self.domain_blacklist = values.split(DOMAIN_LIST_SEPARATOR) - self.domain_blacklist.reject! { |d| d.empty? } - self.domain_blacklist + self.domain_blacklist = domain_strings_to_array(values) end def domain_blacklist_file=(file) self.domain_blacklist_raw = file.read end + def outbound_local_requests_whitelist_raw + array_to_string(self.outbound_local_requests_whitelist) + end + + def outbound_local_requests_whitelist_raw=(values) + self.outbound_local_requests_whitelist = domain_strings_to_array(values) + end + + def outbound_local_requests_whitelist_arrays + strong_memoize(:outbound_local_requests_whitelist_arrays) do + ip_whitelist = [] + domain_whitelist = [] + + self.outbound_local_requests_whitelist.each do |str| + ip_obj = Gitlab::Utils.string_to_ip_object(str) + + if ip_obj + ip_whitelist << ip_obj + else + domain_whitelist << str + end + end + + [ip_whitelist, domain_whitelist] + end + end + def repository_storages Array(read_attribute(:repository_storages)) end @@ -255,6 +279,17 @@ module ApplicationSettingImplementation private + def array_to_string(arr) + arr&.join("\n") + end + + def domain_strings_to_array(values) + values + .split(DOMAIN_LIST_SEPARATOR) + .reject(&:empty?) + .uniq + end + def ensure_uuid! return if uuid? diff --git a/app/models/commit.rb b/app/models/commit.rb index be37fa2e76f..0889ce7e287 100644 --- a/app/models/commit.rb +++ b/app/models/commit.rb @@ -346,7 +346,7 @@ class Commit if commits_in_merge_request.present? message_body << "" - commits_in_merge_request.reverse.each do |commit_in_merge| + commits_in_merge_request.reverse_each do |commit_in_merge| message_body << "#{commit_in_merge.short_id} #{commit_in_merge.title}" end end diff --git a/app/models/concerns/relative_positioning.rb b/app/models/concerns/relative_positioning.rb index e4fe46d722a..9cd7b8d6258 100644 --- a/app/models/concerns/relative_positioning.rb +++ b/app/models/concerns/relative_positioning.rb @@ -1,5 +1,26 @@ # frozen_string_literal: true +# This module makes it possible to handle items as a list, where the order of items can be easily altered +# Requirements: +# +# - Only works for ActiveRecord models +# - relative_position integer field must present on the model +# - This module uses GROUP BY: the model should have a parent relation, example: project -> issues, project is the parent relation (issues table has a parent_id column) +# +# Setup like this in the body of your class: +# +# include RelativePositioning +# +# # base query used for the position calculation +# def self.relative_positioning_query_base(issue) +# where(deleted: false) +# end +# +# # column that should be used in GROUP BY +# def self.relative_positioning_parent_column +# :project_id +# end +# module RelativePositioning extend ActiveSupport::Concern @@ -93,7 +114,7 @@ module RelativePositioning return move_after(before) unless after return move_before(after) unless before - # If there is no place to insert an issue we need to create one by moving the before issue closer + # If there is no place to insert an item we need to create one by moving the before item closer # to its predecessor. This process will recursively move all the predecessors until we have a place if (after.relative_position - before.relative_position) < 2 before.move_before @@ -108,11 +129,11 @@ module RelativePositioning pos_after = before.next_relative_position if before.shift_after? - issue_to_move = self.class.in_parents(parent_ids).find_by!(relative_position: pos_after) - issue_to_move.move_after - @positionable_neighbours = [issue_to_move] # rubocop:disable Gitlab/ModuleWithInstanceVariables + item_to_move = self.class.relative_positioning_query_base(self).find_by!(relative_position: pos_after) + item_to_move.move_after + @positionable_neighbours = [item_to_move] # rubocop:disable Gitlab/ModuleWithInstanceVariables - pos_after = issue_to_move.relative_position + pos_after = item_to_move.relative_position end self.relative_position = self.class.position_between(pos_before, pos_after) @@ -123,11 +144,11 @@ module RelativePositioning pos_before = after.prev_relative_position if after.shift_before? - issue_to_move = self.class.in_parents(parent_ids).find_by!(relative_position: pos_before) - issue_to_move.move_before - @positionable_neighbours = [issue_to_move] # rubocop:disable Gitlab/ModuleWithInstanceVariables + item_to_move = self.class.relative_positioning_query_base(self).find_by!(relative_position: pos_before) + item_to_move.move_before + @positionable_neighbours = [item_to_move] # rubocop:disable Gitlab/ModuleWithInstanceVariables - pos_before = issue_to_move.relative_position + pos_before = item_to_move.relative_position end self.relative_position = self.class.position_between(pos_before, pos_after) @@ -141,13 +162,13 @@ module RelativePositioning self.relative_position = self.class.position_between(min_relative_position || START_POSITION, MIN_POSITION) end - # Indicates if there is an issue that should be shifted to free the place + # Indicates if there is an item that should be shifted to free the place def shift_after? next_pos = next_relative_position next_pos && (next_pos - relative_position) == 1 end - # Indicates if there is an issue that should be shifted to free the place + # Indicates if there is an item that should be shifted to free the place def shift_before? prev_pos = prev_relative_position prev_pos && (relative_position - prev_pos) == 1 @@ -159,7 +180,7 @@ module RelativePositioning def save_positionable_neighbours return unless @positionable_neighbours - status = @positionable_neighbours.all? { |issue| issue.save(touch: false) } + status = @positionable_neighbours.all? { |item| item.save(touch: false) } @positionable_neighbours = nil status @@ -170,16 +191,15 @@ module RelativePositioning # When calculating across projects, this is much more efficient than # MAX(relative_position) without the GROUP BY, due to index usage: # https://gitlab.com/gitlab-org/gitlab-ce/issues/54276#note_119340977 - relation = self.class - .in_parents(parent_ids) + relation = self.class.relative_positioning_query_base(self) .order(Gitlab::Database.nulls_last_order('position', 'DESC')) + .group(self.class.relative_positioning_parent_column) .limit(1) - .group(self.class.parent_column) relation = yield relation if block_given? relation - .pluck(self.class.parent_column, Arel.sql("#{calculation}(relative_position) AS position")) + .pluck(self.class.relative_positioning_parent_column, Arel.sql("#{calculation}(relative_position) AS position")) .first&. last end diff --git a/app/models/container_repository.rb b/app/models/container_repository.rb index 39e12ac2b06..facd81dde80 100644 --- a/app/models/container_repository.rb +++ b/app/models/container_repository.rb @@ -86,4 +86,9 @@ class ContainerRepository < ApplicationRecord def self.build_root_repository(project) self.new(project: project, name: '') end + + def self.find_by_path!(path) + self.find_by!(project: path.repository_project, + name: path.repository_name) + end end diff --git a/app/models/issue.rb b/app/models/issue.rb index 8c5dd5e382e..164858dc432 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -91,11 +91,11 @@ class Issue < ApplicationRecord end end - class << self - alias_method :in_parents, :in_projects + def self.relative_positioning_query_base(issue) + in_projects(issue.parent_ids) end - def self.parent_column + def self.relative_positioning_parent_column :project_id end diff --git a/app/models/label.rb b/app/models/label.rb index b83e0862bab..dd403562bfa 100644 --- a/app/models/label.rb +++ b/app/models/label.rb @@ -33,7 +33,7 @@ class Label < ApplicationRecord default_scope { order(title: :asc) } - scope :templates, -> { where(template: true) } + scope :templates, -> { where(template: true, type: [Label.name, nil]) } scope :with_title, ->(title) { where(title: title) } scope :with_lists_and_board, -> { joins(lists: :board).merge(List.movable) } scope :on_project_boards, ->(project_id) { with_lists_and_board.where(boards: { project_id: project_id }) } diff --git a/app/models/note.rb b/app/models/note.rb index 5c31cff9816..3f182c1f099 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -292,7 +292,7 @@ class Note < ApplicationRecord end def special_role=(role) - raise "Role is undefined, #{role} not found in #{SpecialRole.values}" unless SpecialRole.values.include?(role) + raise "Role is undefined, #{role} not found in #{SpecialRole.values}" unless SpecialRole.value?(role) @special_role = role end diff --git a/app/models/project.rb b/app/models/project.rb index 8030c645e2e..0020e423628 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -1862,16 +1862,24 @@ class Project < ApplicationRecord end def append_or_update_attribute(name, value) - old_values = public_send(name.to_s) # rubocop:disable GitlabSecurity/PublicSend + if Project.reflect_on_association(name).try(:macro) == :has_many + # if this is 1-to-N relation, update the parent object + value.each do |item| + item.update!( + Project.reflect_on_association(name).foreign_key => id) + end + + # force to drop relation cache + public_send(name).reset # rubocop:disable GitlabSecurity/PublicSend - if Project.reflect_on_association(name).try(:macro) == :has_many && old_values.any? - update_attribute(name, old_values + value) + # succeeded + true else + # if this is another relation or attribute, update just object update_attribute(name, value) end - - rescue ActiveRecord::RecordNotSaved => e - handle_update_attribute_error(e, value) + rescue ActiveRecord::RecordInvalid => e + raise e, "Failed to set #{name}: #{e.message}" end # Tries to set repository as read_only, checking for existing Git transfers in progress beforehand @@ -2260,18 +2268,6 @@ class Project < ApplicationRecord ContainerRepository.build_root_repository(self).has_tags? end - def handle_update_attribute_error(ex, value) - if ex.message.start_with?('Failed to replace') - if value.respond_to?(:each) - invalid = value.detect(&:invalid?) - - raise ex, ([ex.message] + invalid.errors.full_messages).join(' ') if invalid - end - end - - raise ex - end - def fetch_branch_allows_collaboration(user, branch_name = nil) return false unless user diff --git a/app/models/project_auto_devops.rb b/app/models/project_auto_devops.rb index f39f54f0434..e11d0c48b4b 100644 --- a/app/models/project_auto_devops.rb +++ b/app/models/project_auto_devops.rb @@ -1,10 +1,6 @@ # frozen_string_literal: true class ProjectAutoDevops < ApplicationRecord - include IgnorableColumn - - ignore_column :domain - belongs_to :project, inverse_of: :auto_devops enum deploy_strategy: { diff --git a/app/models/user_preference.rb b/app/models/user_preference.rb index f1326f4c8cb..b236250c24e 100644 --- a/app/models/user_preference.rb +++ b/app/models/user_preference.rb @@ -26,7 +26,7 @@ class UserPreference < ApplicationRecord def set_notes_filter(filter_id, issuable) # No need to update the column if the value is already set. - if filter_id && NOTES_FILTERS.values.include?(filter_id) + if filter_id && NOTES_FILTERS.value?(filter_id) field = notes_filter_field_for(issuable) self[field] = filter_id |