2016-10-19 03:11:36 +00:00
|
|
|
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
|
2013-06-12 15:59:58 +00:00
|
|
|
|
2012-04-10 14:06:46 +00:00
|
|
|
class TicketArticlesController < ApplicationController
|
2017-03-09 11:44:51 +00:00
|
|
|
include CreatesTicketArticles
|
2017-08-28 21:31:26 +00:00
|
|
|
include ClonesTicketArticleAttachments
|
2017-03-09 11:44:51 +00:00
|
|
|
|
2020-03-19 09:39:51 +00:00
|
|
|
prepend_before_action -> { authorize! }, only: %i[index import_example import_start]
|
2017-02-15 12:29:25 +00:00
|
|
|
prepend_before_action :authentication_check
|
2012-04-10 14:06:46 +00:00
|
|
|
|
|
|
|
# GET /articles
|
|
|
|
def index
|
2016-06-20 12:13:00 +00:00
|
|
|
model_index_render(Ticket::Article, params)
|
2012-04-10 14:06:46 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
# GET /articles/1
|
|
|
|
def show
|
2016-06-20 12:13:00 +00:00
|
|
|
article = Ticket::Article.find(params[:id])
|
2020-03-19 09:39:51 +00:00
|
|
|
authorize!(article)
|
2016-06-20 12:13:00 +00:00
|
|
|
|
2017-12-14 13:19:24 +00:00
|
|
|
if response_expand?
|
2017-01-31 17:13:45 +00:00
|
|
|
result = article.attributes_with_association_names
|
2016-06-20 12:13:00 +00:00
|
|
|
render json: result, status: :ok
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
2017-12-14 13:19:24 +00:00
|
|
|
if response_full?
|
2016-06-20 12:13:00 +00:00
|
|
|
full = Ticket::Article.full(params[:id])
|
|
|
|
render json: full
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
2017-01-31 17:13:45 +00:00
|
|
|
render json: article.attributes_with_association_names
|
2016-06-21 20:59:03 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
# GET /ticket_articles/by_ticket/1
|
|
|
|
def index_by_ticket
|
|
|
|
ticket = Ticket.find(params[:id])
|
2020-03-19 09:39:51 +00:00
|
|
|
authorize!(ticket, :show?)
|
2016-06-21 20:59:03 +00:00
|
|
|
|
|
|
|
articles = []
|
|
|
|
|
2017-12-14 13:19:24 +00:00
|
|
|
if response_expand?
|
2017-10-01 12:25:52 +00:00
|
|
|
ticket.articles.each do |article|
|
2020-03-19 09:39:51 +00:00
|
|
|
next if !authorized?(article, :show?)
|
2018-10-09 06:17:41 +00:00
|
|
|
|
2017-01-31 17:13:45 +00:00
|
|
|
result = article.attributes_with_association_names
|
2016-06-21 20:59:03 +00:00
|
|
|
articles.push result
|
2017-10-01 12:25:52 +00:00
|
|
|
end
|
2016-06-21 20:59:03 +00:00
|
|
|
|
|
|
|
render json: articles, status: :ok
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
2017-12-14 13:19:24 +00:00
|
|
|
if response_full?
|
2016-06-21 20:59:03 +00:00
|
|
|
assets = {}
|
|
|
|
record_ids = []
|
2017-10-01 12:25:52 +00:00
|
|
|
ticket.articles.each do |article|
|
2020-03-19 09:39:51 +00:00
|
|
|
next if !authorized?(article, :show?)
|
2016-06-21 20:59:03 +00:00
|
|
|
|
|
|
|
record_ids.push article.id
|
|
|
|
assets = article.assets({})
|
2017-10-01 12:25:52 +00:00
|
|
|
end
|
2016-06-21 20:59:03 +00:00
|
|
|
render json: {
|
|
|
|
record_ids: record_ids,
|
2018-12-19 17:31:51 +00:00
|
|
|
assets: assets,
|
2017-12-14 13:19:24 +00:00
|
|
|
}, status: :ok
|
2016-06-21 20:59:03 +00:00
|
|
|
return
|
|
|
|
end
|
|
|
|
|
2017-10-01 12:25:52 +00:00
|
|
|
ticket.articles.each do |article|
|
2020-03-19 09:39:51 +00:00
|
|
|
next if !authorized?(article, :show?)
|
2018-10-09 06:17:41 +00:00
|
|
|
|
2017-01-31 17:13:45 +00:00
|
|
|
articles.push article.attributes_with_association_names
|
2017-10-01 12:25:52 +00:00
|
|
|
end
|
2017-12-14 13:19:24 +00:00
|
|
|
render json: articles, status: :ok
|
2012-04-10 14:06:46 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
# POST /articles
|
|
|
|
def create
|
2016-08-24 11:42:22 +00:00
|
|
|
ticket = Ticket.find(params[:ticket_id])
|
2020-03-19 09:39:51 +00:00
|
|
|
authorize!(ticket)
|
2016-08-24 11:42:22 +00:00
|
|
|
article = article_create(ticket, params)
|
2012-11-13 10:34:45 +00:00
|
|
|
|
2017-12-14 13:19:24 +00:00
|
|
|
if response_expand?
|
2017-01-31 17:13:45 +00:00
|
|
|
result = article.attributes_with_association_names
|
2016-08-24 11:42:22 +00:00
|
|
|
render json: result, status: :created
|
|
|
|
return
|
2012-12-02 10:18:55 +00:00
|
|
|
end
|
2012-04-10 14:06:46 +00:00
|
|
|
|
2017-12-14 13:19:24 +00:00
|
|
|
if response_full?
|
2016-08-24 11:42:22 +00:00
|
|
|
full = Ticket::Article.full(params[:id])
|
|
|
|
render json: full, status: :created
|
|
|
|
return
|
2012-04-10 14:06:46 +00:00
|
|
|
end
|
2016-08-24 11:42:22 +00:00
|
|
|
|
2017-01-31 17:13:45 +00:00
|
|
|
render json: article.attributes_with_association_names, status: :created
|
2012-04-10 14:06:46 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
# PUT /articles/1
|
|
|
|
def update
|
2016-06-07 19:22:08 +00:00
|
|
|
article = Ticket::Article.find(params[:id])
|
2020-03-19 09:39:51 +00:00
|
|
|
authorize!(article)
|
2016-08-24 11:42:22 +00:00
|
|
|
|
2020-10-08 07:19:37 +00:00
|
|
|
# only update internal and highlight info
|
|
|
|
clean_params = {}
|
|
|
|
if !params[:internal].nil?
|
|
|
|
clean_params[:internal] = params[:internal]
|
|
|
|
end
|
|
|
|
if params.dig(:preferences, :highlight).present?
|
|
|
|
clean_params = article.param_preferences_merge(clean_params.merge(
|
|
|
|
preferences: {
|
|
|
|
highlight: params[:preferences][:highlight].to_s
|
|
|
|
}
|
|
|
|
))
|
|
|
|
end
|
2018-07-26 14:24:31 +00:00
|
|
|
|
2017-09-11 11:16:08 +00:00
|
|
|
article.update!(clean_params)
|
2016-08-24 11:42:22 +00:00
|
|
|
|
2017-12-14 13:19:24 +00:00
|
|
|
if response_expand?
|
2017-01-31 17:13:45 +00:00
|
|
|
result = article.attributes_with_association_names
|
2016-08-24 11:42:22 +00:00
|
|
|
render json: result, status: :ok
|
|
|
|
return
|
2012-04-10 14:06:46 +00:00
|
|
|
end
|
2016-08-24 11:42:22 +00:00
|
|
|
|
2017-12-14 13:19:24 +00:00
|
|
|
if response_full?
|
2016-08-24 11:42:22 +00:00
|
|
|
full = Ticket::Article.full(params[:id])
|
|
|
|
render json: full, status: :ok
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
2017-01-31 17:13:45 +00:00
|
|
|
render json: article.attributes_with_association_names, status: :ok
|
2012-04-10 14:06:46 +00:00
|
|
|
end
|
|
|
|
|
2019-11-11 15:47:51 +00:00
|
|
|
# DELETE /api/v1/ticket_articles/:id
|
2012-04-10 14:06:46 +00:00
|
|
|
def destroy
|
2016-06-07 19:22:08 +00:00
|
|
|
article = Ticket::Article.find(params[:id])
|
2020-03-19 09:39:51 +00:00
|
|
|
authorize!(article)
|
|
|
|
article.destroy!
|
|
|
|
render json: {}, status: :ok
|
2012-04-10 14:06:46 +00:00
|
|
|
end
|
2012-09-20 12:08:02 +00:00
|
|
|
|
2017-12-05 15:12:52 +00:00
|
|
|
# POST /ticket_attachment_upload_clone_by_article
|
|
|
|
def ticket_attachment_upload_clone_by_article
|
|
|
|
article = Ticket::Article.find(params[:article_id])
|
2020-03-19 09:39:51 +00:00
|
|
|
authorize!(article.ticket, :show?)
|
2017-12-05 15:12:52 +00:00
|
|
|
|
|
|
|
render json: {
|
2017-08-28 21:31:26 +00:00
|
|
|
attachments: article_attachments_clone(article),
|
2017-12-05 15:12:52 +00:00
|
|
|
}
|
|
|
|
end
|
|
|
|
|
2016-06-07 19:22:08 +00:00
|
|
|
# GET /ticket_attachment/:ticket_id/:article_id/:id
|
2012-09-20 12:08:02 +00:00
|
|
|
def attachment
|
2016-05-10 22:09:10 +00:00
|
|
|
ticket = Ticket.lookup(id: params[:ticket_id])
|
2020-03-19 09:39:51 +00:00
|
|
|
authorize!(ticket, :show?)
|
2017-06-16 20:43:09 +00:00
|
|
|
|
2016-05-10 22:09:10 +00:00
|
|
|
article = Ticket::Article.find(params[:article_id])
|
2012-09-20 12:08:02 +00:00
|
|
|
if ticket.id != article.ticket_id
|
2017-04-04 16:15:29 +00:00
|
|
|
|
|
|
|
# check if requested ticket got merged
|
|
|
|
if ticket.state.state_type.name != 'merged'
|
2021-02-04 08:28:41 +00:00
|
|
|
raise Exceptions::Forbidden, 'No access, article_id/ticket_id is not matching.'
|
2017-04-04 16:15:29 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
ticket = article.ticket
|
2020-03-19 09:39:51 +00:00
|
|
|
authorize!(ticket, :show?)
|
2012-09-20 12:08:02 +00:00
|
|
|
end
|
|
|
|
|
2014-02-05 12:22:14 +00:00
|
|
|
list = article.attachments || []
|
2012-09-20 12:08:02 +00:00
|
|
|
access = false
|
2017-10-01 12:25:52 +00:00
|
|
|
list.each do |item|
|
2012-09-20 12:08:02 +00:00
|
|
|
if item.id.to_i == params[:id].to_i
|
|
|
|
access = true
|
|
|
|
end
|
2017-10-01 12:25:52 +00:00
|
|
|
end
|
2021-02-04 08:28:41 +00:00
|
|
|
raise Exceptions::Forbidden, 'Requested file id is not linked with article_id.' if !access
|
2012-09-20 12:08:02 +00:00
|
|
|
|
|
|
|
# find file
|
|
|
|
file = Store.find(params[:id])
|
2017-01-31 16:55:12 +00:00
|
|
|
|
|
|
|
disposition = sanitized_disposition
|
|
|
|
|
2019-02-14 05:42:41 +00:00
|
|
|
content = nil
|
|
|
|
if params[:view].present? && file.preferences[:resizable] == true
|
|
|
|
if file.preferences[:content_inline] == true && params[:view] == 'inline'
|
|
|
|
content = file.content_inline
|
|
|
|
elsif file.preferences[:content_preview] == true && params[:view] == 'preview'
|
|
|
|
content = file.content_preview
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
if content.blank?
|
|
|
|
content = file.content
|
|
|
|
end
|
|
|
|
|
2012-09-20 12:08:02 +00:00
|
|
|
send_data(
|
2019-02-14 05:42:41 +00:00
|
|
|
content,
|
2018-12-19 17:31:51 +00:00
|
|
|
filename: file.filename,
|
|
|
|
type: file.preferences['Content-Type'] || file.preferences['Mime-Type'] || 'application/octet-stream',
|
2017-01-31 16:55:12 +00:00
|
|
|
disposition: disposition
|
2012-09-20 12:08:02 +00:00
|
|
|
)
|
|
|
|
end
|
|
|
|
|
|
|
|
# GET /ticket_article_plain/1
|
|
|
|
def article_plain
|
2016-05-10 22:09:10 +00:00
|
|
|
article = Ticket::Article.find(params[:id])
|
2020-03-19 09:39:51 +00:00
|
|
|
authorize!(article, :show?)
|
2012-09-20 12:08:02 +00:00
|
|
|
|
2016-12-20 23:07:47 +00:00
|
|
|
file = article.as_raw
|
2012-09-20 12:08:02 +00:00
|
|
|
|
|
|
|
# find file
|
2016-12-20 23:07:47 +00:00
|
|
|
return if !file
|
2015-04-30 15:25:04 +00:00
|
|
|
|
|
|
|
send_data(
|
|
|
|
file.content,
|
2018-12-19 17:31:51 +00:00
|
|
|
filename: file.filename,
|
|
|
|
type: 'message/rfc822',
|
2015-04-30 15:25:04 +00:00
|
|
|
disposition: 'inline'
|
|
|
|
)
|
2012-09-20 12:08:02 +00:00
|
|
|
end
|
|
|
|
|
2018-02-20 04:29:30 +00:00
|
|
|
# @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.
|
2021-02-04 08:28:41 +00:00
|
|
|
# @response_message 403 Forbidden / Invalid session.
|
2018-02-20 04:29:30 +00:00
|
|
|
def import_example
|
|
|
|
csv_string = Ticket::Article.csv_example(
|
|
|
|
col_sep: ',',
|
|
|
|
)
|
|
|
|
send_data(
|
|
|
|
csv_string,
|
2018-12-19 17:31:51 +00:00
|
|
|
filename: 'example.csv',
|
|
|
|
type: 'text/csv',
|
2018-02-20 04:29:30 +00:00
|
|
|
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.
|
2021-02-04 08:28:41 +00:00
|
|
|
# @response_message 403 Forbidden / Invalid session.
|
2018-02-20 04:29:30 +00:00
|
|
|
def import_start
|
|
|
|
if Setting.get('import_mode') != true
|
|
|
|
raise 'Only can import tickets if system is in import mode.'
|
|
|
|
end
|
2018-10-09 06:17:41 +00:00
|
|
|
|
2018-11-06 05:42:52 +00:00
|
|
|
string = params[:data]
|
|
|
|
if string.blank? && params[:file].present?
|
|
|
|
string = params[:file].read.force_encoding('utf-8')
|
|
|
|
end
|
|
|
|
raise Exceptions::UnprocessableEntity, 'No source data submitted!' if string.blank?
|
|
|
|
|
2018-02-20 04:29:30 +00:00
|
|
|
result = Ticket::Article.csv_import(
|
2018-12-19 17:31:51 +00:00
|
|
|
string: string,
|
2018-02-20 04:29:30 +00:00
|
|
|
parse_params: {
|
|
|
|
col_sep: ';',
|
|
|
|
},
|
2018-12-19 17:31:51 +00:00
|
|
|
try: params[:try],
|
2018-02-20 04:29:30 +00:00
|
|
|
)
|
|
|
|
render json: result, status: :ok
|
|
|
|
end
|
|
|
|
|
2020-06-02 11:01:16 +00:00
|
|
|
def retry_security_process
|
|
|
|
article = Ticket::Article.find(params[:id])
|
|
|
|
authorize!(article, :update?)
|
|
|
|
|
|
|
|
result = SecureMailing.retry(article)
|
|
|
|
|
|
|
|
render json: result
|
|
|
|
end
|
|
|
|
|
2017-01-31 16:55:12 +00:00
|
|
|
private
|
|
|
|
|
|
|
|
def sanitized_disposition
|
|
|
|
disposition = params.fetch(:disposition, 'inline')
|
2017-11-23 08:09:44 +00:00
|
|
|
valid_disposition = %w[inline attachment]
|
2017-01-31 16:55:12 +00:00
|
|
|
return disposition if valid_disposition.include?(disposition)
|
2018-10-09 06:17:41 +00:00
|
|
|
|
2021-02-04 08:28:41 +00:00
|
|
|
raise Exceptions::Forbidden, "Invalid disposition #{disposition} requested. Only #{valid_disposition.join(', ')} are valid."
|
2017-01-31 16:55:12 +00:00
|
|
|
end
|
2012-04-10 14:06:46 +00:00
|
|
|
end
|