diff --git a/app/controllers/concerns/clones_ticket_article_attachments.rb b/app/controllers/concerns/clones_ticket_article_attachments.rb index da8248030..211d6f29f 100644 --- a/app/controllers/concerns/clones_ticket_article_attachments.rb +++ b/app/controllers/concerns/clones_ticket_article_attachments.rb @@ -12,8 +12,13 @@ module ClonesTicketArticleAttachments ) attachments = [] article.attachments.each do |new_attachment| - next if new_attachment.preferences['Content-ID'].present? next if new_attachment.preferences['content-alternative'] == true + if article.content_type.present? && article.content_type =~ %r{text/html}i + next if new_attachment.preferences['content_disposition'].present? && new_attachment.preferences['content_disposition'] !~ /inline/ + if new_attachment.preferences['Content-ID'].present? && article.body.present? + next if article.body.match?(/#{Regexp.quote(new_attachment.preferences['Content-ID'])}/i) + end + end already_added = false existing_attachments.each do |existing_attachment| next if existing_attachment.filename != new_attachment.filename || existing_attachment.size != new_attachment.size diff --git a/test/controllers/ticket_articles_controller_test.rb b/test/controllers/ticket_articles_controller_test.rb index 0fb8be1d0..4444990e4 100644 --- a/test/controllers/ticket_articles_controller_test.rb +++ b/test/controllers/ticket_articles_controller_test.rb @@ -325,4 +325,194 @@ AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO article = Ticket::Article.find_by( ticket_id: result['id'] ) assert_nil(article.origin_by_id) end + + test '04.01 ticket split with html - check attachments' do + ticket = Ticket.create!( + title: 'some title', + group: Group.lookup(name: 'Users'), + customer_id: @customer_without_org.id, + state: Ticket::State.lookup(name: 'new'), + priority: Ticket::Priority.lookup(name: '2 normal'), + updated_by_id: @agent.id, + created_by_id: @agent.id, + ) + article = Ticket::Article.create!( + type: Ticket::Article::Type.lookup(name: 'note'), + sender: Ticket::Article::Sender.lookup(name: 'Customer'), + from: 'sender', + subject: 'subject', + body: 'test test ', + content_type: 'text/html', + ticket_id: ticket.id, + updated_by_id: 1, + created_by_id: 1, + ) + Store.add( + object: 'Ticket::Article', + o_id: article.id, + data: 'content_file1_normally_should_be_an_image', + filename: 'some_file1.jpg', + preferences: { + 'Content-Type' => 'image/jpeg', + 'Mime-Type' => 'image/jpeg', + 'Content-ID' => '15.274327094.140938@zammad.example.com', + 'Content-Disposition' => 'inline', + }, + created_by_id: 1, + ) + Store.add( + object: 'Ticket::Article', + o_id: article.id, + data: 'content_file2_normally_should_be_an_image', + filename: 'some_file2.jpg', + preferences: { + 'Content-Type' => 'image/jpeg', + 'Mime-Type' => 'image/jpeg', + 'Content-ID' => '15.274327094.140938.2@zammad.example.com', + 'Content-Disposition' => 'inline', + }, + created_by_id: 1, + ) + Store.add( + object: 'Ticket::Article', + o_id: article.id, + data: 'content_file3_normally_should_be_an_image', + filename: 'some_file3.jpg', + preferences: { + 'Content-Type' => 'image/jpeg', + 'Mime-Type' => 'image/jpeg', + 'Content-ID' => '15.274327094.140938.3@zammad.example.com', + }, + created_by_id: 1, + ) + Store.add( + object: 'Ticket::Article', + o_id: article.id, + data: 'content_file4_normally_should_be_an_image', + filename: 'some_file4.jpg', + preferences: { + 'Content-Type' => 'image/jpeg', + 'Mime-Type' => 'image/jpeg', + 'Content-ID' => '15.274327094.140938.4@zammad.example.com', + }, + created_by_id: 1, + ) + Store.add( + object: 'Ticket::Article', + o_id: article.id, + data: 'content_file1_normally_should_be_an_pdf', + filename: 'Rechnung_RE-2018-200.pdf', + preferences: { + 'Content-Type' => 'application/octet-stream; name="Rechnung_RE-2018-200.pdf"', + 'Mime-Type' => 'application/octet-stream', + 'Content-ID' => '8AB0BEC88984EE4EBEF643C79C8E0346@zammad.example.com', + 'Content-Description' => 'Rechnung_RE-2018-200.pdf', + 'Content-Disposition' => 'attachment', + }, + created_by_id: 1, + ) + + credentials = ActionController::HttpAuthentication::Basic.encode_credentials('tickets-agent@example.com', 'agentpw') + + params = { + form_id: 'new_form_id123', + } + post "/api/v1/ticket_attachment_upload_clone_by_article/#{article.id}", params: params.to_json, headers: @headers.merge('Authorization' => credentials) + assert_response(200) + result = JSON.parse(@response.body) + assert_equal(Hash, result.class) + assert(result['attachments']) + assert_equal(result['attachments'].count, 3) + + post "/api/v1/ticket_attachment_upload_clone_by_article/#{article.id}", params: params.to_json, headers: @headers.merge('Authorization' => credentials) + assert_response(200) + result = JSON.parse(@response.body) + assert_equal(Hash, result.class) + assert(result['attachments']) + assert_equal(result['attachments'].count, 0) + end + + test '04.02 ticket split with plain - check attachments' do + ticket = Ticket.create!( + title: 'some title', + group: Group.lookup(name: 'Users'), + customer_id: @customer_without_org.id, + state: Ticket::State.lookup(name: 'new'), + priority: Ticket::Priority.lookup(name: '2 normal'), + updated_by_id: @agent.id, + created_by_id: @agent.id, + ) + article = Ticket::Article.create!( + type: Ticket::Article::Type.lookup(name: 'note'), + sender: Ticket::Article::Sender.lookup(name: 'Customer'), + from: 'sender', + subject: 'subject', + body: 'test ', + content_type: 'text/plain', + ticket_id: ticket.id, + updated_by_id: 1, + created_by_id: 1, + ) + Store.add( + object: 'Ticket::Article', + o_id: article.id, + data: 'content_file1_normally_should_be_an_image', + filename: 'some_file1.jpg', + preferences: { + 'Content-Type' => 'image/jpeg', + 'Mime-Type' => 'image/jpeg', + 'Content-ID' => '15.274327094.140938@zammad.example.com', + 'Content-Disposition' => 'inline', + }, + created_by_id: 1, + ) + Store.add( + object: 'Ticket::Article', + o_id: article.id, + data: 'content_file1_normally_should_be_an_image', + filename: 'some_file2.jpg', + preferences: { + 'Content-Type' => 'image/jpeg', + 'Mime-Type' => 'image/jpeg', + 'Content-ID' => '15.274327094.140938.2@zammad.example.com', + 'Content-Disposition' => 'inline', + }, + created_by_id: 1, + ) + Store.add( + object: 'Ticket::Article', + o_id: article.id, + data: 'content_file1_normally_should_be_an_pdf', + filename: 'Rechnung_RE-2018-200.pdf', + preferences: { + 'Content-Type' => 'application/octet-stream; name="Rechnung_RE-2018-200.pdf"', + 'Mime-Type' => 'application/octet-stream', + 'Content-ID' => '8AB0BEC88984EE4EBEF643C79C8E0346@zammad.example.com', + 'Content-Description' => 'Rechnung_RE-2018-200.pdf', + 'Content-Disposition' => 'attachment', + }, + created_by_id: 1, + ) + + credentials = ActionController::HttpAuthentication::Basic.encode_credentials('tickets-agent@example.com', 'agentpw') + + params = { + form_id: 'new_form_id123', + } + post "/api/v1/ticket_attachment_upload_clone_by_article/#{article.id}", params: params.to_json, headers: @headers.merge('Authorization' => credentials) + assert_response(200) + result = JSON.parse(@response.body) + assert_equal(Hash, result.class) + assert(result['attachments']) + assert_equal(result['attachments'].count, 3) + + post "/api/v1/ticket_attachment_upload_clone_by_article/#{article.id}", params: params.to_json, headers: @headers.merge('Authorization' => credentials) + assert_response(200) + result = JSON.parse(@response.body) + assert_equal(Hash, result.class) + assert(result['attachments']) + assert_equal(result['attachments'].count, 0) + + end + end diff --git a/test/controllers/tickets_controller_test.rb b/test/controllers/tickets_controller_test.rb index 4d4ad6dce..e2619e870 100644 --- a/test/controllers/tickets_controller_test.rb +++ b/test/controllers/tickets_controller_test.rb @@ -1456,4 +1456,204 @@ AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO end + test '05.01 ticket split with html - check attachments' do + ticket = Ticket.create!( + title: 'some title', + group: Group.lookup(name: 'Users'), + customer_id: @customer_without_org.id, + state: Ticket::State.lookup(name: 'new'), + priority: Ticket::Priority.lookup(name: '2 normal'), + updated_by_id: @agent.id, + created_by_id: @agent.id, + ) + article = Ticket::Article.create!( + type: Ticket::Article::Type.lookup(name: 'note'), + sender: Ticket::Article::Sender.lookup(name: 'Customer'), + from: 'sender', + subject: 'subject', + body: 'test test ', + content_type: 'text/html', + ticket_id: ticket.id, + updated_by_id: 1, + created_by_id: 1, + ) + Store.add( + object: 'Ticket::Article', + o_id: article.id, + data: 'content_file1_normally_should_be_an_image', + filename: 'some_file1.jpg', + preferences: { + 'Content-Type' => 'image/jpeg', + 'Mime-Type' => 'image/jpeg', + 'Content-ID' => '15.274327094.140938@zammad.example.com', + 'Content-Disposition' => 'inline', + }, + created_by_id: 1, + ) + Store.add( + object: 'Ticket::Article', + o_id: article.id, + data: 'content_file2_normally_should_be_an_image', + filename: 'some_file2.jpg', + preferences: { + 'Content-Type' => 'image/jpeg', + 'Mime-Type' => 'image/jpeg', + 'Content-ID' => '15.274327094.140938.2@zammad.example.com', + 'Content-Disposition' => 'inline', + }, + created_by_id: 1, + ) + Store.add( + object: 'Ticket::Article', + o_id: article.id, + data: 'content_file3_normally_should_be_an_image', + filename: 'some_file3.jpg', + preferences: { + 'Content-Type' => 'image/jpeg', + 'Mime-Type' => 'image/jpeg', + 'Content-ID' => '15.274327094.140938.3@zammad.example.com', + }, + created_by_id: 1, + ) + Store.add( + object: 'Ticket::Article', + o_id: article.id, + data: 'content_file4_normally_should_be_an_image', + filename: 'some_file4.jpg', + preferences: { + 'Content-Type' => 'image/jpeg', + 'Mime-Type' => 'image/jpeg', + 'Content-ID' => '15.274327094.140938.4@zammad.example.com', + }, + created_by_id: 1, + ) + Store.add( + object: 'Ticket::Article', + o_id: article.id, + data: 'content_file1_normally_should_be_an_pdf', + filename: 'Rechnung_RE-2018-200.pdf', + preferences: { + 'Content-Type' => 'application/octet-stream; name="Rechnung_RE-2018-200.pdf"', + 'Mime-Type' => 'application/octet-stream', + 'Content-ID' => '8AB0BEC88984EE4EBEF643C79C8E0346@zammad.example.com', + 'Content-Description' => 'Rechnung_RE-2018-200.pdf', + 'Content-Disposition' => 'attachment', + }, + created_by_id: 1, + ) + + credentials = ActionController::HttpAuthentication::Basic.encode_credentials('tickets-agent@example.com', 'agentpw') + + get "/api/v1/ticket_split?ticket_id=#{ticket.id}&article_id=#{article.id}&form_id=new_form_id123", params: {}, headers: @headers.merge('Authorization' => credentials) + assert_response(200) + result = JSON.parse(@response.body) + assert_equal(Hash, result.class) + assert(result['assets']) + assert(result['assets']['Ticket']) + assert(result['assets']['Ticket'][ticket.id.to_s]) + assert(result['assets']['TicketArticle'][article.id.to_s]) + assert(result['attachments']) + assert_equal(result['attachments'].count, 3) + + get "/api/v1/ticket_split?ticket_id=#{ticket.id}&article_id=#{article.id}&form_id=new_form_id123", params: {}, headers: @headers.merge('Authorization' => credentials) + assert_response(200) + result = JSON.parse(@response.body) + assert_equal(Hash, result.class) + assert(result['assets']) + assert(result['assets']['Ticket']) + assert(result['assets']['Ticket'][ticket.id.to_s]) + assert(result['assets']['TicketArticle'][article.id.to_s]) + assert(result['attachments']) + assert_equal(result['attachments'].count, 0) + + end + + test '05.02 ticket split with plain - check attachments' do + ticket = Ticket.create!( + title: 'some title', + group: Group.lookup(name: 'Users'), + customer_id: @customer_without_org.id, + state: Ticket::State.lookup(name: 'new'), + priority: Ticket::Priority.lookup(name: '2 normal'), + updated_by_id: @agent.id, + created_by_id: @agent.id, + ) + article = Ticket::Article.create!( + type: Ticket::Article::Type.lookup(name: 'note'), + sender: Ticket::Article::Sender.lookup(name: 'Customer'), + from: 'sender', + subject: 'subject', + body: 'test ', + content_type: 'text/plain', + ticket_id: ticket.id, + updated_by_id: 1, + created_by_id: 1, + ) + Store.add( + object: 'Ticket::Article', + o_id: article.id, + data: 'content_file1_normally_should_be_an_image', + filename: 'some_file1.jpg', + preferences: { + 'Content-Type' => 'image/jpeg', + 'Mime-Type' => 'image/jpeg', + 'Content-ID' => '15.274327094.140938@zammad.example.com', + 'Content-Disposition' => 'inline', + }, + created_by_id: 1, + ) + Store.add( + object: 'Ticket::Article', + o_id: article.id, + data: 'content_file1_normally_should_be_an_image', + filename: 'some_file2.jpg', + preferences: { + 'Content-Type' => 'image/jpeg', + 'Mime-Type' => 'image/jpeg', + 'Content-ID' => '15.274327094.140938.2@zammad.example.com', + 'Content-Disposition' => 'inline', + }, + created_by_id: 1, + ) + Store.add( + object: 'Ticket::Article', + o_id: article.id, + data: 'content_file1_normally_should_be_an_pdf', + filename: 'Rechnung_RE-2018-200.pdf', + preferences: { + 'Content-Type' => 'application/octet-stream; name="Rechnung_RE-2018-200.pdf"', + 'Mime-Type' => 'application/octet-stream', + 'Content-ID' => '8AB0BEC88984EE4EBEF643C79C8E0346@zammad.example.com', + 'Content-Description' => 'Rechnung_RE-2018-200.pdf', + 'Content-Disposition' => 'attachment', + }, + created_by_id: 1, + ) + + credentials = ActionController::HttpAuthentication::Basic.encode_credentials('tickets-agent@example.com', 'agentpw') + + get "/api/v1/ticket_split?ticket_id=#{ticket.id}&article_id=#{article.id}&form_id=new_form_id123", params: {}, headers: @headers.merge('Authorization' => credentials) + assert_response(200) + result = JSON.parse(@response.body) + assert_equal(Hash, result.class) + assert(result['assets']) + assert(result['assets']['Ticket']) + assert(result['assets']['Ticket'][ticket.id.to_s]) + assert(result['assets']['TicketArticle'][article.id.to_s]) + assert(result['attachments']) + assert_equal(result['attachments'].count, 3) + + get "/api/v1/ticket_split?ticket_id=#{ticket.id}&article_id=#{article.id}&form_id=new_form_id123", params: {}, headers: @headers.merge('Authorization' => credentials) + assert_response(200) + result = JSON.parse(@response.body) + assert_equal(Hash, result.class) + assert(result['assets']) + assert(result['assets']['Ticket']) + assert(result['assets']['Ticket'][ticket.id.to_s]) + assert(result['assets']['TicketArticle'][article.id.to_s]) + assert(result['attachments']) + assert_equal(result['attachments'].count, 0) + + end + end