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