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:
Diffstat (limited to 'app/services/import_csv/base_service.rb')
-rw-r--r--app/services/import_csv/base_service.rb99
1 files changed, 99 insertions, 0 deletions
diff --git a/app/services/import_csv/base_service.rb b/app/services/import_csv/base_service.rb
new file mode 100644
index 00000000000..feb76425fb4
--- /dev/null
+++ b/app/services/import_csv/base_service.rb
@@ -0,0 +1,99 @@
+# frozen_string_literal: true
+
+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
+
+ def email_results_to_user
+ raise NotImplementedError
+ end
+
+ private
+
+ attr_reader :user, :project, :csv_io, :results
+
+ def attributes_for(row)
+ raise NotImplementedError
+ end
+
+ def validate_headers_presence!(headers)
+ raise NotImplementedError
+ end
+
+ def create_object_class
+ raise NotImplementedError
+ end
+
+ def process_csv
+ with_csv_lines.each do |row, line_no|
+ attributes = attributes_for(row)
+
+ if create_object(attributes)&.persisted?
+ results[:success] += 1
+ else
+ results[:error_lines].push(line_no)
+ end
+ end
+ rescue ArgumentError, CSV::MalformedCSVError
+ results[:parse_error] = true
+ 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
+
+ def detect_col_sep(header)
+ if header.include?(",")
+ ","
+ elsif header.include?(";")
+ ";"
+ elsif header.include?("\t")
+ "\t"
+ else
+ raise CSV::MalformedCSVError.new('Invalid CSV format', 1)
+ end
+ end
+
+ def create_object(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
+
+ # default_params can be extracted into a method if we need
+ # to support creation of objects that belongs to groups.
+ default_params = { container: project,
+ current_user: user,
+ params: attributes,
+ spam_params: spam_params }
+
+ create_service = create_object_class.new(**default_params.merge(extra_create_service_params))
+
+ create_service.execute_without_rate_limiting
+ end
+
+ # Overidden in subclasses to support specific parameters
+ def extra_create_service_params
+ {}
+ end
+ end
+end