graphql_controller.rb 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. # Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
  2. class GraphqlController < ApplicationController
  3. # If accessing from outside this domain, nullify the session
  4. # This allows for outside API access while preventing CSRF attacks,
  5. # but you'll have to authenticate your user separately
  6. # protect_from_forgery with: :null_session
  7. # Handled in the GraphQL processing, not on controller level.
  8. skip_before_action :verify_csrf_token
  9. prepend_before_action :authentication_check_only
  10. def execute
  11. if params[:_json]
  12. return render json: multiplex
  13. end
  14. render json: single_query
  15. rescue => e
  16. raise e if !Rails.env.development?
  17. handle_error_in_development(e)
  18. end
  19. private
  20. def multiplex
  21. queries = params[:_json].map do |param|
  22. {
  23. query: param[:query],
  24. operation_name: param[:operationName],
  25. variables: prepare_variables(param[:variables]),
  26. context: context
  27. }
  28. end
  29. Gql::ZammadSchema.multiplex(queries)
  30. end
  31. def single_query
  32. query = params[:query]
  33. variables = prepare_variables(params[:variables])
  34. operation_name = params[:operation_name]
  35. Gql::ZammadSchema.execute(query, variables: variables, context: context, operation_name: operation_name)
  36. end
  37. def context
  38. # context must be kept in sync with GraphqlChannel!
  39. {
  40. sid: session.id,
  41. current_user: current_user,
  42. # :controller is used by login/logout mutations and MUST NOT be used otherwise.
  43. controller: self,
  44. }
  45. end
  46. # Handle variables in form data, JSON body, or a blank value
  47. def prepare_variables(variables_param)
  48. case variables_param
  49. when String
  50. if variables_param.present?
  51. JSON.parse(variables_param) || {}
  52. else
  53. {}
  54. end
  55. when Hash
  56. variables_param
  57. when ActionController::Parameters
  58. variables_param.to_unsafe_hash # GraphQL-Ruby will validate name and type of incoming variables.
  59. when nil
  60. {}
  61. else
  62. raise ArgumentError, "Unexpected parameter: #{variables_param}"
  63. end
  64. end
  65. def handle_error_in_development(e)
  66. logger.error e.message
  67. logger.error e.backtrace.join("\n")
  68. render json: { errors: [{ message: e.message, backtrace: e.backtrace }], data: {} }, status: :internal_server_error
  69. end
  70. end