From c51a47e0ad7995c5fda3ad867da366c011779fd2 Mon Sep 17 00:00:00 2001 From: Tung Le Date: Mon, 17 Jun 2024 23:49:26 +0700 Subject: [PATCH] Handle exceptions --- app/controllers/application_controller.rb | 90 +++++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 81fe791..626ab1a 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -47,4 +47,94 @@ def clear_mdc_context org.slf4j.MDC.remove(key) end end + + # Note! Order matters, StandardError needs to be first + rescue_from(StandardError) do |error| + flash[:error] = "Error: #{as_string(error)}" + try_to_redirect_to_account_path = !params[:controller].ends_with?('accounts') + perform_redirect_after_error try_to_redirect_to_account_path + end + + rescue_from(ActionController::ParameterMissing) do |parameter_missing_exception| + log_rescue_error parameter_missing_exception + flash[:error] = "Required parameter missing: #{parameter_missing_exception.param}" + perform_redirect_after_error + end + + rescue_from(KillBillClient::API::ResponseError) do |killbill_exception| + flash[:error] = "Error while communicating with the Kill Bill server: #{as_string(killbill_exception)}" + try_to_redirect_to_account_path = !killbill_exception.is_a?(KillBillClient::API::Unauthorized) && !(killbill_exception.is_a?(KillBillClient::API::NotFound) && params[:controller].ends_with?('accounts')) + perform_redirect_after_error try_to_redirect_to_account_path + end + + private + + def nested_hash_value(obj, key) + if obj.respond_to?(:key?) && obj.key?(key) + obj[key] + elsif obj.is_a?(Hash) || obj.is_a?(Array) + r = nil + obj.find { |*a| r = nested_hash_value(a.last, key) } + r + else + nil + end + end + + def as_string(exception) + if exception.is_a?(KillBillClient::API::ResponseError) + as_string_from_response(exception.response.body) + elsif exception.is_a?(ActionController::ParameterMissing) + # e.message contains corrections, which we don't want + "missing parameter #{exception.param}" + elsif exception.respond_to?(:cause) && !exception.cause.nil? + as_string(exception.cause) + else + log_rescue_error(exception) + exception.message + end + end + + def as_string_from_response(response) + error_message = response + begin + # BillingExceptionJson? + error_message = JSON.parse response + rescue StandardError => _e + # Ignore + end + + if error_message.respond_to?(:[]) && error_message['message'].present? + # Likely BillingExceptionJson + error_message = error_message['message'] + error_message += " (code=#{error_message['code']})" unless error_message['code'].blank? + end + # Limit the error size to avoid ActionDispatch::Cookies::CookieOverflow + error_message[0..1000] + end + + def current_tenant_user + user = current_user + kb_tenant_id = session[:kb_tenant_id] + user_tenant = Kaui::Tenant.find_by_kb_tenant_id(kb_tenant_id) if kb_tenant_id + result = { + :username => user.kb_username, + :password => user.password, + :session_id => user.kb_session_id, + } + if user_tenant + result[:api_key] = user_tenant.api_key + result[:api_secret] = user_tenant.api_secret + end + result + end + + def perform_redirect_after_error(try_to_redirect_to_account_path = true) + account_id = nested_hash_value(params.permit!.to_h, :account_id) + if try_to_redirect_to_account_path && account_id.present? + redirect_to kaui_engine.account_path(account_id) + else + redirect_to kaui_engine.home_path + end + end end