# frozen_string_literal: true module MinatoErrorHandler module ErrorHandler extend ActiveSupport::Concern included do |base| rescue_from StandardError, "JWT::VerificationError", "JWT::DecodeError", "Pundit::NotAuthorizedError", with: :handle base.extend ClassMethods end private def handle(exception) error = parse_error(exception) report_error error render_error error end def parse_error(error) return parse_minato_error(error) if minato_error?(error) build_minato_error(error) end def parse_minato_error(error) error.http_request ||= request error.http_response ||= response error end def minato_error?(error) error.is_a?(MinatoErrorHandler::Errors::MinatoError) end def build_minato_error(error) minato_error = error_class(error).new minato_error.caused_by = error.full_message minato_error.backtrace = error.backtrace minato_error.http_request ||= request minato_error.http_response ||= response minato_error end def error_class(error) case error.class.to_s when "JWT::DecodeError", "JWT::VerificationError" MinatoErrorHandler::Errors::NotAuthenticatedError when "Pundit::NotAuthorizedError" MinatoErrorHandler::Errors::NotAuthorizedError else self.class.default_error_class || MinatoErrorHandler::Errors::InternalError end end def report_error(error) logger = ActiveSupport::TaggedLogging.new(Rails.logger) logger.tagged(error.unique_identifier.to_s).error(error.as_json) end def render_error(error) render json: { error: error.json_response }, status: error.status_code end module ClassMethods def default_error(klass) # rubocop:disable Style/ClassVars class_variable_set(:@@default_error_class, klass.to_s.camelize.constantize) # rubocop:enable Style/ClassVars end def default_error_class return nil unless class_variable_defined? :@@default_error_class class_variable_get(:@@default_error_class) end end end end