form_controller.rb 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. # Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
  2. class FormController < ApplicationController
  3. skip_before_action :verify_csrf_token
  4. before_action :cors_preflight_check_execute
  5. after_action :set_access_control_headers_execute
  6. skip_before_action :user_device_check
  7. def configuration
  8. return if !enabled?
  9. return if !fingerprint_exists?
  10. return if limit_reached?
  11. api_path = Rails.configuration.api_path
  12. http_type = Setting.get('http_type')
  13. fqdn = Setting.get('fqdn')
  14. endpoint = "#{http_type}://#{fqdn}#{api_path}/form_submit"
  15. result = {
  16. enabled: Setting.get('form_ticket_create'),
  17. endpoint: endpoint,
  18. token: token_gen(params[:fingerprint])
  19. }
  20. if params[:test] && current_user && current_user.permissions?('admin.channel_formular')
  21. result[:enabled] = true
  22. end
  23. render json: result, status: :ok
  24. end
  25. def submit
  26. return if !enabled?
  27. return if !fingerprint_exists?
  28. return if !token_valid?(params[:token], params[:fingerprint])
  29. return if limit_reached?
  30. # validate input
  31. errors = {}
  32. if params[:name].blank?
  33. errors['name'] = 'required'
  34. end
  35. if params[:email].blank?
  36. errors['email'] = 'required'
  37. elsif !/@/.match?(params[:email])
  38. errors['email'] = 'invalid'
  39. elsif params[:email].match?(/(>|<|\||\!|"|§|'|\$|%|&|\(|\)|\?|\s|\.\.)/)
  40. errors['email'] = 'invalid'
  41. end
  42. if params[:title].blank?
  43. errors['title'] = 'required'
  44. end
  45. if params[:body].blank?
  46. errors['body'] = 'required'
  47. end
  48. # realtime verify
  49. if errors['email'].blank?
  50. begin
  51. address = ValidEmail2::Address.new(params[:email])
  52. if !address || !address.valid? || !address.valid_mx?
  53. errors['email'] = 'invalid'
  54. end
  55. rescue => e
  56. message = e.to_s
  57. Rails.logger.info "Can't verify email #{params[:email]}: #{message}"
  58. # ignore 450, graylistings
  59. errors['email'] = message if !message.match?(/450/)
  60. end
  61. end
  62. if errors.present?
  63. render json: {
  64. errors: errors
  65. }, status: :ok
  66. return
  67. end
  68. name = params[:name].strip
  69. email = params[:email].strip.downcase
  70. customer = User.find_by(email: email)
  71. if !customer
  72. role_ids = Role.signup_role_ids
  73. customer = User.create(
  74. firstname: name,
  75. lastname: '',
  76. email: email,
  77. active: true,
  78. role_ids: role_ids,
  79. updated_by_id: 1,
  80. created_by_id: 1,
  81. )
  82. end
  83. # set current user
  84. UserInfo.current_user_id = customer.id
  85. group = Group.find_by(id: Setting.get('form_ticket_create_group_id'))
  86. if !group
  87. group = Group.where(active: true).first
  88. if !group
  89. group = Group.first
  90. end
  91. end
  92. ticket = Ticket.create!(
  93. group_id: group.id,
  94. customer_id: customer.id,
  95. title: params[:title],
  96. preferences: {
  97. form: {
  98. remote_ip: request.remote_ip,
  99. fingerprint_md5: Digest::MD5.hexdigest(params[:fingerprint]),
  100. }
  101. }
  102. )
  103. article = Ticket::Article.create!(
  104. ticket_id: ticket.id,
  105. type_id: Ticket::Article::Type.find_by(name: 'web').id,
  106. sender_id: Ticket::Article::Sender.find_by(name: 'Customer').id,
  107. body: params[:body],
  108. subject: params[:title],
  109. internal: false,
  110. )
  111. params[:file]&.each do |file|
  112. Store.add(
  113. object: 'Ticket::Article',
  114. o_id: article.id,
  115. data: file.read,
  116. filename: file.original_filename,
  117. preferences: {
  118. 'Mime-Type' => file.content_type,
  119. }
  120. )
  121. end
  122. UserInfo.current_user_id = 1
  123. result = {
  124. ticket: {
  125. id: ticket.id,
  126. number: ticket.number
  127. }
  128. }
  129. render json: result, status: :ok
  130. end
  131. private
  132. def token_gen(fingerprint)
  133. crypt = ActiveSupport::MessageEncryptor.new(Setting.get('application_secret')[0, 32])
  134. fingerprint = "#{Base64.strict_encode64(Setting.get('fqdn'))}:#{Time.zone.now.to_i}:#{Base64.strict_encode64(fingerprint)}"
  135. Base64.strict_encode64(crypt.encrypt_and_sign(fingerprint))
  136. end
  137. def token_valid?(token, fingerprint)
  138. if token.blank?
  139. Rails.logger.info 'No token for form!'
  140. response_access_deny
  141. return false
  142. end
  143. begin
  144. crypt = ActiveSupport::MessageEncryptor.new(Setting.get('application_secret')[0, 32])
  145. result = crypt.decrypt_and_verify(Base64.decode64(token))
  146. rescue
  147. Rails.logger.info 'Invalid token for form!'
  148. response_access_deny
  149. return false
  150. end
  151. if result.blank?
  152. Rails.logger.info 'Invalid token for form!'
  153. response_access_deny
  154. return false
  155. end
  156. parts = result.split(/:/)
  157. if parts.count != 3
  158. Rails.logger.info "Invalid token for form (need to have 3 parts, only #{parts.count} found)!"
  159. response_access_deny
  160. return false
  161. end
  162. fqdn_local = Base64.decode64(parts[0])
  163. if fqdn_local != Setting.get('fqdn')
  164. Rails.logger.info "Invalid token for form (invalid fqdn found #{fqdn_local} != #{Setting.get('fqdn')})!"
  165. response_access_deny
  166. return false
  167. end
  168. fingerprint_local = Base64.decode64(parts[2])
  169. if fingerprint_local != fingerprint
  170. Rails.logger.info "Invalid token for form (invalid fingerprint found #{fingerprint_local} != #{fingerprint})!"
  171. response_access_deny
  172. return false
  173. end
  174. if parts[1].to_i < (Time.zone.now.to_i - 60 * 60 * 24)
  175. Rails.logger.info 'Invalid token for form (token expired})!'
  176. response_access_deny
  177. return false
  178. end
  179. true
  180. end
  181. def limit_reached?
  182. return false if !SearchIndexBackend.enabled?
  183. form_limit_by_ip_per_hour = Setting.get('form_ticket_create_by_ip_per_hour') || 20
  184. result = SearchIndexBackend.search("preferences.form.remote_ip:'#{request.remote_ip}' AND created_at:>now-1h", form_limit_by_ip_per_hour, 'Ticket')
  185. if result.count >= form_limit_by_ip_per_hour.to_i
  186. response_access_deny
  187. return true
  188. end
  189. form_limit_by_ip_per_day = Setting.get('form_ticket_create_by_ip_per_day') || 240
  190. result = SearchIndexBackend.search("preferences.form.remote_ip:'#{request.remote_ip}' AND created_at:>now-1d", form_limit_by_ip_per_day, 'Ticket')
  191. if result.count >= form_limit_by_ip_per_day.to_i
  192. response_access_deny
  193. return true
  194. end
  195. form_limit_per_day = Setting.get('form_ticket_create_per_day') || 5000
  196. result = SearchIndexBackend.search('preferences.form.remote_ip:* AND created_at:>now-1d', form_limit_per_day, 'Ticket')
  197. if result.count >= form_limit_per_day.to_i
  198. response_access_deny
  199. return true
  200. end
  201. false
  202. end
  203. def fingerprint_exists?
  204. return true if params[:fingerprint].present? && params[:fingerprint].length > 30
  205. Rails.logger.info 'No fingerprint given!'
  206. response_access_deny
  207. false
  208. end
  209. def enabled?
  210. return true if params[:test] && current_user && current_user.permissions?('admin.channel_formular')
  211. return true if Setting.get('form_ticket_create')
  212. response_access_deny
  213. false
  214. end
  215. end