12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485 |
- # Copyright (C) 2012-2023 Zammad Foundation, https://zammad-foundation.org/
- class GraphqlController < ApplicationController
- # Handled in the GraphQL processing, not on controller level.
- skip_before_action :verify_csrf_token
- prepend_before_action lambda {
- begin
- authentication_check_only
- rescue Exceptions::Forbidden
- # Don't throw if the user is not authenticated. Just continue without a current_user.
- end
- }
- def execute
- if params[:_json]
- return render json: multiplex
- end
- render json: single_query
- rescue => e
- raise e if !Rails.env.development?
- handle_error_in_development(e)
- end
- private
- def multiplex
- queries = params[:_json].map do |param|
- {
- query: param[:query],
- operation_name: param[:operationName],
- variables: prepare_variables(param[:variables]),
- context: context
- }
- end
- Gql::ZammadSchema.multiplex(queries)
- end
- def single_query
- query = params[:query]
- variables = prepare_variables(params[:variables])
- operation_name = params[:operation_name]
- Gql::ZammadSchema.execute(query, variables: variables, context: context, operation_name: operation_name)
- end
- def context
- # context must be kept in sync with GraphqlChannel!
- {
- sid: session.id,
- current_user: current_user,
- # :controller is used by login/logout mutations and MUST NOT be used otherwise.
- controller: self,
- }
- end
- # Handle variables in form data, JSON body, or a blank value
- def prepare_variables(variables_param)
- case variables_param
- when String
- if variables_param.present?
- JSON.parse(variables_param) || {}
- else
- {}
- end
- when Hash
- variables_param
- when ActionController::Parameters
- variables_param.to_unsafe_hash # GraphQL-Ruby will validate name and type of incoming variables.
- when nil
- {}
- else
- raise ArgumentError, "Unexpected parameter: #{variables_param}"
- end
- end
- def handle_error_in_development(e)
- logger.error e.message
- logger.error e.backtrace.join("\n")
- render json: { errors: [{ message: e.message, backtrace: e.backtrace }], data: {} }, status: :internal_server_error
- end
- end
|