article_attachments_spec.rb 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. # Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
  2. require 'rails_helper'
  3. RSpec.describe 'Ticket Article Attachments', type: :request, authenticated_as: -> { agent } do
  4. let(:group) { create(:group) }
  5. let(:agent) do
  6. create(:agent, groups: [Group.lookup(name: 'Users'), group])
  7. end
  8. describe 'request handling' do
  9. context 'with attachment urls' do
  10. let(:ticket1) { create(:ticket, group: group) }
  11. let(:article1) { create(:ticket_article, ticket: ticket1) }
  12. let(:ticket2) { create(:ticket, group: group) }
  13. let(:article2) { create(:ticket_article, ticket: ticket2) }
  14. let(:store_file_content_type) { 'text/plain' }
  15. let(:store_file_content) { 'some content' }
  16. let(:store_file_name) { 'some_file.txt' }
  17. let!(:store_file) do
  18. create(:store,
  19. object: 'Ticket::Article',
  20. o_id: article1.id,
  21. data: store_file_content,
  22. filename: store_file_name,
  23. preferences: {
  24. 'Content-Type' => store_file_content_type,
  25. })
  26. end
  27. context 'with one article attachment' do
  28. it 'does test different attachment urls' do
  29. get "/api/v1/ticket_attachment/#{ticket1.id}/#{article1.id}/#{store_file.id}", params: {}
  30. expect(response).to have_http_status(:ok)
  31. expect('some content').to eq(response.body)
  32. get "/api/v1/ticket_attachment/#{ticket1.id}/#{article2.id}/#{store_file.id}", params: {}
  33. expect(response).to have_http_status(:forbidden)
  34. expect(response.body).to match(%r{403: Forbidden})
  35. end
  36. end
  37. context 'with attachment from merged ticket' do
  38. before do
  39. ticket1.merge_to(
  40. ticket_id: ticket2.id,
  41. user_id: 1,
  42. )
  43. end
  44. it 'does test attachment url after ticket merge' do
  45. get "/api/v1/ticket_attachment/#{ticket2.id}/#{article1.id}/#{store_file.id}", params: {}
  46. expect(response).to have_http_status(:ok)
  47. expect('some content').to eq(response.body)
  48. get "/api/v1/ticket_attachment/#{ticket2.id}/#{article2.id}/#{store_file.id}", params: {}
  49. expect(response).to have_http_status(:forbidden)
  50. expect(response.body).to match(%r{403: Forbidden})
  51. # allow access via merged ticket id also
  52. get "/api/v1/ticket_attachment/#{ticket1.id}/#{article1.id}/#{store_file.id}", params: {}
  53. expect(response).to have_http_status(:ok)
  54. expect('some content').to eq(response.body)
  55. get "/api/v1/ticket_attachment/#{ticket1.id}/#{article2.id}/#{store_file.id}", params: {}
  56. expect(response).to have_http_status(:forbidden)
  57. expect(response.body).to match(%r{403: Forbidden})
  58. end
  59. end
  60. context 'with different file content types' do
  61. context 'without allowed inline file content type' do
  62. it 'disposition can not be inline' do
  63. get "/api/v1/ticket_attachment/#{ticket1.id}/#{article1.id}/#{store_file.id}?disposition=inline", params: {}
  64. expect(response.headers['Content-Disposition']).to include('attachment')
  65. end
  66. it 'content-type is correct' do
  67. get "/api/v1/ticket_attachment/#{ticket1.id}/#{article1.id}/#{store_file.id}?disposition=inline", params: {}
  68. expect(response.headers['Content-Type']).to include('text/plain')
  69. end
  70. end
  71. context 'with binary file content type' do
  72. let(:store_file_content_type) { 'image/svg+xml' }
  73. it 'disposition can not be inline' do
  74. get "/api/v1/ticket_attachment/#{ticket1.id}/#{article1.id}/#{store_file.id}?disposition=inline", params: {}
  75. expect(response.headers['Content-Disposition']).to include('attachment')
  76. end
  77. it 'content-type was forced to active storage binary content type' do
  78. get "/api/v1/ticket_attachment/#{ticket1.id}/#{article1.id}/#{store_file.id}?disposition=inline", params: {}
  79. expect(response.headers['Content-Type']).to include('application/octet-stream')
  80. end
  81. end
  82. context 'with allowed inline file content type' do
  83. let(:store_file_content_type) { 'application/pdf' }
  84. it 'disposition is inline' do
  85. get "/api/v1/ticket_attachment/#{ticket1.id}/#{article1.id}/#{store_file.id}?disposition=inline", params: {}
  86. expect(response.headers['Content-Disposition']).to include('inline')
  87. end
  88. end
  89. context 'with calendar preview' do
  90. let(:store_file_content) do
  91. File.read(Rails.root.join('spec/fixtures/files/calendar/basic.ics'))
  92. end
  93. let(:store_file_name) { 'basic.ics' }
  94. let(:store_file_content_type) { 'text/calendar' }
  95. let(:expected_event) do
  96. {
  97. 'title' => 'Test Summary',
  98. 'location' => 'https://us.zoom.us/j/example?pwd=test',
  99. 'start_date' => '2021-07-27T10:30:00.000+02:00',
  100. 'end_date' => '2021-07-27T12:00:00.000+02:00',
  101. 'attendees' => ['M.bob@example.com', 'J.doe@example.com'],
  102. 'organizer' => 'f.sample@example.com',
  103. 'description' => 'Test description'
  104. }
  105. end
  106. it 'renders a parsed calender data' do
  107. get "/api/v1/ticket_attachment/#{ticket1.id}/#{article1.id}/#{store_file.id}?view=preview&type=calendar", params: {}
  108. expect(response).to have_http_status(:ok)
  109. expect(json_response).to be_a_kind_of(Hash)
  110. expect(json_response['filename']).to eq store_file_name
  111. expect(json_response['events'].first).to include(expected_event)
  112. end
  113. end
  114. end
  115. end
  116. context 'when attachment actions are used' do
  117. it 'does test attachments for split' do
  118. email_file_path = Rails.root.join('test/data/mail/mail024.box')
  119. email_raw_string = File.read(email_file_path)
  120. ticket_p, article_p, _user_p = Channel::EmailParser.new.process({}, email_raw_string)
  121. get '/api/v1/ticket_split', params: { form_id: '1234-2', ticket_id: ticket_p.id, article_id: article_p.id }, as: :json
  122. expect(response).to have_http_status(:ok)
  123. expect(json_response['assets']).to be_truthy
  124. expect(json_response['attachments']).to be_a_kind_of(Array)
  125. expect(json_response['attachments'].count).to eq(1)
  126. expect(json_response['attachments'][0]['filename']).to eq('rulesets-report.csv')
  127. end
  128. it 'does test attachments for forward' do
  129. email_file_path = Rails.root.join('test/data/mail/mail008.box')
  130. email_raw_string = File.read(email_file_path)
  131. _ticket_p, article_p, _user_p = Channel::EmailParser.new.process({}, email_raw_string)
  132. post "/api/v1/ticket_attachment_upload_clone_by_article/#{article_p.id}", params: {}, as: :json
  133. expect(response).to have_http_status(:unprocessable_entity)
  134. expect(json_response).to be_a_kind_of(Hash)
  135. expect(json_response['error']).to eq("Need 'form_id' to add attachments to new form.")
  136. post "/api/v1/ticket_attachment_upload_clone_by_article/#{article_p.id}", params: { form_id: '1234-1' }, as: :json
  137. expect(response).to have_http_status(:ok)
  138. expect(json_response['attachments']).to be_a_kind_of(Array)
  139. expect(json_response['attachments']).to be_blank
  140. email_file_path = Rails.root.join('test/data/mail/mail024.box')
  141. email_raw_string = File.read(email_file_path)
  142. _ticket_p, article_p, _user_p = Channel::EmailParser.new.process({}, email_raw_string)
  143. post "/api/v1/ticket_attachment_upload_clone_by_article/#{article_p.id}", params: { form_id: '1234-2' }, as: :json
  144. expect(response).to have_http_status(:ok)
  145. expect(json_response['attachments']).to be_a_kind_of(Array)
  146. expect(json_response['attachments'].count).to eq(1)
  147. expect(json_response['attachments'][0]['filename']).to eq('rulesets-report.csv')
  148. post "/api/v1/ticket_attachment_upload_clone_by_article/#{article_p.id}", params: { form_id: '1234-2' }, as: :json
  149. expect(response).to have_http_status(:ok)
  150. expect(json_response['attachments']).to be_a_kind_of(Array)
  151. expect(json_response['attachments']).to be_blank
  152. end
  153. end
  154. end
  155. end