form_controller.rb 7.0 KB

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