From c4e2c8cb4c45af21f071d3072d2c9c831bf0bcb8 Mon Sep 17 00:00:00 2001 From: Matt-Yorkley <9029026+Matt-Yorkley@users.noreply.github.com> Date: Mon, 11 Oct 2021 11:21:05 +0100 Subject: [PATCH] Tidy up error handling and update response formats for JSON:API standard Update translation key namespacing --- app/controllers/api/v1/base_controller.rb | 51 +++++++++++++++-------- config/locales/en.yml | 5 ++- 2 files changed, 37 insertions(+), 19 deletions(-) diff --git a/app/controllers/api/v1/base_controller.rb b/app/controllers/api/v1/base_controller.rb index 879b155491..12f7f8748e 100644 --- a/app/controllers/api/v1/base_controller.rb +++ b/app/controllers/api/v1/base_controller.rb @@ -35,13 +35,6 @@ module Api invalid_api_key end - def error_during_processing(exception) - Bugsnag.notify(exception) - - render json: { exception: exception.message }, - status: :unprocessable_entity - end - def current_ability Spree::Ability.new(current_api_user) end @@ -49,27 +42,49 @@ module Api def api_key request.headers["X-Spree-Token"] || params[:token] end - helper_method :api_key - def invalid_resource!(resource) - render json: { error: I18n.t(:invalid_resource, scope: "spree.api"), - errors: resource.errors }, - status: :unprocessable_entity + def error_during_processing(exception) + Bugsnag.notify(exception) + + render status: :unprocessable_entity, + json: json_api_error(exception.message, backtrace: exception.backtrace) + end + + def invalid_resource!(resource = nil) + render status: :unprocessable_entity, + json: json_api_invalid( + I18n.t(:invalid_resource, scope: "api"), + resource&.errors + ) end def invalid_api_key - render json: { error: I18n.t(:invalid_api_key, key: api_key, scope: "spree.api") }, - status: :unauthorized + render status: :unauthorized, + json: json_api_error(I18n.t(:invalid_api_key, key: api_key, scope: "api")) end def unauthorized - render json: { error: I18n.t(:unauthorized, scope: "spree.api") }, - status: :unauthorized + render status: :unauthorized, + json: json_api_error(I18n.t(:unauthorized, scope: "api")) end def not_found - render json: { error: I18n.t(:resource_not_found, scope: "spree.api") }, - status: :not_found + render status: :not_found, + json: json_api_error(I18n.t(:resource_not_found, scope: "api")) + end + + def json_api_error(message, **options) + error_response = { errors: [{ detail: message }] } + if options[:backtrace] && (Rails.env.development? || Rails.env.test?) + error_response.merge!(meta: [options[:backtrace]]) + end + error_response + end + + def json_api_invalid(message, errors) + error_response = { errors: [{ detail: message }] } + error_response.merge!(meta: { validation_errors: errors.to_a }) if errors.any? + error_response end end end diff --git a/config/locales/en.yml b/config/locales/en.yml index 96c26482c5..95fcaecaec 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -165,7 +165,6 @@ en: no_default_card: "^No default card available for this customer" shipping_method: not_available_to_shop: "is not available to %{shop}" - card_details: "Card details" card_type: "Card type" cardholder_name: "Cardholder name" @@ -1410,6 +1409,10 @@ en: # API # api: + invalid_api_key: "Invalid API key (%{key}) specified." + unauthorized: "You are not authorized to perform that action." + invalid_resource: "Invalid resource. Please fix errors and try again." + resource_not_found: "The resource you were looking for could not be found." enterprise_logo: destroy_attachment_does_not_exist: "Logo does not exist" enterprise_promo_image: