graphql_controller.rb 2.2 KB

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