Skip to content

Commit 3ed6b30

Browse files
committed
Merge pull request #16 from RadiusNetworks/port-sauron-patches
Improve gem integration
2 parents 7f0bfed + a38f181 commit 3ed6b30

File tree

6 files changed

+95
-18
lines changed

6 files changed

+95
-18
lines changed

lib/kracken.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
require "kracken/credential_authenticator"
1010
require "kracken/authenticator"
1111
require "kracken/registration"
12+
require "kracken/railtie" if defined?(Rails)
1213

1314
module Kracken
1415
mattr_accessor :config

lib/kracken/controllers/json_api_compatible.rb

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ module Kracken
22
module Controllers
33
module JsonApiCompatible
44

5-
65
module MungeAndMirror
76
# Wraps the data root in an Array, if it is not already an Array. This
87
# will not wrap the value if the resource root is not present.
@@ -75,15 +74,6 @@ def verify_required_params(options = {})
7574
end
7675
end
7776

78-
def self.included(base)
79-
base.instance_exec do
80-
extend Macros
81-
82-
before_action :munge_chained_param_ids!
83-
skip_before_action :verify_authenticity_token
84-
end
85-
end
86-
8777
module DataIntegrity
8878
# Scan each item in the data root and enforce it has an id set.
8979
def enforce_resource_ids!
@@ -123,7 +113,29 @@ def resource_type
123113
end
124114
include VirtualAttributes
125115

116+
def self.included(base)
117+
base.instance_exec do
118+
extend Macros
119+
120+
before_action :munge_chained_param_ids!
121+
skip_before_action :verify_authenticity_token
122+
123+
if defined?(::ActiveRecord)
124+
rescue_from ::ActiveRecord::RecordNotFound do |error|
125+
# In order to use named captures we need to use an inline regex
126+
# on the LHS.
127+
#
128+
# Source: http://rubular.com/r/NoQ4SZMav4
129+
/Couldn't find( all)? (?<resource>\w+) with 'id'.?( \()?(?<ids>[,\s\w]+)\)?/ =~ error.message
130+
resource = resource.underscore.pluralize
131+
raise ResourceNotFound.new(resource, ids.strip)
132+
end
133+
end
134+
end
135+
end
136+
126137
# Common Actions Necessary in JSON API controllers
138+
module_function
127139

128140
# Wrap a block in an Active Record transaction
129141
#

lib/kracken/controllers/token_authenticatable.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@ def self.included(base)
1313
end
1414
end
1515

16-
# NOTE: Monkey-patch until this is merged into the gem
16+
# Customize the `authenticate_or_request_with_http_token` process:
17+
# http://api.rubyonrails.org/classes/ActionController/HttpAuthentication/Token/ControllerMethods.html#method-i-request_http_token_authentication
1718
def request_http_token_authentication(realm = 'Application')
19+
# Modified from https://github.com/rails/rails/blob/60d0aec7/actionpack/lib/action_controller/metal/http_authentication.rb#L490-L499
1820
headers["WWW-Authenticate"] = %(Token realm="#{realm.gsub(/"/, "")}")
1921
raise TokenUnauthorized, "Invalid Credentials"
2022
end

lib/kracken/error.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ def initialize(resource, missing_ids)
1717
@missing_ids = Array(missing_ids)
1818
@resource = resource
1919
super(
20-
"Couldn't find #{resource} with id(s): #{missing_ids.join(', ')}"
20+
"Couldn't find #{@resource} with id(s): #{@missing_ids.join(', ')}"
2121
)
2222
end
2323
end

lib/kracken/json_api/public_exceptions.rb

Lines changed: 57 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,67 @@
11
module Kracken
22
module JsonApi
3+
# Error logging methods used by `ActionDispatch::DebugExceptions`
4+
# https://github.com/rails/rails/blob/v4.2.6/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb
5+
module ErrorLogging
6+
def log_error(env, wrapper)
7+
logger = logger(env)
8+
return unless logger
9+
10+
exception = wrapper.exception
11+
12+
trace = wrapper.application_trace
13+
trace = wrapper.framework_trace if trace.empty?
14+
15+
ActiveSupport::Deprecation.silence do
16+
message = "\n#{exception.class} (#{exception.message}):\n"
17+
message << exception.annoted_source_code.to_s if exception.respond_to?(:annoted_source_code)
18+
message << " " << trace.join("\n ")
19+
logger.fatal("#{message}\n\n")
20+
end
21+
end
22+
23+
def logger(env)
24+
env['action_dispatch.logger'] || stderr_logger
25+
end
26+
27+
def stderr_logger
28+
@stderr_logger ||= ActiveSupport::Logger.new($stderr)
29+
end
30+
end
31+
332
class PublicExceptions
4-
attr_reader :app
33+
include ErrorLogging
34+
535
def initialize(app)
636
@app = app
737
end
838

939
def call(env)
10-
app.call(env)
40+
if JsonApi.has_path?(JsonApi::Request.new(env))
41+
capture_error(env)
42+
else
43+
@app.call(env)
44+
end
45+
end
46+
47+
# Use similar logic to how `ActionDispatch::DebugExceptions` captures
48+
# routing errors.
49+
# https://github.com/rails/rails/blob/v4.2.6/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb
50+
def capture_error(env)
51+
_, headers, body = response = @app.call(env)
52+
53+
if headers['X-Cascade'] == 'pass'
54+
body.close if body.respond_to?(:close)
55+
raise ActionController::RoutingError,
56+
"No route matches [#{env['REQUEST_METHOD']}] " \
57+
"#{env['PATH_INFO'].inspect}"
58+
end
59+
60+
response
1161
rescue Exception => exception
12-
raise exception unless JsonApi.has_path?(JsonApi::Request.new(env))
13-
render_json_error(ExceptionWrapper.new(env, exception))
62+
wrapper = ExceptionWrapper.new(env, exception)
63+
log_error(env, wrapper)
64+
render_json_error(wrapper)
1465
end
1566

1667
if Rails.env.production?
@@ -27,8 +78,8 @@ def additional_details(error)
2778

2879
def show_error_details?(wrapper)
2980
wrapper.is_details_exception? ||
30-
( Rails.application.config.consider_all_requests_local &&
31-
wrapper.status_code == 500)
81+
Rails.application.config.consider_all_requests_local ||
82+
(Rails.env.test? && wrapper.status_code == 500)
3283
end
3384

3485
def error_as_json(wrapper)

lib/kracken/railtie.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
require "kracken/json_api"
2+
3+
module Kracken
4+
# Railtie to hook into Rails.
5+
class Railtie < ::Rails::Railtie
6+
initializer "kracken.json_api.public_exceptions" do |app|
7+
app.middleware.insert_after ActionDispatch::DebugExceptions,
8+
::Kracken::JsonApi::PublicExceptions
9+
end
10+
end
11+
end

0 commit comments

Comments
 (0)