class Fanforce::Error < StandardError require 'fanforce/utils' include Fanforce::Utils attr_reader :public_errors, :env def for(*args) self.new(*args) end def initialize(*errors) if errors[0].is_a?(String) and errors[1].is_a?(Hash) and is_blank?(errors[1][:message]) tmp = errors.shift() and errors[0][:message] = tmp end @public_errors = format_errors(errors) @env = Fanforce.env super("#{@public_errors[0].to_json}") end def format_errors(raw_errors) raw_errors.is_a?(Array) ? raw_errors.inject([]) {|errors, e| errors << format_error(e) } : [format_error(raw_errors)] end def format_error(raw_error) return {message: is_blank?(raw_error) ? default_message : raw_error.to_s} if !raw_error.is_a?(Hash) raw_error = symbolize_keys(raw_error) error = { message: is_blank?(raw_error[:message]) ? default_message : raw_error[:message].to_s } error[:resource] = raw_error[:resource].to_s if is_present?(raw_error[:resource]) error[:code] = (is_blank?(raw_error[:code]) or !valid_error_codes.include? raw_error[:code].to_sym) ? default_error_code : raw_error[:code].to_s error[:field] = raw_error[:field].to_s if is_present?(raw_error[:field]) error[:fields] = raw_error[:fields].map {|f| f.to_s } if is_present?(raw_error[:fields]) error end def curl_command return nil if is_blank?(@env[:request_method]) or is_blank?(@env[:request_url]) Fanforce::Utils.curl_command(@env[:request_method], @env[:request_url], @env[:request_params]) end def code; 500 end def default_message; end def valid_error_codes; [] end def default_error_code; end end class Fanforce::Error::BadRequest < Fanforce::Error # Request is missing something or invalid def code; 400 end def default_message; 'Bad Request' end def valid_error_codes; [:blank_field, :missing_field, :invalid_association, :invalid_field] end def default_error_code; :unknown end end class Fanforce::Error::Unauthorized < Fanforce::Error # Could not successfully authenticate def code; 401 end def default_message; 'Unauthorized Request' end def valid_error_codes; [:unauthorized, :unknown_login] end def default_error_code; :unauthorized end end class Fanforce::Error::Forbidden < Fanforce::Error # Current API key does not allow access def code; 403 end def default_message; 'API Key Forbids Access' end def valid_error_codes; [:weak_api_key] end def default_error_code; :weak_api_key end end class Fanforce::Error::NotFound < Fanforce::Error # Method or record could not be found def code; 404 end def default_message; 'Not Found' end def valid_error_codes; [:record_not_found, :method_not_found] end def default_error_code; :unknown end def initialize(*args) if args[0].is_a?(Hash) super(*args) else super( resource: args[0].to_s.demodulize.singularize, message: args[1] ) end end def self.for(resource, message=nil) self.new(resource, message) end end class Fanforce::Error::RequestFailed < Fanforce::Error # Request has correct fields but failed for another reason def code; 422 end def default_message; 'Request Failed' end def valid_error_codes; [:invalid_data, :record_already_exists, :maxed_capacity] end def default_error_code; :unknown end end class Fanforce::Error::InternalError < Fanforce::Error def code; 500 end def default_message; 'Request Failed for Internal Reason' end def valid_error_codes; [:internal_error, :invalid_fanforce_auth, :user_tampering, :third_party_error] end def default_error_code; :unknown end end class Fanforce::Error::WebhookFailed < Fanforce::Error # Parameters were valid but request failed for another reason attr_reader :request_url, :request_params, :response_code, :response_body, :request_curl_command def code; 500 end def default_message; 'Webhook Failed' end def valid_error_codes; [:third_party_error] end def default_error_code; :unknown end def initialize(hash) @request_url = hash[:request_url] @request_params = hash[:request_params] @response_code = hash[:response_code] @response_body = hash[:response_body] @request_curl_command = "curl -X POST -d \"#{@request_params.to_param}\" #{@request_url}" super("Callback returned an HTTP response code of #{@response_code} when only 200 and 201 are allowed.") end end class Fanforce::Error::AddonFailed < Fanforce::Error # A 3rd-party addon crapped out attr_reader :plugin_dev_error def default_message; 'Third-Party Plugin Error' end def valid_error_codes; [:third_party_error] end def default_error_code; :third_party_error end def initialize(plugin_type, plugin_id, e, msg, &block) plugin_dev_error = {} plugin_dev_error[:problem] = msg if e.is_a?(Fanforce::Errors::WebhookFailed) plugin_dev_error[:request_url] = e.request_url plugin_dev_error[:request_params] = e.request_params plugin_dev_error[:response_code] = e.response_code plugin_dev_error[:response_body] = e.response_body.to_s plugin_dev_error[:curl_command] = "curl -X POST -d \"#{e.request_params.to_param}\" #{e.request_url}" end @plugin_dev_errors = e.respond_to?(:plugin_dev_errors) ? e.plugin_dev_errors : [] @plugin_dev_errors << plugin_dev_error self.class.handler_blocks.each {|block| block.call(plugin_type, plugin_id, plugin_dev_error, e.backtrace) } super(msg) end def self.handler(&block) handler_blocks << block end def self.handler_blocks @handler_blocks ||= [] end end module Fanforce::Errors def self.included(base) base.extend(self) end BadRequest = Fanforce::Error::BadRequest unless defined?(BadRequest) Unauthorized = Fanforce::Error::Unauthorized unless defined?(Unauthorized) Forbidden = Fanforce::Error::Forbidden unless defined?(Forbidden) NotFound = Fanforce::Error::NotFound unless defined?(NotFound) RequestFailed = Fanforce::Error::RequestFailed unless defined?(RequestFailed) InternalError = Fanforce::Error::InternalError unless defined?(InternalError) WebhookFailed = Fanforce::Error::WebhookFailed unless defined?(WebhookFailed) AddonFailed = Fanforce::Error::AddonFailed unless defined?(AddonFailed) def self.format_admin_details(e, errors=[], additional_options={}) admin_details = {error_class: e.class.name, public_response: errors} admin_details[:curl_command] = e.curl_command if e.respond_to?(:curl_command) admin_details[:raw_message] = e.message admin_details.merge(additional_options) end end