summaryrefslogtreecommitdiff
path: root/app/services/issuable
diff options
context:
space:
mode:
Diffstat (limited to 'app/services/issuable')
-rw-r--r--app/services/issuable/bulk_update_service.rb30
-rw-r--r--app/services/issuable/clone/base_service.rb7
-rw-r--r--app/services/issuable/destroy_service.rb5
-rw-r--r--app/services/issuable/discussions_list_service.rb2
-rw-r--r--app/services/issuable/export_csv/base_service.rb38
-rw-r--r--app/services/issuable/import_csv/base_service.rb80
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