Initial generic csv based import of text modules, users, organizations and tickets for model and controller.

This commit is contained in:
Martin Edenhofer 2018-02-20 05:29:30 +01:00
parent 4537a281a3
commit 6a0f5d4c25
30 changed files with 1882 additions and 38 deletions

View file

@ -323,4 +323,43 @@ curl http://localhost/api/v1/organization/{id} -v -u #{login}:#{password} -H "Co
render json: history render json: history
end end
# @path [GET] /organizations/import_example
#
# @summary Download of example CSV file.
# @notes The requester have 'admin.organization' permissions to be able to download it.
# @example curl -u 'me@example.com:test' http://localhost:3000/api/v1/organizations/import_example
#
# @response_message 200 File download.
# @response_message 401 Invalid session.
def import_example
permission_check('admin.organization')
send_data(
Organization.csv_example,
filename: 'organization-example.csv',
type: 'text/csv',
disposition: 'attachment'
)
end
# @path [POST] /organizations/import
#
# @summary Starts import.
# @notes The requester have 'admin.text_module' permissions to be create a new import.
# @example curl -u 'me@example.com:test' -F 'file=@/path/to/file/organizations.csv' 'https://your.zammad/api/v1/organizations/import?try=true'
# @example curl -u 'me@example.com:test' -F 'file=@/path/to/file/organizations.csv' 'https://your.zammad/api/v1/organizations/import'
#
# @response_message 201 Import started.
# @response_message 401 Invalid session.
def import_start
permission_check('admin.user')
result = Organization.csv_import(
string: params[:file].read.force_encoding('utf-8'),
parse_params: {
col_sep: ';',
},
try: params[:try],
)
render json: result, status: :ok
end
end end

View file

@ -152,4 +152,48 @@ curl http://localhost/api/v1/text_modules.json -v -u #{login}:#{password} -H "Co
permission_check('admin.text_module') permission_check('admin.text_module')
model_destroy_render(TextModule, params) model_destroy_render(TextModule, params)
end end
# @path [GET] /text_modules/import_example
#
# @summary Download of example CSV file.
# @notes The requester have 'admin.text_module' permissions to be able to download it.
# @example curl -u 'me@example.com:test' http://localhost:3000/api/v1/text_modules/import_example
#
# @response_message 200 File download.
# @response_message 401 Invalid session.
def import_example
permission_check('admin.text_module')
csv_string = TextModule.csv_example(
col_sep: ',',
)
send_data(
csv_string,
filename: 'example.csv',
type: 'text/csv',
disposition: 'attachment'
)
end
# @path [POST] /text_modules/import
#
# @summary Starts import.
# @notes The requester have 'admin.text_module' permissions to be create a new import.
# @example curl -u 'me@example.com:test' -F 'file=@/path/to/file/Textbausteine_final2.csv' 'https://your.zammad/api/v1/text_modules/import?try=true'
# @example curl -u 'me@example.com:test' -F 'file=@/path/to/file/Textbausteine_final2.csv' 'https://your.zammad/api/v1/text_modules/import'
#
# @response_message 201 Import started.
# @response_message 401 Invalid session.
def import_start
permission_check('admin.text_module')
result = TextModule.csv_import(
string: params[:file].read.force_encoding('utf-8'),
parse_params: {
col_sep: ';',
},
try: params[:try],
)
render json: result, status: :ok
end
end end

View file

@ -276,6 +276,52 @@ class TicketArticlesController < ApplicationController
) )
end end
# @path [GET] /ticket_articles/import_example
#
# @summary Download of example CSV file.
# @notes The requester have 'admin' permissions to be able to download it.
# @example curl -u 'me@example.com:test' http://localhost:3000/api/v1/ticket_articles/import_example
#
# @response_message 200 File download.
# @response_message 401 Invalid session.
def import_example
permission_check('admin')
csv_string = Ticket::Article.csv_example(
col_sep: ',',
)
send_data(
csv_string,
filename: 'example.csv',
type: 'text/csv',
disposition: 'attachment'
)
end
# @path [POST] /ticket_articles/import
#
# @summary Starts import.
# @notes The requester have 'admin' permissions to be create a new import.
# @example curl -u 'me@example.com:test' -F 'file=@/path/to/file/ticket_articles.csv' 'https://your.zammad/api/v1/ticket_articles/import?try=true'
# @example curl -u 'me@example.com:test' -F 'file=@/path/to/file/ticket_articles.csv' 'https://your.zammad/api/v1/ticket_articles/import'
#
# @response_message 201 Import started.
# @response_message 401 Invalid session.
def import_start
permission_check('admin')
if Setting.get('import_mode') != true
raise 'Only can import tickets if system is in import mode.'
end
result = Ticket::Article.csv_import(
string: params[:file].read.force_encoding('utf-8'),
parse_params: {
col_sep: ';',
},
try: params[:try],
)
render json: result, status: :ok
end
private private
def sanitized_disposition def sanitized_disposition

View file

@ -598,6 +598,52 @@ class TicketsController < ApplicationController
} }
end end
# @path [GET] /tickets/import_example
#
# @summary Download of example CSV file.
# @notes The requester have 'admin' permissions to be able to download it.
# @example curl -u 'me@example.com:test' http://localhost:3000/api/v1/tickets/import_example
#
# @response_message 200 File download.
# @response_message 401 Invalid session.
def import_example
permission_check('admin')
csv_string = Ticket.csv_example(
col_sep: ',',
)
send_data(
csv_string,
filename: 'example.csv',
type: 'text/csv',
disposition: 'attachment'
)
end
# @path [POST] /tickets/import
#
# @summary Starts import.
# @notes The requester have 'admin' permissions to be create a new import.
# @example curl -u 'me@example.com:test' -F 'file=@/path/to/file/tickets.csv' 'https://your.zammad/api/v1/tickets/import?try=true'
# @example curl -u 'me@example.com:test' -F 'file=@/path/to/file/tickets.csv' 'https://your.zammad/api/v1/tickets/import'
#
# @response_message 201 Import started.
# @response_message 401 Invalid session.
def import_start
permission_check('admin')
if Setting.get('import_mode') != true
raise 'Only can import tickets if system is in import mode.'
end
result = Ticket.csv_import(
string: params[:file].read.force_encoding('utf-8'),
parse_params: {
col_sep: ';',
},
try: params[:try],
)
render json: result, status: :ok
end
private private
def follow_up_possible_check def follow_up_possible_check

View file

@ -1061,6 +1061,45 @@ curl http://localhost/api/v1/users/avatar -v -u #{login}:#{password} -H "Content
render json: { avatars: result }, status: :ok render json: { avatars: result }, status: :ok
end end
# @path [GET] /users/import_example
#
# @summary Download of example CSV file.
# @notes The requester have 'admin.user' permissions to be able to download it.
# @example curl -u 'me@example.com:test' http://localhost:3000/api/v1/users/import_example
#
# @response_message 200 File download.
# @response_message 401 Invalid session.
def import_example
permission_check('admin.user')
send_data(
User.csv_example,
filename: 'user-example.csv',
type: 'text/csv',
disposition: 'attachment'
)
end
# @path [POST] /users/import
#
# @summary Starts import.
# @notes The requester have 'admin.text_module' permissions to be create a new import.
# @example curl -u 'me@example.com:test' -F 'file=@/path/to/file/users.csv' 'https://your.zammad/api/v1/users/import?try=true'
# @example curl -u 'me@example.com:test' -F 'file=@/path/to/file/users.csv' 'https://your.zammad/api/v1/users/import'
#
# @response_message 201 Import started.
# @response_message 401 Invalid session.
def import_start
permission_check('admin.user')
result = User.csv_import(
string: params[:file].read.force_encoding('utf-8'),
parse_params: {
col_sep: ';',
},
try: params[:try],
)
render json: result, status: :ok
end
private private
def password_policy(password) def password_policy(password)

View file

@ -63,6 +63,9 @@ returns
real_values = real_values.to_sym real_values = real_values.to_sym
next if !respond_to?(real_values) next if !respond_to?(real_values)
next if !params[real_values] next if !params[real_values]
if params[real_values].instance_of?(String) || params[real_values].instance_of?(Integer) || params[real_values].instance_of?(Float)
params[real_values] = [params[real_values]]
end
next if !params[real_values].instance_of?(Array) next if !params[real_values].instance_of?(Array)
list = [] list = []
class_object = assoc.klass class_object = assoc.klass

View file

@ -39,10 +39,9 @@ returns
where(name: data[:name]) where(name: data[:name])
end end
records.each do |loop_record| records.each do |loop_record|
if loop_record.name == data[:name] next if loop_record.name != data[:name]
cache_set(data[:name], loop_record) cache_set(data[:name], loop_record)
return loop_record return loop_record
end
end end
return return
elsif data[:login] elsif data[:login]
@ -56,10 +55,9 @@ returns
where(login: data[:login]) where(login: data[:login])
end end
records.each do |loop_record| records.each do |loop_record|
if loop_record.login == data[:login] next if loop_record.login != data[:login]
cache_set(data[:login], loop_record) cache_set(data[:login], loop_record)
return loop_record return loop_record
end
end end
return return
elsif data[:email] elsif data[:email]
@ -73,15 +71,27 @@ returns
where(email: data[:email]) where(email: data[:email])
end end
records.each do |loop_record| records.each do |loop_record|
if loop_record.email == data[:email] next if loop_record.email != data[:email]
cache_set(data[:email], loop_record) cache_set(data[:email], loop_record)
return loop_record return loop_record
end end
return
elsif data[:number]
# do lookup with == to handle case insensitive databases
records = if Rails.application.config.db_case_sensitive
where('LOWER(number) = LOWER(?)', data[:number])
else
where(number: data[:number])
end
records.each do |loop_record|
next if loop_record.number != data[:number]
return loop_record
end end
return return
end end
raise ArgumentError, 'Need name, id, login or email for lookup()' raise ArgumentError, 'Need name, id, number, login or email for lookup()'
end end
end end
end end

View file

@ -0,0 +1,351 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
require 'csv'
module CanCsvImport
extend ActiveSupport::Concern
# methods defined here are going to extend the class, not the instance of it
class_methods do
=begin
result = Model.csv_import(
string: csv_string,
parse_params: {
col_sep: ',',
},
try: true,
)
result = Model.csv_import(
file: '/file/location/of/file.csv',
parse_params: {
col_sep: ',',
},
try: true,
)
result = TextModule.csv_import(
file: '/Users/me/Downloads/Textbausteine_final.csv',
parse_params: {
col_sep: ',',
},
try: false,
)
returns
{
records: [record1, ...]
try: true, # true|false
success: true, # true|false
}
=end
def csv_import(data)
if data[:file].present?
raise Exceptions::UnprocessableEntity, "No such file '#{data[:file]}'" if !File.exist?(data[:file])
begin
file = File.open(data[:file], 'r:UTF-8')
data[:string] = file.read
rescue => e
raise Exceptions::UnprocessableEntity, "Unable to read file '#{data[:file]}': #{e.inspect}"
end
end
if data[:string].blank?
raise Exceptions::UnprocessableEntity, 'Unable to parse empty file/string!'
end
rows = CSV.parse(data[:string], data[:parse_params])
header = rows.shift
if header.blank?
raise Exceptions::UnprocessableEntity, 'Unable to parse file/string without header!'
end
header.each do |item|
if item.respond_to?(:strip!)
item.strip!
end
next if !item.respond_to?(:downcase!)
item.downcase!
end
# get payload based on csv
payload = []
rows.each do |row|
if row[0].blank? && row[1].blank?
payload_last = payload.last
row.each_with_index do |item, count|
next if item.blank?
if payload_last[header[count].to_sym].class != Array
payload_last[header[count].to_sym] = [payload_last[header[count].to_sym]]
end
payload_last[header[count].to_sym].push item.strip
end
next
end
attributes = {}
row.each_with_index do |item, count|
next if !item
next if header[count].blank?
next if @csv_attributes_ignored&.include?(header[count].to_sym)
attributes[header[count].to_sym] = if item.respond_to?(:strip)
item.strip
else
item
end
end
data[:fixed_params]&.each do |key, value|
attributes[key] = value
end
payload.push attributes
end
# create or update records
csv_object_ids_ignored = @csv_object_ids_ignored || []
records = []
stats = {
created: 0,
updated: 0,
}
errors = []
line_count = 0
payload.each do |attributes|
line_count += 1
record = nil
%i[id number name login email].each do |lookup_by|
next if !attributes[lookup_by]
params = {}
params[lookup_by] = attributes[lookup_by]
record = lookup(params)
break if record
end
if attributes[:id].present? && !record
errors.push "Line #{line_count}: unknown record with id '#{attributes[:id]}' for #{new.class}."
next
end
if record && csv_object_ids_ignored.include?(record.id)
errors.push "Line #{line_count}: unable to update record with id '#{attributes[:id]}' for #{new.class}."
next
end
begin
clean_params = association_name_to_id_convert(attributes)
rescue => e
errors.push "Line #{line_count}: #{e.message}"
next
end
# create object
Transaction.execute(disable_notification: true, reset_user_id: true) do
UserInfo.current_user_id = clean_params[:updated_by_id] || clean_params[:created_by_id]
if !record
stats[:created] += 1
begin
csv_verify_attributes(clean_params)
clean_params = param_cleanup(clean_params)
if !UserInfo.current_user_id
clean_params[:created_by_id] = 1
clean_params[:updated_by_id] = 1
end
record = new(clean_params)
next if data[:try] == 'true' || data[:try] == true
record.associations_from_param(attributes)
record.save!
rescue => e
errors.push "Line #{line_count}: #{e.message}"
next
end
else
stats[:updated] += 1
next if data[:try] == 'true' || data[:try] == true
begin
csv_verify_attributes(clean_params)
clean_params = param_cleanup(clean_params)
if !UserInfo.current_user_id
clean_params[:updated_by_id] = 1
end
record.with_lock do
record.associations_from_param(attributes)
record.update_attributes!(clean_params)
end
rescue => e
errors.push "Line #{line_count}: #{e.message}"
next
end
end
end
records.push record
end
result = 'success'
if errors.present?
result = 'failed'
end
{
stats: stats,
records: records,
errors: errors,
try: data[:try],
result: result,
}
end
=begin
verify if attributes are valid, will raise an ArgumentError with "unknown attribute '#{key}' for #{new.class}."
Model.csv_verify_attributes({'attribute': 'some value'})
=end
def csv_verify_attributes(clean_params)
all_clean_attributes = {}
new.attributes.each_key do |attribute|
all_clean_attributes[attribute.to_sym] = true
end
reflect_on_all_associations.map do |assoc|
all_clean_attributes[assoc.name.to_sym] = true
ref = if assoc.name.to_s.end_with?('_id')
"#{assoc.name}_id"
else
"#{assoc.name.to_s.chop}_ids"
end
all_clean_attributes[ref.to_sym] = true
end
clean_params.each_key do |key|
next if all_clean_attributes.key?(key.to_sym)
raise ArgumentError, "unknown attribute '#{key}' for #{new.class}."
end
true
end
=begin
csv_string = Model.csv_example(
col_sep: ',',
)
returns
csv_string
=end
def csv_example(params = {})
header = []
csv_object_ids_ignored = @csv_object_ids_ignored || []
records = where.not(id: csv_object_ids_ignored).offset(1).limit(23).to_a
if records.count < 20
record_ids = records.pluck(:id).concat(csv_object_ids_ignored)
local_records = where.not(id: record_ids).limit(20 - records.count)
records = records.concat(local_records)
end
records_attributes_with_association_names = []
records.each do |record|
record_attributes_with_association_names = record.attributes_with_association_names
records_attributes_with_association_names.push record_attributes_with_association_names
record_attributes_with_association_names.each do |key, value|
next if value.class == ActiveSupport::HashWithIndifferentAccess
next if value.class == Hash
next if @csv_attributes_ignored&.include?(key.to_sym)
next if key.match?(/_id$/)
next if key.match?(/_ids$/)
next if key == 'created_by'
next if key == 'updated_by'
next if key == 'created_at'
next if key == 'updated_at'
next if header.include?(key)
header.push key
end
end
rows = []
records_attributes_with_association_names.each do |record|
row = []
rows_to_add = []
position = -1
header.each do |key|
position += 1
if record[key].class == ActiveSupport::TimeWithZone
row.push record[key].iso8601
next
end
if record[key].class == Array
entry_count = -2
record[key].each do |entry|
entry_count += 1
next if entry_count == -1
if !rows_to_add[entry_count]
rows_to_add[entry_count] = Array.new(header.count + 1) { '' }
end
rows_to_add[entry_count][position] = entry
end
record[key] = record[key][0]
end
row.push record[key]
end
rows.push row
next unless rows_to_add.count.positive?
rows_to_add.each do |item|
rows.push item
end
rows_to_add = []
end
CSV.generate(params) do |csv|
csv << header
rows.each do |row|
csv << row
end
end
end
=begin
serve methode to ignore model based on id
class Model < ApplicationModel
include CanCsvImport
csv_object_ids_ignored(1, 2, 3)
end
=end
def csv_object_ids_ignored(*object_ids)
@csv_object_ids_ignored = object_ids
end
=begin
serve methode to ignore model attributes
class Model < ApplicationModel
include CanCsvImport
csv_attributes_ignored :password,
:image_source,
:login_failed,
:source,
:image_source,
:image,
:authorizations,
:organizations
end
=end
def csv_attributes_ignored(*attributes)
@csv_attributes_ignored = attributes
end
end
end

View file

@ -6,6 +6,7 @@ class Organization < ApplicationModel
include ChecksLatestChangeObserved include ChecksLatestChangeObserved
include HasHistory include HasHistory
include HasSearchIndexBackend include HasSearchIndexBackend
include CanCsvImport
include Organization::ChecksAccess include Organization::ChecksAccess
load 'organization/assets.rb' load 'organization/assets.rb'

View file

@ -3,10 +3,14 @@
class TextModule < ApplicationModel class TextModule < ApplicationModel
include ChecksClientNotification include ChecksClientNotification
include ChecksHtmlSanitized include ChecksHtmlSanitized
include CanCsvImport
validates :name, presence: true validates :name, presence: true
validates :content, presence: true validates :content, presence: true
before_create :validate_content
before_update :validate_content
sanitized_html :content sanitized_html :content
=begin =begin
@ -97,4 +101,14 @@ push text_modules to online
true true
end end
private
def validate_content
return true if content.blank?
return true if content.match?(/<.+?>/)
content.gsub!(/(\r\n|\n\r|\r)/, "\n")
self.content = content.text2html
true
end
end end

View file

@ -4,6 +4,7 @@ class Ticket < ApplicationModel
include HasActivityStreamLog include HasActivityStreamLog
include ChecksClientNotification include ChecksClientNotification
include ChecksLatestChangeObserved include ChecksLatestChangeObserved
include CanCsvImport
include HasHistory include HasHistory
include HasTags include HasTags
include HasSearchIndexBackend include HasSearchIndexBackend

View file

@ -4,6 +4,7 @@ class Ticket::Article < ApplicationModel
include ChecksClientNotification include ChecksClientNotification
include HasHistory include HasHistory
include ChecksHtmlSanitized include ChecksHtmlSanitized
include CanCsvImport
include Ticket::Article::ChecksAccess include Ticket::Article::ChecksAccess
load 'ticket/article/assets.rb' load 'ticket/article/assets.rb'

View file

@ -28,6 +28,7 @@ class User < ApplicationModel
include ChecksClientNotification include ChecksClientNotification
include HasHistory include HasHistory
include HasSearchIndexBackend include HasSearchIndexBackend
include CanCsvImport
include HasGroups include HasGroups
include HasRoles include HasRoles
include User::ChecksAccess include User::ChecksAccess
@ -74,6 +75,18 @@ class User < ApplicationModel
:source, :source,
:login_failed :login_failed
csv_object_ids_ignored 1
csv_attributes_ignored :password,
:login_failed,
:source,
:image_source,
:image,
:authorizations,
:organizations,
:groups,
:user_groups
def ignore_search_indexing?(_action) def ignore_search_indexing?(_action)
# ignore internal user # ignore internal user
return true if id == 1 return true if id == 1

View file

@ -2,12 +2,14 @@ Zammad::Application.routes.draw do
api_path = Rails.configuration.api_path api_path = Rails.configuration.api_path
# organizations # organizations
match api_path + '/organizations/search', to: 'organizations#search', via: %i[get post] match api_path + '/organizations/import_example', to: 'organizations#import_example', via: :get
match api_path + '/organizations', to: 'organizations#index', via: :get match api_path + '/organizations/import', to: 'organizations#import_start', via: :post
match api_path + '/organizations/:id', to: 'organizations#show', via: :get match api_path + '/organizations/search', to: 'organizations#search', via: %i[get post]
match api_path + '/organizations', to: 'organizations#create', via: :post match api_path + '/organizations', to: 'organizations#index', via: :get
match api_path + '/organizations/:id', to: 'organizations#update', via: :put match api_path + '/organizations/:id', to: 'organizations#show', via: :get
match api_path + '/organizations/:id', to: 'organizations#destroy', via: :delete match api_path + '/organizations', to: 'organizations#create', via: :post
match api_path + '/organizations/history/:id', to: 'organizations#history', via: :get match api_path + '/organizations/:id', to: 'organizations#update', via: :put
match api_path + '/organizations/:id', to: 'organizations#destroy', via: :delete
match api_path + '/organizations/history/:id', to: 'organizations#history', via: :get
end end

View file

@ -2,10 +2,12 @@ Zammad::Application.routes.draw do
api_path = Rails.configuration.api_path api_path = Rails.configuration.api_path
# text_modules # text_modules
match api_path + '/text_modules', to: 'text_modules#index', via: :get match api_path + '/text_modules/import_example', to: 'text_modules#import_example', via: :get
match api_path + '/text_modules/:id', to: 'text_modules#show', via: :get match api_path + '/text_modules/import', to: 'text_modules#import_start', via: :post
match api_path + '/text_modules', to: 'text_modules#create', via: :post match api_path + '/text_modules', to: 'text_modules#index', via: :get
match api_path + '/text_modules/:id', to: 'text_modules#update', via: :put match api_path + '/text_modules/:id', to: 'text_modules#show', via: :get
match api_path + '/text_modules/:id', to: 'text_modules#destroy', via: :delete match api_path + '/text_modules', to: 'text_modules#create', via: :post
match api_path + '/text_modules/:id', to: 'text_modules#update', via: :put
match api_path + '/text_modules/:id', to: 'text_modules#destroy', via: :delete
end end

View file

@ -2,7 +2,7 @@ Zammad::Application.routes.draw do
api_path = Rails.configuration.api_path api_path = Rails.configuration.api_path
# users # users
match api_path + '/users/search', to: 'users#search', via: %i[get post] match api_path + '/users/search', to: 'users#search', via: %i[get post option]
match api_path + '/users/recent', to: 'users#recent', via: %i[get post] match api_path + '/users/recent', to: 'users#recent', via: %i[get post]
match api_path + '/users/password_reset', to: 'users#password_reset_send', via: :post match api_path + '/users/password_reset', to: 'users#password_reset_send', via: :post
match api_path + '/users/password_reset_verify', to: 'users#password_reset_verify', via: :post match api_path + '/users/password_reset_verify', to: 'users#password_reset_verify', via: :post
@ -11,6 +11,9 @@ Zammad::Application.routes.draw do
match api_path + '/users/out_of_office', to: 'users#out_of_office', via: :put match api_path + '/users/out_of_office', to: 'users#out_of_office', via: :put
match api_path + '/users/account', to: 'users#account_remove', via: :delete match api_path + '/users/account', to: 'users#account_remove', via: :delete
match api_path + '/users/import_example', to: 'users#import_example', via: :get
match api_path + '/users/import', to: 'users#import_start', via: :post
match api_path + '/users/avatar', to: 'users#avatar_new', via: :post match api_path + '/users/avatar', to: 'users#avatar_new', via: :post
match api_path + '/users/avatar', to: 'users#avatar_list', via: :get match api_path + '/users/avatar', to: 'users#avatar_list', via: :get
match api_path + '/users/avatar', to: 'users#avatar_destroy', via: :delete match api_path + '/users/avatar', to: 'users#avatar_destroy', via: :delete

View file

@ -14,17 +14,6 @@ class OrganizationControllerTest < ActionDispatch::IntegrationTest
UserInfo.current_user_id = 1 UserInfo.current_user_id = 1
@backup_admin = User.create_or_update(
login: 'backup-admin',
firstname: 'Backup',
lastname: 'Agent',
email: 'backup-admin@example.com',
password: 'adminpw',
active: true,
roles: roles,
groups: groups,
)
@admin = User.create_or_update( @admin = User.create_or_update(
login: 'rest-admin', login: 'rest-admin',
firstname: 'Rest', firstname: 'Rest',
@ -510,4 +499,110 @@ class OrganizationControllerTest < ActionDispatch::IntegrationTest
end end
test '05.01 csv example - customer no access' do
credentials = ActionController::HttpAuthentication::Basic.encode_credentials('rest-customer1@example.com', 'customer1pw')
get '/api/v1/organizations/import_example', params: {}, headers: @headers.merge('Authorization' => credentials)
assert_response(401)
result = JSON.parse(@response.body)
assert_equal('Not authorized (user)!', result['error'])
end
test '05.02 csv example - admin access' do
credentials = ActionController::HttpAuthentication::Basic.encode_credentials('rest-admin@example.com', 'adminpw')
get '/api/v1/organizations/import_example', params: {}, headers: @headers.merge('Authorization' => credentials)
assert_response(200)
rows = CSV.parse(@response.body)
header = rows.shift
assert_equal('id', header[0])
assert_equal('name', header[1])
assert_equal('shared', header[2])
assert_equal('domain', header[3])
assert_equal('domain_assignment', header[4])
assert_equal('active', header[5])
assert_equal('note', header[6])
assert(header.include?('members'))
end
test '05.03 csv import - admin access' do
UserInfo.current_user_id = 1
customer1 = User.create_or_update(
login: 'customer1-members@example.com',
firstname: 'Member',
lastname: 'Customer',
email: 'customer1-members@example.com',
password: 'customerpw',
active: true,
)
customer2 = User.create_or_update(
login: 'customer2-members@example.com',
firstname: 'Member',
lastname: 'Customer',
email: 'customer2-members@example.com',
password: 'customerpw',
active: true,
)
UserInfo.current_user_id = nil
credentials = ActionController::HttpAuthentication::Basic.encode_credentials('rest-admin@example.com', 'adminpw')
# invalid file
csv_file = ::Rack::Test::UploadedFile.new(Rails.root.join('test', 'fixtures', 'csv', 'organization_simple_col_not_existing.csv'), 'text/csv')
post '/api/v1/organizations/import?try=true', params: { file: csv_file }, headers: { 'Authorization' => credentials }
assert_response(200)
result = JSON.parse(@response.body)
assert_equal(Hash, result.class)
assert_equal('true', result['try'])
assert_equal(2, result['records'].count)
assert_equal('failed', result['result'])
assert_equal(2, result['errors'].count)
assert_equal("Line 1: unknown attribute 'name2' for Organization.", result['errors'][0])
assert_equal("Line 2: unknown attribute 'name2' for Organization.", result['errors'][1])
# valid file try
csv_file = ::Rack::Test::UploadedFile.new(Rails.root.join('test', 'fixtures', 'csv', 'organization_simple.csv'), 'text/csv')
post '/api/v1/organizations/import?try=true', params: { file: csv_file }, headers: { 'Authorization' => credentials }
assert_response(200)
result = JSON.parse(@response.body)
assert_equal(Hash, result.class)
assert_equal('true', result['try'])
assert_equal(2, result['records'].count)
assert_equal('success', result['result'])
assert_nil(Organization.find_by(name: 'organization-member-import1'))
assert_nil(Organization.find_by(name: 'organization-member-import2'))
# valid file
csv_file = ::Rack::Test::UploadedFile.new(Rails.root.join('test', 'fixtures', 'csv', 'organization_simple.csv'), 'text/csv')
post '/api/v1/organizations/import', params: { file: csv_file }, headers: { 'Authorization' => credentials }
assert_response(200)
result = JSON.parse(@response.body)
assert_equal(Hash, result.class)
assert_nil(result['try'])
assert_equal(2, result['records'].count)
assert_equal('success', result['result'])
organization1 = Organization.find_by(name: 'organization-member-import1')
assert(organization1)
assert_equal(organization1.name, 'organization-member-import1')
assert_equal(organization1.members.count, 1)
assert_equal(organization1.members.first.login, customer1.login)
assert_equal(organization1.active, true)
organization2 = Organization.find_by(name: 'organization-member-import2')
assert(organization2)
assert_equal(organization2.name, 'organization-member-import2')
assert_equal(organization2.members.count, 1)
assert_equal(organization2.members.first.login, customer2.login)
assert_equal(organization2.active, false)
end
end end

View file

@ -0,0 +1,157 @@
require 'test_helper'
require 'rake'
class TextModuleControllerTest < ActionDispatch::IntegrationTest
setup do
# set accept header
@headers = { 'ACCEPT' => 'application/json', 'CONTENT_TYPE' => 'application/json' }
# create agent
roles = Role.where(name: %w[Admin Agent])
groups = Group.all
UserInfo.current_user_id = 1
@admin = User.create_or_update(
login: 'rest-admin',
firstname: 'Rest',
lastname: 'Agent',
email: 'rest-admin@example.com',
password: 'adminpw',
active: true,
roles: roles,
groups: groups,
)
# create agent
roles = Role.where(name: 'Agent')
@agent = User.create_or_update(
login: 'rest-agent@example.com',
firstname: 'Rest',
lastname: 'Agent',
email: 'rest-agent@example.com',
password: 'agentpw',
active: true,
roles: roles,
groups: groups,
)
# create customer without org
roles = Role.where(name: 'Customer')
@customer_without_org = User.create_or_update(
login: 'rest-customer1@example.com',
firstname: 'Rest',
lastname: 'Customer1',
email: 'rest-customer1@example.com',
password: 'customer1pw',
active: true,
roles: roles,
)
# create customer
@customer_with_org = User.create_or_update(
login: 'rest-customer2@example.com',
firstname: 'Rest',
lastname: 'Customer2',
email: 'rest-customer2@example.com',
password: 'customer2pw',
active: true,
roles: roles,
)
UserInfo.current_user_id = nil
end
test '05.01 csv example - customer no access' do
credentials = ActionController::HttpAuthentication::Basic.encode_credentials('rest-customer1@example.com', 'customer1pw')
get '/api/v1/text_modules/import_example', params: {}, headers: @headers.merge('Authorization' => credentials)
assert_response(401)
result = JSON.parse(@response.body)
assert_equal('Not authorized (user)!', result['error'])
end
test '05.02 csv example - admin access' do
TextModule.load('en-en')
credentials = ActionController::HttpAuthentication::Basic.encode_credentials('rest-admin@example.com', 'adminpw')
get '/api/v1/text_modules/import_example', params: {}, headers: @headers.merge('Authorization' => credentials)
assert_response(200)
rows = CSV.parse(@response.body)
header = rows.shift
assert_equal('id', header[0])
assert_equal('name', header[1])
assert_equal('keywords', header[2])
assert_equal('content', header[3])
assert_equal('note', header[4])
assert_equal('active', header[5])
assert_not(header.include?('organization'))
assert_not(header.include?('priority'))
assert_not(header.include?('state'))
assert_not(header.include?('owner'))
assert_not(header.include?('customer'))
end
test '05.03 csv import - admin access' do
credentials = ActionController::HttpAuthentication::Basic.encode_credentials('rest-admin@example.com', 'adminpw')
# invalid file
csv_file = ::Rack::Test::UploadedFile.new(Rails.root.join('test', 'fixtures', 'csv', 'text_module_simple_col_not_existing.csv'), 'text/csv')
post '/api/v1/text_modules/import?try=true', params: { file: csv_file }, headers: { 'Authorization' => credentials }
assert_response(200)
result = JSON.parse(@response.body)
assert_equal(Hash, result.class)
assert_equal('true', result['try'])
assert_equal(2, result['records'].count)
assert_equal('failed', result['result'])
assert_equal(2, result['errors'].count)
assert_equal("Line 1: unknown attribute 'keywords2' for TextModule.", result['errors'][0])
assert_equal("Line 2: unknown attribute 'keywords2' for TextModule.", result['errors'][1])
# valid file try
csv_file = ::Rack::Test::UploadedFile.new(Rails.root.join('test', 'fixtures', 'csv', 'text_module_simple.csv'), 'text/csv')
post '/api/v1/text_modules/import?try=true', params: { file: csv_file }, headers: { 'Authorization' => credentials }
assert_response(200)
result = JSON.parse(@response.body)
assert_equal(Hash, result.class)
assert_equal('true', result['try'])
assert_equal(2, result['records'].count)
assert_equal('success', result['result'])
assert_nil(TextModule.find_by(name: 'some name1'))
assert_nil(TextModule.find_by(name: 'some name2'))
# valid file
csv_file = ::Rack::Test::UploadedFile.new(Rails.root.join('test', 'fixtures', 'csv', 'text_module_simple.csv'), 'text/csv')
post '/api/v1/text_modules/import', params: { file: csv_file }, headers: { 'Authorization' => credentials }
assert_response(200)
result = JSON.parse(@response.body)
assert_equal(Hash, result.class)
assert_nil(result['try'])
assert_equal(2, result['records'].count)
assert_equal('success', result['result'])
text_module1 = TextModule.find_by(name: 'some name1')
assert(text_module1)
assert_equal(text_module1.name, 'some name1')
assert_equal(text_module1.keywords, 'keyword1')
assert_equal(text_module1.content, 'some<br>content1')
assert_equal(text_module1.active, true)
text_module2 = TextModule.find_by(name: 'some name2')
assert(text_module2)
assert_equal(text_module2.name, 'some name2')
assert_equal(text_module2.keywords, 'keyword2')
assert_equal(text_module2.content, 'some content<br>test123')
assert_equal(text_module2.active, true)
end
end

View file

@ -957,4 +957,93 @@ class UserControllerTest < ActionDispatch::IntegrationTest
end end
test '05.01 csv example - customer no access' do
credentials = ActionController::HttpAuthentication::Basic.encode_credentials('rest-customer1@example.com', 'customer1pw')
get '/api/v1/users/import_example', params: {}, headers: @headers.merge('Authorization' => credentials)
assert_response(401)
result = JSON.parse(@response.body)
assert_equal('Not authorized (user)!', result['error'])
end
test '05.02 csv example - admin access' do
credentials = ActionController::HttpAuthentication::Basic.encode_credentials('rest-admin@example.com', 'adminpw')
get '/api/v1/users/import_example', params: {}, headers: @headers.merge('Authorization' => credentials)
assert_response(200)
rows = CSV.parse(@response.body)
header = rows.shift
assert_equal('id', header[0])
assert_equal('login', header[1])
assert_equal('firstname', header[2])
assert_equal('lastname', header[3])
assert_equal('email', header[4])
assert(header.include?('organization'))
end
test '05.03 csv import - admin access' do
credentials = ActionController::HttpAuthentication::Basic.encode_credentials('rest-admin@example.com', 'adminpw')
# invalid file
csv_file = ::Rack::Test::UploadedFile.new(Rails.root.join('test', 'fixtures', 'csv', 'user_simple_col_not_existing.csv'), 'text/csv')
post '/api/v1/users/import?try=true', params: { file: csv_file }, headers: { 'Authorization' => credentials }
assert_response(200)
result = JSON.parse(@response.body)
assert_equal(Hash, result.class)
assert_equal('true', result['try'])
assert_equal(2, result['records'].count)
assert_equal('failed', result['result'])
assert_equal(2, result['errors'].count)
assert_equal("Line 1: unknown attribute 'firstname2' for User.", result['errors'][0])
assert_equal("Line 2: unknown attribute 'firstname2' for User.", result['errors'][1])
# valid file try
csv_file = ::Rack::Test::UploadedFile.new(Rails.root.join('test', 'fixtures', 'csv', 'user_simple.csv'), 'text/csv')
post '/api/v1/users/import?try=true', params: { file: csv_file }, headers: { 'Authorization' => credentials }
assert_response(200)
result = JSON.parse(@response.body)
assert_equal(Hash, result.class)
assert_equal('true', result['try'])
assert_equal(2, result['records'].count)
assert_equal('success', result['result'])
assert_nil(User.find_by(login: 'user-simple-import1'))
assert_nil(User.find_by(login: 'user-simple-import2'))
# valid file
csv_file = ::Rack::Test::UploadedFile.new(Rails.root.join('test', 'fixtures', 'csv', 'user_simple.csv'), 'text/csv')
post '/api/v1/users/import', params: { file: csv_file }, headers: { 'Authorization' => credentials }
assert_response(200)
result = JSON.parse(@response.body)
assert_equal(Hash, result.class)
assert_nil(result['try'])
assert_equal(2, result['records'].count)
assert_equal('success', result['result'])
user1 = User.find_by(login: 'user-simple-import1')
assert(user1)
assert_equal(user1.login, 'user-simple-import1')
assert_equal(user1.firstname, 'firstname-simple-import1')
assert_equal(user1.lastname, 'lastname-simple-import1')
assert_equal(user1.email, 'user-simple-import1@example.com')
assert_equal(user1.active, true)
user2 = User.find_by(login: 'user-simple-import2')
assert(user2)
assert_equal(user2.login, 'user-simple-import2')
assert_equal(user2.firstname, 'firstname-simple-import2')
assert_equal(user2.lastname, 'lastname-simple-import2')
assert_equal(user2.email, 'user-simple-import2@example.com')
assert_equal(user2.active, false)
user1.destroy!
user2.destroy!
end
end end

View file

@ -0,0 +1,4 @@
id;name;members;active
;organization-member-import1;customer1-members@example.com
;organization-member-import2;customer2-members@example.com;false
1 id;name;members;active
2 ;organization-member-import1;customer1-members@example.com
3 ;organization-member-import2;customer2-members@example.com;false

View file

@ -0,0 +1,3 @@
id;name2;shared;domain;domain_assignment;active;note
;org-simple-import1;true;org-simple-import1.example.com;false;true;some note1
;org-simple-import2;true;org-simple-import2.example.com;false;false;some note2
1 id name2 shared domain domain_assignment active note
2 org-simple-import1 true org-simple-import1.example.com false true some note1
3 org-simple-import2 true org-simple-import2.example.com false false some note2

View file

@ -0,0 +1,4 @@
name;keywords;content;note;active;
some name1;keyword1;"some
content1";-;
some name2;keyword2;some content<br>test123
Can't render this file because it has a wrong number of fields in line 2.

View file

@ -0,0 +1,3 @@
name;keywords2;content;note;active;
some name1;keyword1;"some content1";-;
some name2;keyword2;some content<br>test123
Can't render this file because it has a wrong number of fields in line 2.

3
test/fixtures/csv/user_simple.csv vendored Normal file
View file

@ -0,0 +1,3 @@
login;firstname;lastname;email;active;
user-simple-import1;firstname-simple-import1;lastname-simple-import1;user-simple-import1@example.com;true
user-simple-import2;firstname-simple-import2;lastname-simple-import2;user-simple-import2@example.com;false
1 login;firstname;lastname;email;active;
2 user-simple-import1;firstname-simple-import1;lastname-simple-import1;user-simple-import1@example.com;true
3 user-simple-import2;firstname-simple-import2;lastname-simple-import2;user-simple-import2@example.com;false

View file

@ -0,0 +1,3 @@
login;firstname2;lastname;email;active;
user-simple-import1;firstname-simple-import1;lastname-simple-import1;user-simple-import1@example.com;true
user-simple-import2;firstname-simple-import2;lastname-simple-import2;user-simple-import2@example.com;false
1 login;firstname2;lastname;email;active;
2 user-simple-import1;firstname-simple-import1;lastname-simple-import1;user-simple-import1@example.com;true
3 user-simple-import2;firstname-simple-import2;lastname-simple-import2;user-simple-import2@example.com;false

View file

@ -0,0 +1,209 @@
require 'test_helper'
class OrganizationCsvImportTest < ActiveSupport::TestCase
test 'import example verify' do
csv_string = Organization.csv_example
rows = CSV.parse(csv_string)
header = rows.shift
assert_equal('id', header[0])
assert_equal('name', header[1])
assert_equal('shared', header[2])
assert_equal('domain', header[3])
assert_equal('domain_assignment', header[4])
assert_equal('active', header[5])
assert_equal('note', header[6])
assert(header.include?('members'))
end
test 'simple import' do
csv_string = "id;name;shared;domain;domain_assignment;active;note\n;org-simple-import1;true;org-simple-import1.example.com;false;true;some note1\n;org-simple-import2;true;org-simple-import2.example.com;false;false;some note2\n"
result = Organization.csv_import(
string: csv_string,
parse_params: {
col_sep: ';',
},
try: true,
)
assert_equal(true, result[:try])
assert_equal(2, result[:records].count)
assert_equal('success', result[:result])
assert_nil(Organization.find_by(name: 'org-simple-import1'))
assert_nil(Organization.find_by(name: 'org-simple-import2'))
result = Organization.csv_import(
string: csv_string,
parse_params: {
col_sep: ';',
},
try: false,
)
assert_equal(false, result[:try])
assert_equal(2, result[:records].count)
assert_equal('success', result[:result])
organization1 = Organization.find_by(name: 'org-simple-import1')
assert(organization1)
assert_equal(organization1.name, 'org-simple-import1')
assert_equal(organization1.shared, true)
assert_equal(organization1.domain, 'org-simple-import1.example.com')
assert_equal(organization1.domain_assignment, false)
assert_equal(organization1.note, 'some note1')
assert_equal(organization1.active, true)
organization2 = Organization.find_by(name: 'org-simple-import2')
assert(organization2)
assert_equal(organization2.name, 'org-simple-import2')
assert_equal(organization2.shared, true)
assert_equal(organization2.domain, 'org-simple-import2.example.com')
assert_equal(organization2.domain_assignment, false)
assert_equal(organization2.note, 'some note2')
assert_equal(organization2.active, false)
organization1.destroy!
organization2.destroy!
end
test 'simple import with invalid id' do
csv_string = "id;name;shared;domain;domain_assignment;active;note;\n999999999;organization-simple-invalid_id-import1;\n;organization-simple-invalid_id-import2;\n"
result = Organization.csv_import(
string: csv_string,
parse_params: {
col_sep: ';',
},
try: true,
)
assert_equal(true, result[:try])
assert_equal(1, result[:errors].count)
assert_equal('failed', result[:result])
assert_equal("Line 1: unknown record with id '999999999' for Organization.", result[:errors][0])
assert_nil(Organization.find_by(name: 'organization-simple-invalid_id-import1'))
assert_nil(Organization.find_by(name: 'organization-simple-invalid_id-import2'))
result = Organization.csv_import(
string: csv_string,
parse_params: {
col_sep: ';',
},
try: false,
)
assert_equal(false, result[:try])
assert_equal(1, result[:records].count)
assert_equal('failed', result[:result])
assert_nil(Organization.find_by(name: 'organization-simple-invalid_id-import1'))
organization2 = Organization.find_by(name: 'organization-simple-invalid_id-import2')
assert(organization2)
assert_equal(organization2.name, 'organization-simple-invalid_id-import2')
assert_equal(organization2.active, true)
organization2.destroy!
end
test 'simple import with members' do
UserInfo.current_user_id = 1
name = rand(999_999_999)
customer1 = User.create_or_update(
login: "customer1-members#{name}@example.com",
firstname: 'Member',
lastname: "Customer#{name}",
email: "customer1-members#{name}@example.com",
password: 'customerpw',
active: true,
)
customer2 = User.create_or_update(
login: "customer2-members#{name}@example.com",
firstname: 'Member',
lastname: "Customer#{name}",
email: "customer2-members#{name}@example.com",
password: 'customerpw',
active: true,
)
csv_string = "id;name;members;\n;organization-member-import1;\n;organization-member-import2;#{customer1.email}\n;;#{customer2.email}"
result = Organization.csv_import(
string: csv_string,
parse_params: {
col_sep: ';',
},
try: true,
)
assert_equal(true, result[:try])
assert_equal(2, result[:records].count)
assert_equal('success', result[:result])
assert_nil(Organization.find_by(name: 'organization-member-import1'))
assert_nil(Organization.find_by(name: 'organization-member-import2'))
result = Organization.csv_import(
string: csv_string,
parse_params: {
col_sep: ';',
},
try: false,
)
assert_equal(false, result[:try])
assert_equal(2, result[:records].count)
assert_equal('success', result[:result])
organization1 = Organization.find_by(name: 'organization-member-import1')
assert(organization1)
assert_equal(organization1.name, 'organization-member-import1')
assert_equal(organization1.members.count, 0)
organization2 = Organization.find_by(name: 'organization-member-import2')
assert(organization2)
assert_equal(organization2.name, 'organization-member-import2')
assert_equal(organization2.members.count, 2)
customer1.destroy!
customer2.destroy!
organization1.destroy!
organization2.destroy!
end
test 'invalid attributes' do
csv_string = "name;note;not existing\norganization-invalid-import1;some note;abc\norganization-invalid-import2;some other note;123; with not exsiting header\n"
result = Organization.csv_import(
string: csv_string,
parse_params: {
col_sep: ';',
},
try: true,
)
assert_equal(true, result[:try])
assert_equal(2, result[:errors].count)
assert_equal('failed', result[:result])
assert_equal("Line 1: unknown attribute 'not existing' for Organization.", result[:errors][0])
assert_equal("Line 2: unknown attribute 'not existing' for Organization.", result[:errors][1])
assert_nil(Organization.find_by(name: 'organization-invalid-import1'))
assert_nil(Organization.find_by(name: 'organization-invalid-import2'))
result = Organization.csv_import(
string: csv_string,
parse_params: {
col_sep: ';',
},
try: false,
)
assert_equal(false, result[:try])
assert_equal(2, result[:errors].count)
assert_equal('failed', result[:result])
assert_equal("Line 1: unknown attribute 'not existing' for Organization.", result[:errors][0])
assert_equal("Line 2: unknown attribute 'not existing' for Organization.", result[:errors][1])
assert_nil(Organization.find_by(name: 'organization-invalid-import1'))
assert_nil(Organization.find_by(name: 'organization-invalid-import2'))
end
end

View file

@ -0,0 +1,72 @@
require 'test_helper'
class TextModuleCsvImportTest < ActiveSupport::TestCase
test 'import example verify' do
TextModule.load('en-en')
csv_string = TextModule.csv_example
rows = CSV.parse(csv_string)
header = rows.shift
assert_equal('id', header[0])
assert_equal('name', header[1])
assert_equal('keywords', header[2])
assert_equal('content', header[3])
assert_equal('note', header[4])
assert_equal('active', header[5])
assert_not(header.include?('organization'))
assert_not(header.include?('priority'))
assert_not(header.include?('state'))
assert_not(header.include?('owner'))
assert_not(header.include?('customer'))
end
test 'simple import' do
csv_string = "name;keywords;content;note;active;\nsome name1;keyword1;\"some\ncontent1\";-;\nsome name2;keyword2;some content<br>test123\n"
result = TextModule.csv_import(
string: csv_string,
parse_params: {
col_sep: ';',
},
try: true,
)
assert_equal(true, result[:try])
assert_equal(2, result[:records].count)
assert_equal('success', result[:result])
assert_nil(TextModule.find_by(name: 'some name1'))
assert_nil(TextModule.find_by(name: 'some name2'))
result = TextModule.csv_import(
string: csv_string,
parse_params: {
col_sep: ';',
},
try: false,
)
assert_equal(false, result[:try])
assert_equal(2, result[:records].count)
assert_equal('success', result[:result])
text_module1 = TextModule.find_by(name: 'some name1')
assert(text_module1)
assert_equal(text_module1.name, 'some name1')
assert_equal(text_module1.keywords, 'keyword1')
assert_equal(text_module1.content, 'some<br>content1')
assert_equal(text_module1.active, true)
text_module2 = TextModule.find_by(name: 'some name2')
assert(text_module2)
assert_equal(text_module2.name, 'some name2')
assert_equal(text_module2.keywords, 'keyword2')
assert_equal(text_module2.content, 'some content<br>test123')
assert_equal(text_module2.active, true)
text_module1.destroy!
text_module2.destroy!
end
end

View file

@ -0,0 +1,172 @@
require 'test_helper'
class TicketCsvImportTest < ActiveSupport::TestCase
test 'import example verify' do
csv_string = Ticket.csv_example
rows = CSV.parse(csv_string)
header = rows.shift
assert_equal('id', header[0])
assert_equal('number', header[1])
assert_equal('title', header[2])
assert_equal('note', header[3])
assert_equal('first_response_at', header[4])
assert_equal('first_response_escalation_at', header[5])
assert(header.include?('organization'))
assert(header.include?('priority'))
assert(header.include?('state'))
assert(header.include?('owner'))
assert(header.include?('customer'))
end
test 'simple import' do
csv_string = "id;number;title;state;priority;owner;customer;group;note\n;123456;some title1;new;2 normal;-;nicole.braun@zammad.org;Users;some note1\n;123457;some title2;closed;1 low;admin@example.com;nicole.braun@zammad.org;Users;some note2\n"
result = Ticket.csv_import(
string: csv_string,
parse_params: {
col_sep: ';',
},
try: true,
)
assert_equal(true, result[:try])
assert_equal(2, result[:records].count)
assert_equal('success', result[:result])
assert_nil(Ticket.find_by(number: '123456'))
assert_nil(Ticket.find_by(number: '123457'))
result = Ticket.csv_import(
string: csv_string,
parse_params: {
col_sep: ';',
},
try: false,
)
assert_equal(false, result[:try])
assert_equal(2, result[:records].count)
assert_equal('success', result[:result])
ticket1 = Ticket.find_by(number: '123456')
assert(ticket1)
assert_equal(ticket1.number, '123456')
assert_equal(ticket1.title, 'some title1')
assert_equal(ticket1.state.name, 'new')
assert_equal(ticket1.priority.name, '2 normal')
assert_equal(ticket1.owner.login, '-')
assert_equal(ticket1.customer.login, 'nicole.braun@zammad.org')
assert_equal(ticket1.note, 'some note1')
ticket2 = Ticket.find_by(number: '123457')
assert(ticket2)
assert_equal(ticket2.number, '123457')
assert_equal(ticket2.title, 'some title2')
assert_equal(ticket2.state.name, 'closed')
assert_equal(ticket2.priority.name, '1 low')
assert_equal(ticket2.owner.login, 'admin@example.com')
assert_equal(ticket2.customer.login, 'nicole.braun@zammad.org')
assert_equal(ticket2.note, 'some note2')
ticket1.destroy!
ticket2.destroy!
end
test 'simple import with invalid id' do
csv_string = "id;number;title;state;priority;owner;customer;group;note\n999999999;123456;some title1;new;2 normal;-;nicole.braun@zammad.org;Users;some note1\n;123457;some title2;closed;1 low;admin@example.com;nicole.braun@zammad.org;Users;some note2\n"
result = Ticket.csv_import(
string: csv_string,
parse_params: {
col_sep: ';',
},
try: true,
)
assert_equal(true, result[:try])
assert_equal(1, result[:errors].count)
assert_equal('failed', result[:result])
assert_equal("Line 1: unknown record with id '999999999' for Ticket.", result[:errors][0])
assert_nil(Ticket.find_by(number: '123456'))
assert_nil(Ticket.find_by(number: '123457'))
result = Ticket.csv_import(
string: csv_string,
parse_params: {
col_sep: ';',
},
try: false,
)
assert_equal(false, result[:try])
assert_equal(1, result[:records].count)
assert_equal('failed', result[:result])
assert_nil(Ticket.find_by(number: '123456'))
ticket2 = Ticket.find_by(number: '123457')
assert(ticket2)
assert_equal(ticket2.title, 'some title2')
assert_equal(ticket2.note, 'some note2')
csv_string = "id;number;title;state;priority;owner;customer;group;note\n999999999;123456;some title1;new;2 normal;-;nicole.braun@zammad.org;Users;some note1\n;123457;some title22;closed;1 low;admin@example.com;nicole.braun@zammad.org;Users;some note22\n"
result = Ticket.csv_import(
string: csv_string,
parse_params: {
col_sep: ';',
},
try: false,
)
assert_equal(false, result[:try])
assert_equal(1, result[:records].count)
assert_equal('failed', result[:result])
assert_nil(Ticket.find_by(number: '123456'))
ticket2 = Ticket.find_by(number: '123457')
assert(ticket2)
assert_equal(ticket2.title, 'some title22')
assert_equal(ticket2.note, 'some note22')
ticket2.destroy!
end
test 'invalid attributes' do
csv_string = "id;number;not_existing;state;priority;owner;customer;group;note\n;123456;some title1;new;2 normal;-;nicole.braun@zammad.org;Users;some note1\n;123457;some title2;closed;1 low;admin@example.com;nicole.braun@zammad.org;Users;some note2\n"
result = Ticket.csv_import(
string: csv_string,
parse_params: {
col_sep: ';',
},
try: true,
)
assert_equal(true, result[:try])
assert_equal(2, result[:errors].count)
assert_equal('failed', result[:result])
assert_equal("Line 1: unknown attribute 'not_existing' for Ticket.", result[:errors][0])
assert_equal("Line 2: unknown attribute 'not_existing' for Ticket.", result[:errors][1])
assert_nil(Ticket.find_by(number: '123456'))
assert_nil(Ticket.find_by(number: '123457'))
result = Ticket.csv_import(
string: csv_string,
parse_params: {
col_sep: ';',
},
try: false,
)
assert_equal(false, result[:try])
assert_equal(2, result[:errors].count)
assert_equal('failed', result[:result])
assert_equal("Line 1: unknown attribute 'not_existing' for Ticket.", result[:errors][0])
assert_equal("Line 2: unknown attribute 'not_existing' for Ticket.", result[:errors][1])
assert_nil(Ticket.find_by(number: '123456'))
assert_nil(Ticket.find_by(number: '123457'))
end
end

View file

@ -0,0 +1,416 @@
require 'test_helper'
class UserCsvImportTest < ActiveSupport::TestCase
test 'import example verify' do
csv_string = User.csv_example
rows = CSV.parse(csv_string)
header = rows.shift
assert_equal('id', header[0])
assert_equal('login', header[1])
assert_equal('firstname', header[2])
assert_equal('lastname', header[3])
assert_equal('email', header[4])
assert(header.include?('organization'))
end
test 'simple import' do
csv_string = "login;firstname;lastname;email;active;\nuser-simple-import1;firstname-simple-import1;lastname-simple-import1;user-simple-import1@example.com;true\nuser-simple-import2;firstname-simple-import2;lastname-simple-import2;user-simple-import2@example.com;false\n"
result = User.csv_import(
string: csv_string,
parse_params: {
col_sep: ';',
},
try: true,
)
assert_equal(true, result[:try])
assert_equal(2, result[:records].count)
assert_equal('success', result[:result])
assert_nil(User.find_by(login: 'user-simple-import1'))
assert_nil(User.find_by(login: 'user-simple-import2'))
result = User.csv_import(
string: csv_string,
parse_params: {
col_sep: ';',
},
try: false,
)
assert_equal(false, result[:try])
assert_equal(2, result[:records].count)
assert_equal('success', result[:result])
user1 = User.find_by(login: 'user-simple-import1')
assert(user1)
assert_equal(user1.login, 'user-simple-import1')
assert_equal(user1.firstname, 'firstname-simple-import1')
assert_equal(user1.lastname, 'lastname-simple-import1')
assert_equal(user1.email, 'user-simple-import1@example.com')
assert_equal(user1.active, true)
user2 = User.find_by(login: 'user-simple-import2')
assert(user2)
assert_equal(user2.login, 'user-simple-import2')
assert_equal(user2.firstname, 'firstname-simple-import2')
assert_equal(user2.lastname, 'lastname-simple-import2')
assert_equal(user2.email, 'user-simple-import2@example.com')
assert_equal(user2.active, false)
user1.destroy!
user2.destroy!
end
test 'simple import with invalid id' do
csv_string = "id;login;firstname;lastname;email;active;\n999999999;user-simple-invalid_id-import1;firstname-simple-import1;lastname-simple-import1;user-simple-invalid_id-import1@example.com;true\n;user-simple-invalid_id-import2;firstname-simple-import2;lastname-simple-import2;user-simple-invalid_id-import2@example.com;false\n"
result = User.csv_import(
string: csv_string,
parse_params: {
col_sep: ';',
},
try: true,
)
assert_equal(true, result[:try])
assert_equal(1, result[:errors].count)
assert_equal('failed', result[:result])
assert_equal("Line 1: unknown record with id '999999999' for User.", result[:errors][0])
assert_nil(User.find_by(login: 'user-simple-invalid_id-import1'))
assert_nil(User.find_by(login: 'user-simple-invalid_id-import2'))
result = User.csv_import(
string: csv_string,
parse_params: {
col_sep: ';',
},
try: false,
)
assert_equal(false, result[:try])
assert_equal(1, result[:records].count)
assert_equal('failed', result[:result])
assert_nil(User.find_by(login: 'user-simple-invalid_id-import1'))
user2 = User.find_by(login: 'user-simple-invalid_id-import2')
assert(user2)
assert_equal(user2.login, 'user-simple-invalid_id-import2')
assert_equal(user2.firstname, 'firstname-simple-import2')
assert_equal(user2.lastname, 'lastname-simple-import2')
assert_equal(user2.email, 'user-simple-invalid_id-import2@example.com')
assert_equal(user2.active, false)
user2.destroy!
end
test 'simple import with read only id' do
csv_string = "id;login;firstname;lastname;email;active;\n1;user-simple-readonly_id-import1;firstname-simple-import1;lastname-simple-import1;user-simple-readonly_id-import1@example.com;true\n;user-simple-readonly_id-import2;firstname-simple-import2;lastname-simple-import2;user-simple-readonly_id-import2@example.com;false\n"
result = User.csv_import(
string: csv_string,
parse_params: {
col_sep: ';',
},
try: true,
)
assert_equal(true, result[:try])
assert_equal(1, result[:errors].count)
assert_equal('failed', result[:result])
assert_equal("Line 1: unable to update record with id '1' for User.", result[:errors][0])
assert_nil(User.find_by(login: 'user-simple-readonly_id-import1'))
assert_nil(User.find_by(login: 'user-simple-readonly_id-import2'))
result = User.csv_import(
string: csv_string,
parse_params: {
col_sep: ';',
},
try: false,
)
assert_equal(false, result[:try])
assert_equal(1, result[:records].count)
assert_equal('failed', result[:result])
assert_nil(User.find_by(login: 'user-simple-readonly_id-import1'))
user2 = User.find_by(login: 'user-simple-readonly_id-import2')
assert(user2)
assert_equal(user2.login, 'user-simple-readonly_id-import2')
assert_equal(user2.firstname, 'firstname-simple-import2')
assert_equal(user2.lastname, 'lastname-simple-import2')
assert_equal(user2.email, 'user-simple-readonly_id-import2@example.com')
assert_equal(user2.active, false)
user2.destroy!
end
test 'simple import with roles' do
UserInfo.current_user_id = 1
admin = User.create_or_update(
login: 'admin1@example.com',
firstname: 'Admin',
lastname: '1',
email: 'admin1@example.com',
password: 'agentpw',
active: true,
roles: Role.where(name: 'Admin'),
)
csv_string = "login;firstname;lastname;email;roles;\nuser-role-import1;firstname-role-import1;lastname-role-import1;user-role-import1@example.com;Customer;\nuser-role-import2;firstname-role-import2;lastname-role-import2;user-role-import2@example.com;Agent\n;;;;Admin"
result = User.csv_import(
string: csv_string,
parse_params: {
col_sep: ';',
},
try: true,
)
assert_equal(true, result[:try])
assert_equal(2, result[:records].count)
assert_equal('success', result[:result])
assert_nil(User.find_by(login: 'user-role-import1'))
assert_nil(User.find_by(login: 'user-role-import2'))
result = User.csv_import(
string: csv_string,
parse_params: {
col_sep: ';',
},
try: false,
)
assert_equal(false, result[:try])
assert_equal(2, result[:records].count)
assert_equal('success', result[:result])
user1 = User.find_by(login: 'user-role-import1')
assert(user1)
assert_equal(user1.login, 'user-role-import1')
assert_equal(user1.firstname, 'firstname-role-import1')
assert_equal(user1.lastname, 'lastname-role-import1')
assert_equal(user1.email, 'user-role-import1@example.com')
assert_equal(user1.roles.count, 1)
user2 = User.find_by(login: 'user-role-import2')
assert(user2)
assert_equal(user2.login, 'user-role-import2')
assert_equal(user2.firstname, 'firstname-role-import2')
assert_equal(user2.lastname, 'lastname-role-import2')
assert_equal(user2.email, 'user-role-import2@example.com')
assert_equal(user2.roles.count, 2)
user1.destroy!
user2.destroy!
admin.destroy!
end
test 'simple import + fixed params' do
csv_string = "login;firstname;lastname;email\nuser-simple-import-fixed1;firstname-simple-import-fixed1;lastname-simple-import-fixed1;user-simple-import-fixed1@example.com\nuser-simple-import-fixed2;firstname-simple-import-fixed2;lastname-simple-import-fixed2;user-simple-import-fixed2@example.com\n"
result = User.csv_import(
string: csv_string,
parse_params: {
col_sep: ';',
},
fixed_params: {
note: 'some note',
},
try: true,
)
assert_equal(true, result[:try])
assert_equal(2, result[:records].count)
assert_equal('success', result[:result])
assert_nil(User.find_by(login: 'user-simple-import-fixed1'))
assert_nil(User.find_by(login: 'user-simple-import-fixed2'))
result = User.csv_import(
string: csv_string,
parse_params: {
col_sep: ';',
},
fixed_params: {
note: 'some note',
},
try: false,
)
assert_equal(false, result[:try])
assert_equal(2, result[:records].count)
assert_equal('success', result[:result])
user1 = User.find_by(login: 'user-simple-import-fixed1')
user2 = User.find_by(login: 'user-simple-import-fixed2')
assert(user1)
assert_equal('some note', user1.note)
assert_equal('user-simple-import-fixed1', user1.login)
assert_equal('firstname-simple-import-fixed1', user1.firstname)
assert_equal('lastname-simple-import-fixed1', user1.lastname)
assert_equal('user-simple-import-fixed1@example.com', user1.email)
assert(user2)
assert_equal('some note', user2.note)
assert_equal('user-simple-import-fixed2', user2.login)
assert_equal('firstname-simple-import-fixed2', user2.firstname)
assert_equal('lastname-simple-import-fixed2', user2.lastname)
assert_equal('user-simple-import-fixed2@example.com', user2.email)
user1.destroy!
user2.destroy!
end
test 'duplicate import' do
csv_string = "login;firstname;lastname;email\nuser-duplicate-import1;firstname-duplicate-import1;firstname-duplicate-import1;user-duplicate-import1@example.com\nuser-duplicate-import2;firstname-duplicate-import2;firstname-duplicate-import2;user-duplicate-import2@example.com\nuser-duplicate-import2;firstname-duplicate-import3;firstname-duplicate-import3;user-duplicate-import3@example.com"
result = User.csv_import(
string: csv_string,
parse_params: {
col_sep: ';',
},
try: true,
)
assert_equal(true, result[:try])
assert_equal(3, result[:records].count)
assert_equal('success', result[:result])
assert_nil(User.find_by(login: 'user-duplicate-import1'))
assert_nil(User.find_by(login: 'user-duplicate-import2'))
assert_nil(User.find_by(login: 'user-duplicate-import3'))
result = User.csv_import(
string: csv_string,
parse_params: {
col_sep: ';',
},
try: false,
)
assert_equal(false, result[:try])
assert_equal(3, result[:records].count)
assert_equal('success', result[:result])
assert(User.find_by(login: 'user-duplicate-import1'))
assert(User.find_by(login: 'user-duplicate-import2'))
assert_nil(User.find_by(login: 'user-duplicate-import3'))
User.find_by(login: 'user-duplicate-import1').destroy!
User.find_by(login: 'user-duplicate-import2').destroy!
end
test 'invalid attributes' do
csv_string = "login;firstname2;lastname;email\nuser-invalid-import1;firstname-invalid-import1;firstname-invalid-import1;user-invalid-import1@example.com\nuser-invalid-import2;firstname-invalid-import2;firstname-invalid-import2;user-invalid-import2@example.com\n"
result = User.csv_import(
string: csv_string,
parse_params: {
col_sep: ';',
},
try: true,
)
assert_equal(true, result[:try])
assert_equal(2, result[:errors].count)
assert_equal('failed', result[:result])
assert_equal("Line 1: unknown attribute 'firstname2' for User.", result[:errors][0])
assert_equal("Line 2: unknown attribute 'firstname2' for User.", result[:errors][1])
assert_nil(User.find_by(login: 'user-invalid-import1'))
assert_nil(User.find_by(login: 'user-invalid-import2'))
result = User.csv_import(
string: csv_string,
parse_params: {
col_sep: ';',
},
try: false,
)
assert_equal(false, result[:try])
assert_equal(2, result[:errors].count)
assert_equal('failed', result[:result])
assert_equal("Line 1: unknown attribute 'firstname2' for User.", result[:errors][0])
assert_equal("Line 2: unknown attribute 'firstname2' for User.", result[:errors][1])
assert_nil(User.find_by(login: 'user-invalid-import1'))
assert_nil(User.find_by(login: 'user-invalid-import2'))
end
test 'reference import' do
csv_string = "login;firstname;lastname;email;organization\nuser-reference-import1;firstname-reference-import1;firstname-reference-import1;user-reference-import1@example.com;organization-reference-import1\nuser-reference-import2;firstname-reference-import2;firstname-reference-import2;user-reference-import2@example.com;organization-reference-import2\nuser-reference-import3;firstname-reference-import3;firstname-reference-import3;user-reference-import3@example.com;Zammad Foundation\n"
result = User.csv_import(
string: csv_string,
parse_params: {
col_sep: ';',
},
try: true,
)
assert_equal(true, result[:try])
assert_equal(2, result[:errors].count)
assert_equal('failed', result[:result])
assert_nil(User.find_by(login: 'user-reference-import1'))
assert_nil(User.find_by(login: 'user-reference-import2'))
assert_nil(User.find_by(login: 'user-reference-import3'))
assert_equal("Line 1: No lookup value found for 'organization': \"organization-reference-import1\"", result[:errors][0])
assert_equal("Line 2: No lookup value found for 'organization': \"organization-reference-import2\"", result[:errors][1])
result = User.csv_import(
string: csv_string,
parse_params: {
col_sep: ';',
},
try: false,
)
assert_equal(false, result[:try])
assert_equal(2, result[:errors].count)
assert_equal('failed', result[:result])
assert_nil(User.find_by(login: 'user-reference-import1'))
assert_nil(User.find_by(login: 'user-reference-import2'))
assert(User.find_by(login: 'user-reference-import3'))
assert_equal("Line 1: No lookup value found for 'organization': \"organization-reference-import1\"", result[:errors][0])
assert_equal("Line 2: No lookup value found for 'organization': \"organization-reference-import2\"", result[:errors][1])
UserInfo.current_user_id = 1
orgaization1 = Organization.create_if_not_exists(name: 'organization-reference-import1')
orgaization2 = Organization.create_if_not_exists(name: 'organization-reference-import2')
result = User.csv_import(
string: csv_string,
parse_params: {
col_sep: ';',
},
try: true,
)
assert_equal(true, result[:try])
assert_equal(0, result[:errors].count)
assert_equal('success', result[:result])
assert_nil(User.find_by(login: 'user-reference-import1'))
assert_nil(User.find_by(login: 'user-reference-import2'))
assert(User.find_by(login: 'user-reference-import3'))
result = User.csv_import(
string: csv_string,
parse_params: {
col_sep: ';',
},
try: false,
)
assert_equal(false, result[:try])
assert_equal(0, result[:errors].count)
assert_equal('success', result[:result])
assert(User.find_by(login: 'user-reference-import1'))
assert(User.find_by(login: 'user-reference-import2'))
assert(User.find_by(login: 'user-reference-import3'))
User.find_by(login: 'user-reference-import1').destroy!
User.find_by(login: 'user-reference-import2').destroy!
User.find_by(login: 'user-reference-import3').destroy!
orgaization1.destroy!
orgaization2.destroy!
end
end

View file

@ -570,7 +570,6 @@ class UserTest < ActiveSupport::TestCase
test 'ensure roles' do test 'ensure roles' do
name = rand(999_999_999) name = rand(999_999_999)
admin = User.create_or_update( admin = User.create_or_update(
login: "admin-role#{name}@example.com", login: "admin-role#{name}@example.com",
firstname: 'Role', firstname: 'Role',