207 lines
7.9 KiB
Ruby
207 lines
7.9 KiB
Ruby
class HelpdeskWidgetController < ApplicationController
|
|
unloadable
|
|
layout false
|
|
helper :custom_fields
|
|
protect_from_forgery :except => [:widget, :load_form, :load_custom_fields, :avatar, :create_ticket, :iframe]
|
|
skip_before_filter :check_if_login_required, :only => [:widget, :load_form, :load_custom_fields, :avatar, :create_ticket, :iframe]
|
|
|
|
before_filter :prepare_data, :only => [:load_custom_fields, :create_ticket]
|
|
after_filter :set_access_control_header
|
|
|
|
def load_form
|
|
render :json => schema.to_json
|
|
end
|
|
|
|
def load_custom_fields
|
|
@issue = @project.issues.build(:tracker => @tracker) if @tracker
|
|
@enabled_cf = HelpdeskSettings["helpdesk_widget_available_custom_fields", nil]
|
|
end
|
|
|
|
def avatar
|
|
user = User.where(:login => params[:login]).first
|
|
return render :nothing => true, :status => 404 unless user
|
|
if user.try(:avatar).nil?
|
|
avatar_thumb, avatar_type = gravatar_avatar(user) if Setting.gravatar_enabled?
|
|
else
|
|
avatar_thumb, avatar_type = local_avatar(user.avatar)
|
|
end
|
|
return render :nothing => true, :status => 404 unless avatar_thumb
|
|
send_avatar(avatar_thumb, avatar_type)
|
|
end
|
|
|
|
def send_avatar(avatar_thumb, avatar_type)
|
|
send_file avatar_thumb, :filename => (request.env['HTTP_USER_AGENT'] =~ %r{MSIE} ? ERB::Util.url_encode(params[:login]) : params[:login]),
|
|
:type => avatar_type,
|
|
:disposition => 'inline'
|
|
end
|
|
|
|
def gravatar_avatar(user)
|
|
email = user.mail if user.respond_to?(:mail)
|
|
email = user.to_s[/<(.+?)>/, 1] unless email
|
|
return [nil, nil] unless email
|
|
default = Setting.gravatar_default ? CGI::escape(Setting.gravatar_default) : ''
|
|
temp_file = Tempfile.new([user.login, '.jpeg'])
|
|
temp_file.binmode
|
|
open("http://www.gravatar.com/avatar/#{Digest::MD5.hexdigest(email)}?rating=PG&size=54&default=#{default}") do |url_file|
|
|
temp_file.write(url_file.read)
|
|
end
|
|
temp_file.rewind
|
|
[temp_file, 'image/jpeg']
|
|
end
|
|
|
|
def local_avatar(user_avatar)
|
|
return nil unless user_avatar.readable? || user_avatar.thumbnailable?
|
|
if (defined?(RedmineContacts::Thumbnail) == 'constant') && Redmine::Thumbnail.convert_available?
|
|
target = File.join(user_avatar.class.thumbnails_storage_path, "#{user_avatar.id}_#{user_avatar.digest}_54x54.thumb")
|
|
thumbnail = RedmineContacts::Thumbnail.generate(user_avatar.diskfile, target, '54x54')
|
|
elsif Redmine::Thumbnail.convert_available?
|
|
thumbnail = user_avatar.thumbnail(:size => '54x54')
|
|
else
|
|
thumbnail = user_avatar.diskfile
|
|
end
|
|
[thumbnail, detect_content_type(user_avatar)]
|
|
end
|
|
|
|
def create_ticket
|
|
@issue = prepare_issue
|
|
@issue.helpdesk_ticket = prepare_helpdesk_ticket
|
|
result =
|
|
if valid_email? && @issue.save
|
|
save_attachment(@issue)
|
|
HelpdeskMailer.auto_answer(@issue.helpdesk_ticket.customer, @issue).deliver if HelpdeskSettings["helpdesk_send_notification", @project].to_i > 0
|
|
{ :result => true, :errors => [] }
|
|
else
|
|
{ :result => false, :errors => prepared_errors }
|
|
end
|
|
render :json => result
|
|
end
|
|
|
|
private
|
|
|
|
def prepare_data
|
|
@project = Project.find(params[:project_id])
|
|
@tracker = @project.trackers.where(:id => params[:tracker_id]).first
|
|
end
|
|
|
|
def schema
|
|
if HelpdeskSettings["helpdesk_widget_enable", nil].to_i > 0
|
|
projects = Project.has_module('contacts_helpdesk').where(:id => HelpdeskSettings[:helpdesk_widget_available_projects, nil])
|
|
else
|
|
projects = []
|
|
end
|
|
data_schema = {}
|
|
data_schema[:projects] = Hash[projects.map { |project| [project.name.capitalize, project.id] }]
|
|
data_schema[:projects_data] = {}
|
|
projects.each do |project|
|
|
data_schema[:projects_data][project.id] = {}
|
|
if HelpdeskSettings["helpdesk_tracker", project] && HelpdeskSettings["helpdesk_tracker", project] != 'all'
|
|
data_schema[:projects_data][project.id][:trackers] = Hash[Tracker.where(id: HelpdeskSettings["helpdesk_tracker", project])
|
|
.map { |tracker| [tracker.name, tracker.id] }]
|
|
else
|
|
data_schema[:projects_data][project.id][:trackers] = Hash[project.trackers.map { |tracker| [tracker.name, tracker.id] }]
|
|
end
|
|
end
|
|
data_schema[:custom_fields] = Hash[IssueCustomField.where(id: HelpdeskSettings["helpdesk_widget_available_custom_fields", nil])
|
|
.map { |custom_field| [custom_field.name, custom_field.id] }]
|
|
data_schema[:avatar] = HelpdeskSettings[:helpdesk_widget_avatar_login, nil]
|
|
data_schema
|
|
end
|
|
|
|
def prepared_errors
|
|
errors_hash = @issue.errors.dup
|
|
# Username
|
|
if errors_hash[:'helpdesk_ticket.customer.first_name'].present?
|
|
@issue.errors.delete(:'helpdesk_ticket.customer.first_name')
|
|
@issue.errors[:username] = errors_hash[:'helpdesk_ticket.customer.first_name'].collect { |error| ['Username', error].join(' ') }
|
|
end
|
|
|
|
# Subject
|
|
if errors_hash[:subject].present?
|
|
errors = errors_hash[:subject].collect { |error| ['Subject', error].join(' ') }
|
|
@issue.errors[:subject].clear
|
|
@issue.errors[:subject] = errors
|
|
end
|
|
|
|
# Description
|
|
if params[:issue][:description].empty?
|
|
@issue.errors[:description] = I18n.t(:label_helpdesk_widget_ticket_error_description)
|
|
end
|
|
|
|
# Nested objects
|
|
if errors_hash[:'helpdesk_ticket.customer.projects'].present?
|
|
@issue.errors.delete(:'helpdesk_ticket.customer.projects')
|
|
end
|
|
@issue.errors
|
|
end
|
|
|
|
def prepare_issue
|
|
redmine_user = User.where(id: params[:redmine_user]).first
|
|
author = redmine_user.present? && redmine_user.allowed_to?(:edit_helpdesk_tickets, @project) ? redmine_user : User.anonymous
|
|
issue = @project.issues.build(:tracker => @tracker, :author => author)
|
|
issue.safe_attributes = params[:issue].deep_dup
|
|
issue.assigned_to = widget_contact.find_assigned_user(@project, HelpdeskSettings["helpdesk_assigned_to", @project])
|
|
issue
|
|
end
|
|
|
|
def prepare_helpdesk_ticket
|
|
HelpdeskTicket.new(:from_address => params[:email],
|
|
:ticket_date => Time.now,
|
|
:customer => widget_contact,
|
|
:issue => @issue,
|
|
:source => HelpdeskTicket::HELPDESK_WEB_SOURCE)
|
|
end
|
|
|
|
def save_attachment(issue)
|
|
return unless params[:attachment].present?
|
|
attachment_hash = split_base64(params[:attachment])
|
|
attachment = Attachment.new(file: Base64.decode64(attachment_hash[:data]))
|
|
attachment.filename = params[:attachment_name] || [Redmine::Utils.random_hex(16), attachment_hash[:extension]].join('.')
|
|
attachment.content_type = attachment_hash[:type]
|
|
attachment.author = User.anonymous
|
|
issue.attachments << attachment
|
|
issue.save
|
|
end
|
|
|
|
def split_base64(uri)
|
|
matcher = uri.match(/^data:(.*?)\;(.*?),(.*)$/)
|
|
{ type: matcher[1],
|
|
encoder: matcher[2],
|
|
data: matcher[3],
|
|
extension: matcher[1].split('/')[1] }
|
|
end
|
|
|
|
def widget_contact
|
|
return @widget_contact if @widget_contact
|
|
contacts = Contact.find_by_emails([params[:email]])
|
|
return @widget_contact = contacts.first if contacts.any?
|
|
@widget_contact = Contact.new(:email => params[:email])
|
|
@widget_contact.first_name, @widget_contact.last_name = params[:username].split(' ')
|
|
@widget_contact.projects << @project
|
|
@widget_contact
|
|
end
|
|
|
|
def set_access_control_header
|
|
headers['Access-Control-Allow-Origin'] = '*'
|
|
headers['X-Frame-Options'] = '*'
|
|
end
|
|
|
|
def valid_email?
|
|
if params[:email].empty?
|
|
@issue.errors[:email] = 'Email cannot be empty'
|
|
return false
|
|
elsif params[:email].match(/\A([\w\.\+\-]+)@([\w\-]+\.)+([\w]{2,})\z/i).nil?
|
|
@issue.errors[:email] = 'Email is incorrect'
|
|
return false
|
|
end
|
|
true
|
|
end
|
|
|
|
def detect_content_type(attachment)
|
|
content_type = attachment.content_type
|
|
if content_type.blank?
|
|
content_type = Redmine::MimeType.of(attachment.filename)
|
|
end
|
|
content_type.to_s
|
|
end
|
|
end
|