creates_ticket_articles.rb 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. module CreatesTicketArticles # rubocop:disable Metrics/ModuleLength
  3. extend ActiveSupport::Concern
  4. private
  5. def article_create(ticket, params)
  6. # create article if given
  7. form_id = params.delete(:form_id)
  8. subtype = params.delete(:subtype)
  9. # check min. params
  10. raise Exceptions::UnprocessableEntity, __("Need at least an 'article body' field.") if params[:body].nil?
  11. # fill default values
  12. if params[:type_id].blank? && params[:type].blank?
  13. params[:type_id] = Ticket::Article::Type.lookup(name: 'note').id
  14. end
  15. if params[:sender_id].blank? && params[:sender].blank?
  16. sender = 'Customer'
  17. if current_user.permissions?('ticket.agent')
  18. sender = 'Agent'
  19. end
  20. params[:sender_id] = Ticket::Article::Sender.lookup(name: sender).id
  21. end
  22. # remember time accounting values
  23. if params[:time_unit].present?
  24. accounted_time_params = {
  25. time_unit: params[:time_unit],
  26. type_id: params[:accounted_time_type_id],
  27. type: params[:accounted_time_type],
  28. }
  29. end
  30. clean_params = Ticket::Article.association_name_to_id_convert(params)
  31. clean_params = Ticket::Article.param_cleanup(clean_params, true)
  32. # overwrite params
  33. if !current_user.permissions?('ticket.agent')
  34. clean_params[:sender_id] = Ticket::Article::Sender.lookup(name: 'Customer').id
  35. clean_params.delete(:sender)
  36. clean_params.delete(:origin_by_id)
  37. type = Ticket::Article::Type.lookup(id: clean_params[:type_id])
  38. if !type.name.match?(%r{^(note|web)$})
  39. clean_params[:type_id] = Ticket::Article::Type.lookup(name: 'note').id
  40. end
  41. clean_params.delete(:type)
  42. clean_params[:internal] = false
  43. end
  44. article = Ticket::Article.new(clean_params)
  45. article.ticket_id = ticket.id
  46. article.check_mentions_raises_error = true
  47. article.check_email_recipient_raises_error = true
  48. # store dataurl images to store
  49. attachments_inline = []
  50. if article.body && article.content_type =~ %r{text/html}i
  51. (article.body, attachments_inline) = HtmlSanitizer.replace_inline_images(article.body, ticket.id)
  52. end
  53. # find attachments in upload cache
  54. attachments = []
  55. if form_id
  56. attachments += UploadCache
  57. .new(form_id)
  58. .attachments
  59. .reject do |elem|
  60. UploadCache.files_include_attachment?(attachments_inline, elem) || elem.inline?
  61. end
  62. end
  63. # store inline attachments
  64. attachments_inline.each do |attachment|
  65. attachments << {
  66. data: attachment[:data],
  67. filename: attachment[:filename],
  68. preferences: attachment[:preferences],
  69. }
  70. end
  71. # add attachments as param
  72. if params[:attachments].present?
  73. required_keys = %w[mime-type filename data]
  74. preferences_keys = %w[charset mime-type]
  75. params[:attachments].each_with_index do |attachment, index|
  76. # validation
  77. required_keys.each do |key|
  78. next if attachment[key]
  79. raise Exceptions::UnprocessableEntity, "Attachment needs '#{key}' param for attachment with index '#{index}'"
  80. end
  81. preferences = {}
  82. preferences_keys.each do |key|
  83. next if !attachment[key]
  84. store_key = key.tr('-', '_').camelize.gsub(%r{(.+)([A-Z])}, '\1_\2').tr('_', '-')
  85. preferences[store_key] = attachment[key]
  86. end
  87. begin
  88. base64_data = attachment[:data].gsub(%r{[\r\n]}, '')
  89. attachment_data = Base64.strict_decode64(base64_data)
  90. rescue ArgumentError
  91. raise Exceptions::UnprocessableEntity, "Invalid base64 for attachment with index '#{index}'"
  92. end
  93. attachments << {
  94. data: attachment_data,
  95. filename: attachment[:filename],
  96. preferences: preferences,
  97. }
  98. end
  99. end
  100. article.attachments = attachments
  101. # set subtype of present
  102. article.preferences[:subtype] = subtype if subtype.present?
  103. article.save!
  104. # account time
  105. if accounted_time_params.present?
  106. clean_accounted_time_params = Ticket::TimeAccounting.association_name_to_id_convert(accounted_time_params)
  107. clean_accounted_time_params = Ticket::TimeAccounting.param_cleanup(clean_accounted_time_params, true)
  108. time_accounting = Ticket::TimeAccounting.new(
  109. ticket_id: article.ticket_id,
  110. ticket_article_id: article.id,
  111. **clean_accounted_time_params,
  112. )
  113. authorize! time_accounting, :create?
  114. time_accounting.save!
  115. end
  116. return article if form_id.blank?
  117. # clear in-progress state from taskbar
  118. Taskbar
  119. .where(user_id: current_user.id)
  120. .find { |taskbar| taskbar.persisted_form_id == form_id }
  121. &.update!(state: {})
  122. # remove temporary attachment cache
  123. UploadCache.new(form_id).destroy
  124. article
  125. end
  126. end