diff options
Diffstat (limited to 'app/services/issuable')
-rw-r--r-- | app/services/issuable/bulk_update_service.rb | 30 | ||||
-rw-r--r-- | app/services/issuable/clone/base_service.rb | 7 | ||||
-rw-r--r-- | app/services/issuable/destroy_service.rb | 5 | ||||
-rw-r--r-- | app/services/issuable/discussions_list_service.rb | 2 | ||||
-rw-r--r-- | app/services/issuable/export_csv/base_service.rb | 38 | ||||
-rw-r--r-- | app/services/issuable/import_csv/base_service.rb | 80 |
6 files changed, 34 insertions, 128 deletions
diff --git a/app/services/issuable/bulk_update_service.rb b/app/services/issuable/bulk_update_service.rb index 30444fa3938..c01509bc4d1 100644 --- a/app/services/issuable/bulk_update_service.rb +++ b/app/services/issuable/bulk_update_service.rb @@ -13,9 +13,9 @@ module Issuable end def execute(type) - ids = params.delete(:issuable_ids).split(",") + model_ids = ids_from_params(params.delete(:issuable_ids)) set_update_params(type) - updated_issuables = update_issuables(type, ids) + updated_issuables = update_issuables(type, model_ids) if updated_issuables.present? && requires_count_cache_reset?(type) schedule_group_issues_count_reset(updated_issuables) @@ -28,9 +28,14 @@ module Issuable private + def ids_from_params(issuable_ids) + return issuable_ids if issuable_ids.is_a?(Array) + + issuable_ids.split(',') + end + def set_update_params(type) params.slice!(*permitted_attrs(type)) - params.delete_if { |k, v| v.blank? } if params[:assignee_ids] == [IssuableFinder::Params::NONE.to_s] params[:assignee_ids] = [] @@ -40,8 +45,6 @@ module Issuable def permitted_attrs(type) attrs = %i(state_event milestone_id add_label_ids remove_label_ids subscription_event) - attrs.push(:sprint_id) if type == 'issue' - if type == 'issue' || type == 'merge_request' attrs.push(:assignee_ids) else @@ -53,10 +56,12 @@ module Issuable model_class = type.classify.constantize update_class = type.classify.pluralize.constantize::UpdateService items = find_issuables(parent, model_class, ids) + authorized_issuables = [] items.each do |issuable| next unless can?(current_user, :"update_#{type}", issuable) + authorized_issuables << issuable update_class.new( **update_class.constructor_container_arg(issuable.issuing_parent), current_user: current_user, @@ -64,23 +69,22 @@ module Issuable ).execute(issuable) end - items + authorized_issuables end def find_issuables(parent, model_class, ids) + issuables = model_class.id_in(ids) + case parent when Project - projects = parent + issuables = issuables.of_projects(parent) when Group - projects = parent.all_projects + issuables = issuables.of_projects(parent.all_projects) else - return + raise ArgumentError, _('A parent must be provided when bulk updating issuables') end - model_class - .id_in(ids) - .of_projects(projects) - .includes_for_bulk_update + issuables.includes_for_bulk_update end # Duplicates params and its top-level values diff --git a/app/services/issuable/clone/base_service.rb b/app/services/issuable/clone/base_service.rb index 3c13944cfbc..02beaaf5d83 100644 --- a/app/services/issuable/clone/base_service.rb +++ b/app/services/issuable/clone/base_service.rb @@ -7,6 +7,11 @@ module Issuable alias_method :old_project, :project + # TODO: this is to be removed once we get to rename the IssuableBaseService project param to container + def initialize(container:, current_user: nil, params: {}) + super(project: container, current_user: current_user, params: params) + end + def execute(original_entity, target_parent) @original_entity = original_entity @target_parent = target_parent @@ -77,7 +82,7 @@ module Issuable end def close_issue - close_service = Issues::CloseService.new(project: old_project, current_user: current_user) + close_service = Issues::CloseService.new(container: old_project, current_user: current_user) close_service.execute(original_entity, notifications: false, system_note: true) end diff --git a/app/services/issuable/destroy_service.rb b/app/services/issuable/destroy_service.rb index 6aab56f0f68..4c3e518d62b 100644 --- a/app/services/issuable/destroy_service.rb +++ b/app/services/issuable/destroy_service.rb @@ -2,6 +2,11 @@ module Issuable class DestroyService < IssuableBaseService + # TODO: this is to be removed once we get to rename the IssuableBaseService project param to container + def initialize(container:, current_user: nil, params: {}) + super(project: container, current_user: current_user, params: params) + end + def execute(issuable) after_destroy(issuable) if issuable.destroy end diff --git a/app/services/issuable/discussions_list_service.rb b/app/services/issuable/discussions_list_service.rb index 10e7660289b..cb9271de11d 100644 --- a/app/services/issuable/discussions_list_service.rb +++ b/app/services/issuable/discussions_list_service.rb @@ -25,7 +25,7 @@ module Issuable paginated_discussions_by_type = paginator.records.group_by(&:table_name) notes = if paginated_discussions_by_type['notes'].present? - notes.with_discussion_ids(paginated_discussions_by_type['notes'].map(&:discussion_id)) + notes.id_in(paginated_discussions_by_type['notes'].flat_map(&:ids)) else notes.none end diff --git a/app/services/issuable/export_csv/base_service.rb b/app/services/issuable/export_csv/base_service.rb deleted file mode 100644 index 49ff05935c9..00000000000 --- a/app/services/issuable/export_csv/base_service.rb +++ /dev/null @@ -1,38 +0,0 @@ -# frozen_string_literal: true - -module Issuable - module ExportCsv - class BaseService - # Target attachment size before base64 encoding - TARGET_FILESIZE = 15.megabytes - - def initialize(issuables_relation, project) - @issuables = issuables_relation - @project = project - end - - def csv_data - csv_builder.render(TARGET_FILESIZE) - end - - private - - attr_reader :project, :issuables - - # rubocop: disable CodeReuse/ActiveRecord - def csv_builder - @csv_builder ||= - CsvBuilder.new(issuables.preload(associations_to_preload), header_to_value_hash) - end - # rubocop: enable CodeReuse/ActiveRecord - - def associations_to_preload - [] - end - - def header_to_value_hash - raise NotImplementedError - end - end - end -end diff --git a/app/services/issuable/import_csv/base_service.rb b/app/services/issuable/import_csv/base_service.rb index e84d1032e41..83cf5a67453 100644 --- a/app/services/issuable/import_csv/base_service.rb +++ b/app/services/issuable/import_csv/base_service.rb @@ -2,38 +2,13 @@ module Issuable module ImportCsv - class BaseService - def initialize(user, project, csv_io) - @user = user - @project = project - @csv_io = csv_io - @results = { success: 0, error_lines: [], parse_error: false } - end - - def execute - process_csv - email_results_to_user - - @results - end + class BaseService < ::ImportCsv::BaseService + extend ::Gitlab::Utils::Override private - def process_csv - with_csv_lines.each do |row, line_no| - attributes = issuable_attributes_for(row) - - if create_issuable(attributes)&.persisted? - @results[:success] += 1 - else - @results[:error_lines].push(line_no) - end - end - rescue ArgumentError, CSV::MalformedCSVError - @results[:parse_error] = true - end - - def issuable_attributes_for(row) + override :attributes_for + def attributes_for(row) { title: row[:title], description: row[:description], @@ -41,58 +16,13 @@ module Issuable } end - def with_csv_lines - csv_data = @csv_io.open(&:read).force_encoding(Encoding::UTF_8) - validate_headers_presence!(csv_data.lines.first) - - CSV.new( - csv_data, - col_sep: detect_col_sep(csv_data.lines.first), - headers: true, - header_converters: :symbol - ).each.with_index(2) - end - + override :validate_headers_presence! def validate_headers_presence!(headers) headers.downcase! if headers return if headers && headers.include?('title') && headers.include?('description') raise CSV::MalformedCSVError end - - def detect_col_sep(header) - if header.include?(",") - "," - elsif header.include?(";") - ";" - elsif header.include?("\t") - "\t" - else - raise CSV::MalformedCSVError - end - end - - def create_issuable(attributes) - # NOTE: CSV imports are performed by workers, so we do not have a request context in order - # to create a SpamParams object to pass to the issuable create service. - spam_params = nil - create_service = create_issuable_class.new(project: @project, current_user: @user, params: attributes, spam_params: spam_params) - - # For now, if create_issuable_class prepends RateLimitedService let's bypass rate limiting - if create_issuable_class < RateLimitedService - create_service.execute_without_rate_limiting - else - create_service.execute - end - end - - def email_results_to_user - # defined in ImportCsvService - end - - def create_issuable_class - # defined in ImportCsvService - end end end end |