2018-11-19 21:18:17 +01:00
|
|
|
class API::V2::GraphqlController < API::V2::BaseController
|
|
|
|
def execute
|
2023-04-04 14:45:22 +02:00
|
|
|
result = API::V2::Schema.execute(query:, variables:, context:, operation_name:)
|
|
|
|
@query_info = result.context.query_info
|
2023-02-15 19:07:54 +01:00
|
|
|
|
2018-11-19 21:18:17 +01:00
|
|
|
render json: result
|
2022-10-29 12:35:52 +02:00
|
|
|
rescue GraphQL::ParseError, JSON::ParserError => exception
|
2023-04-18 09:48:38 +02:00
|
|
|
handle_parse_error(exception, :graphql_parse_failed)
|
|
|
|
rescue ArgumentError => exception
|
|
|
|
handle_parse_error(exception, :bad_request)
|
2020-12-18 12:03:55 +01:00
|
|
|
rescue => exception
|
2021-02-10 09:54:37 +01:00
|
|
|
if Rails.env.production?
|
2020-12-18 12:03:55 +01:00
|
|
|
handle_error_in_production(exception)
|
2021-02-10 09:54:37 +01:00
|
|
|
else
|
|
|
|
handle_error_in_development(exception)
|
2018-11-19 21:18:17 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
2021-10-28 22:05:11 +02:00
|
|
|
def append_info_to_payload(payload)
|
2023-03-15 21:46:34 +01:00
|
|
|
# if on the graphql playground, authenticate via devise
|
|
|
|
# if authenticate by a v2 or v3 token
|
|
|
|
# @current_user is set by `api_v2_base_controller.authenticate_administrateur_from_token`
|
|
|
|
# else it is set on `context.authorized_demarche`
|
|
|
|
@current_user ||= Current.user
|
|
|
|
|
2021-10-28 22:05:11 +02:00
|
|
|
super
|
|
|
|
|
2023-04-04 14:45:22 +02:00
|
|
|
payload.merge!(@query_info.presence || {})
|
2021-10-28 22:05:11 +02:00
|
|
|
end
|
|
|
|
|
2020-09-30 11:59:49 +02:00
|
|
|
def process_action(*args)
|
|
|
|
super
|
|
|
|
rescue ActionDispatch::Http::Parameters::ParseError => exception
|
2020-12-18 12:03:55 +01:00
|
|
|
render json: {
|
|
|
|
errors: [
|
2023-04-18 09:48:38 +02:00
|
|
|
{
|
|
|
|
message: exception.cause.message,
|
|
|
|
extensions: {
|
|
|
|
code: :bad_request
|
|
|
|
}
|
|
|
|
}
|
2020-12-18 12:03:55 +01:00
|
|
|
],
|
|
|
|
data: nil
|
|
|
|
}, status: 400
|
2020-09-30 11:59:49 +02:00
|
|
|
end
|
|
|
|
|
2023-04-04 14:45:22 +02:00
|
|
|
def query
|
2022-10-31 18:21:24 +01:00
|
|
|
if params[:queryId].present?
|
2023-04-04 14:45:22 +02:00
|
|
|
API::V2::StoredQuery.get(params[:queryId])
|
2022-10-31 18:21:24 +01:00
|
|
|
else
|
|
|
|
params[:query]
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def variables
|
|
|
|
ensure_hash(params[:variables])
|
|
|
|
end
|
|
|
|
|
2023-04-04 14:45:22 +02:00
|
|
|
def operation_name
|
|
|
|
params[:operationName]
|
|
|
|
end
|
|
|
|
|
2018-11-19 21:18:17 +01:00
|
|
|
# Handle form data, JSON body, or a blank value
|
|
|
|
def ensure_hash(ambiguous_param)
|
|
|
|
case ambiguous_param
|
|
|
|
when String
|
|
|
|
if ambiguous_param.present?
|
|
|
|
ensure_hash(JSON.parse(ambiguous_param))
|
|
|
|
else
|
|
|
|
{}
|
|
|
|
end
|
2022-11-24 15:24:05 +01:00
|
|
|
when Hash
|
2018-11-19 21:18:17 +01:00
|
|
|
ambiguous_param
|
2022-11-24 15:24:05 +01:00
|
|
|
when ActionController::Parameters
|
|
|
|
ambiguous_param.to_unsafe_h
|
2018-11-19 21:18:17 +01:00
|
|
|
when nil
|
|
|
|
{}
|
|
|
|
else
|
|
|
|
raise ArgumentError, "Unexpected parameter: #{ambiguous_param}"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2023-04-18 09:48:38 +02:00
|
|
|
def handle_parse_error(exception, code)
|
2021-11-19 15:15:10 +01:00
|
|
|
render json: {
|
|
|
|
errors: [
|
2023-04-18 09:48:38 +02:00
|
|
|
{
|
|
|
|
message: exception.message,
|
|
|
|
extensions: { code: }
|
|
|
|
}
|
2021-11-19 15:15:10 +01:00
|
|
|
],
|
|
|
|
data: nil
|
|
|
|
}, status: 400
|
|
|
|
end
|
|
|
|
|
2020-12-18 12:03:55 +01:00
|
|
|
def handle_error_in_development(exception)
|
|
|
|
logger.error exception.message
|
|
|
|
logger.error exception.backtrace.join("\n")
|
2018-11-19 21:18:17 +01:00
|
|
|
|
2020-12-18 12:03:55 +01:00
|
|
|
render json: {
|
|
|
|
errors: [
|
2023-04-18 09:48:38 +02:00
|
|
|
{
|
|
|
|
message: exception.message,
|
|
|
|
extensions: {
|
|
|
|
code: :internal_server_error,
|
|
|
|
backtrace: exception.backtrace
|
|
|
|
}
|
|
|
|
}
|
2020-12-18 12:03:55 +01:00
|
|
|
],
|
|
|
|
data: nil
|
|
|
|
}, status: 500
|
|
|
|
end
|
|
|
|
|
|
|
|
def handle_error_in_production(exception)
|
2023-04-18 09:48:38 +02:00
|
|
|
exception_id = SecureRandom.uuid
|
|
|
|
Sentry.with_scope do |scope|
|
|
|
|
scope.set_tags(exception_id:)
|
|
|
|
Sentry.capture_exception(exception)
|
|
|
|
end
|
2020-12-18 12:03:55 +01:00
|
|
|
|
|
|
|
render json: {
|
|
|
|
errors: [
|
|
|
|
{
|
|
|
|
message: "Internal Server Error",
|
|
|
|
extensions: {
|
2023-04-18 09:48:38 +02:00
|
|
|
code: :internal_server_error,
|
|
|
|
exception_id:
|
2020-12-18 12:03:55 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
],
|
|
|
|
data: nil
|
|
|
|
}, status: 500
|
2018-11-19 21:18:17 +01:00
|
|
|
end
|
|
|
|
end
|