halorgium-actionpack 3.0.pre
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +5179 -0
- data/MIT-LICENSE +21 -0
- data/README +409 -0
- data/lib/abstract_controller.rb +16 -0
- data/lib/abstract_controller/base.rb +158 -0
- data/lib/abstract_controller/callbacks.rb +113 -0
- data/lib/abstract_controller/exceptions.rb +12 -0
- data/lib/abstract_controller/helpers.rb +151 -0
- data/lib/abstract_controller/layouts.rb +250 -0
- data/lib/abstract_controller/localized_cache.rb +49 -0
- data/lib/abstract_controller/logger.rb +61 -0
- data/lib/abstract_controller/rendering_controller.rb +188 -0
- data/lib/action_controller.rb +72 -0
- data/lib/action_controller/base.rb +168 -0
- data/lib/action_controller/caching.rb +80 -0
- data/lib/action_controller/caching/actions.rb +163 -0
- data/lib/action_controller/caching/fragments.rb +116 -0
- data/lib/action_controller/caching/pages.rb +154 -0
- data/lib/action_controller/caching/sweeping.rb +97 -0
- data/lib/action_controller/deprecated.rb +4 -0
- data/lib/action_controller/deprecated/integration_test.rb +2 -0
- data/lib/action_controller/deprecated/performance_test.rb +1 -0
- data/lib/action_controller/dispatch/dispatcher.rb +57 -0
- data/lib/action_controller/metal.rb +129 -0
- data/lib/action_controller/metal/benchmarking.rb +73 -0
- data/lib/action_controller/metal/compatibility.rb +145 -0
- data/lib/action_controller/metal/conditional_get.rb +86 -0
- data/lib/action_controller/metal/configuration.rb +28 -0
- data/lib/action_controller/metal/cookies.rb +105 -0
- data/lib/action_controller/metal/exceptions.rb +55 -0
- data/lib/action_controller/metal/filter_parameter_logging.rb +77 -0
- data/lib/action_controller/metal/flash.rb +162 -0
- data/lib/action_controller/metal/head.rb +27 -0
- data/lib/action_controller/metal/helpers.rb +115 -0
- data/lib/action_controller/metal/hide_actions.rb +47 -0
- data/lib/action_controller/metal/http_authentication.rb +312 -0
- data/lib/action_controller/metal/layouts.rb +171 -0
- data/lib/action_controller/metal/mime_responds.rb +317 -0
- data/lib/action_controller/metal/rack_convenience.rb +27 -0
- data/lib/action_controller/metal/redirector.rb +22 -0
- data/lib/action_controller/metal/render_options.rb +103 -0
- data/lib/action_controller/metal/rendering_controller.rb +57 -0
- data/lib/action_controller/metal/request_forgery_protection.rb +108 -0
- data/lib/action_controller/metal/rescuable.rb +13 -0
- data/lib/action_controller/metal/responder.rb +200 -0
- data/lib/action_controller/metal/session.rb +15 -0
- data/lib/action_controller/metal/session_management.rb +45 -0
- data/lib/action_controller/metal/streaming.rb +188 -0
- data/lib/action_controller/metal/testing.rb +39 -0
- data/lib/action_controller/metal/url_for.rb +41 -0
- data/lib/action_controller/metal/verification.rb +130 -0
- data/lib/action_controller/middleware.rb +38 -0
- data/lib/action_controller/notifications.rb +10 -0
- data/lib/action_controller/polymorphic_routes.rb +183 -0
- data/lib/action_controller/record_identifier.rb +91 -0
- data/lib/action_controller/testing/process.rb +111 -0
- data/lib/action_controller/testing/test_case.rb +345 -0
- data/lib/action_controller/translation.rb +13 -0
- data/lib/action_controller/url_rewriter.rb +204 -0
- data/lib/action_controller/vendor/html-scanner.rb +16 -0
- data/lib/action_controller/vendor/html-scanner/html/document.rb +68 -0
- data/lib/action_controller/vendor/html-scanner/html/node.rb +537 -0
- data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +176 -0
- data/lib/action_controller/vendor/html-scanner/html/selector.rb +828 -0
- data/lib/action_controller/vendor/html-scanner/html/tokenizer.rb +105 -0
- data/lib/action_controller/vendor/html-scanner/html/version.rb +11 -0
- data/lib/action_dispatch.rb +70 -0
- data/lib/action_dispatch/http/headers.rb +33 -0
- data/lib/action_dispatch/http/mime_type.rb +231 -0
- data/lib/action_dispatch/http/mime_types.rb +23 -0
- data/lib/action_dispatch/http/request.rb +539 -0
- data/lib/action_dispatch/http/response.rb +290 -0
- data/lib/action_dispatch/http/status_codes.rb +42 -0
- data/lib/action_dispatch/http/utils.rb +20 -0
- data/lib/action_dispatch/middleware/callbacks.rb +50 -0
- data/lib/action_dispatch/middleware/params_parser.rb +79 -0
- data/lib/action_dispatch/middleware/rescue.rb +26 -0
- data/lib/action_dispatch/middleware/session/abstract_store.rb +208 -0
- data/lib/action_dispatch/middleware/session/cookie_store.rb +235 -0
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +47 -0
- data/lib/action_dispatch/middleware/show_exceptions.rb +143 -0
- data/lib/action_dispatch/middleware/stack.rb +116 -0
- data/lib/action_dispatch/middleware/static.rb +44 -0
- data/lib/action_dispatch/middleware/string_coercion.rb +29 -0
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb +24 -0
- data/lib/action_dispatch/middleware/templates/rescues/_trace.erb +26 -0
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb +10 -0
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +29 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.erb +2 -0
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.erb +10 -0
- data/lib/action_dispatch/middleware/templates/rescues/template_error.erb +21 -0
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.erb +2 -0
- data/lib/action_dispatch/routing.rb +381 -0
- data/lib/action_dispatch/routing/deprecated_mapper.rb +878 -0
- data/lib/action_dispatch/routing/mapper.rb +327 -0
- data/lib/action_dispatch/routing/route.rb +49 -0
- data/lib/action_dispatch/routing/route_set.rb +497 -0
- data/lib/action_dispatch/testing/assertions.rb +8 -0
- data/lib/action_dispatch/testing/assertions/dom.rb +35 -0
- data/lib/action_dispatch/testing/assertions/model.rb +19 -0
- data/lib/action_dispatch/testing/assertions/response.rb +145 -0
- data/lib/action_dispatch/testing/assertions/routing.rb +144 -0
- data/lib/action_dispatch/testing/assertions/selector.rb +639 -0
- data/lib/action_dispatch/testing/assertions/tag.rb +123 -0
- data/lib/action_dispatch/testing/integration.rb +504 -0
- data/lib/action_dispatch/testing/performance_test.rb +15 -0
- data/lib/action_dispatch/testing/test_request.rb +83 -0
- data/lib/action_dispatch/testing/test_response.rb +131 -0
- data/lib/action_pack.rb +24 -0
- data/lib/action_pack/version.rb +9 -0
- data/lib/action_view.rb +58 -0
- data/lib/action_view/base.rb +308 -0
- data/lib/action_view/context.rb +44 -0
- data/lib/action_view/erb/util.rb +48 -0
- data/lib/action_view/helpers.rb +62 -0
- data/lib/action_view/helpers/active_model_helper.rb +306 -0
- data/lib/action_view/helpers/ajax_helper.rb +68 -0
- data/lib/action_view/helpers/asset_tag_helper.rb +830 -0
- data/lib/action_view/helpers/atom_feed_helper.rb +198 -0
- data/lib/action_view/helpers/cache_helper.rb +39 -0
- data/lib/action_view/helpers/capture_helper.rb +168 -0
- data/lib/action_view/helpers/date_helper.rb +988 -0
- data/lib/action_view/helpers/debug_helper.rb +38 -0
- data/lib/action_view/helpers/form_helper.rb +1102 -0
- data/lib/action_view/helpers/form_options_helper.rb +600 -0
- data/lib/action_view/helpers/form_tag_helper.rb +495 -0
- data/lib/action_view/helpers/javascript_helper.rb +208 -0
- data/lib/action_view/helpers/number_helper.rb +311 -0
- data/lib/action_view/helpers/prototype_helper.rb +1309 -0
- data/lib/action_view/helpers/raw_output_helper.rb +9 -0
- data/lib/action_view/helpers/record_identification_helper.rb +20 -0
- data/lib/action_view/helpers/record_tag_helper.rb +58 -0
- data/lib/action_view/helpers/sanitize_helper.rb +259 -0
- data/lib/action_view/helpers/scriptaculous_helper.rb +226 -0
- data/lib/action_view/helpers/tag_helper.rb +151 -0
- data/lib/action_view/helpers/text_helper.rb +594 -0
- data/lib/action_view/helpers/translation_helper.rb +39 -0
- data/lib/action_view/helpers/url_helper.rb +639 -0
- data/lib/action_view/locale/en.yml +117 -0
- data/lib/action_view/paths.rb +80 -0
- data/lib/action_view/render/partials.rb +342 -0
- data/lib/action_view/render/rendering.rb +134 -0
- data/lib/action_view/safe_buffer.rb +28 -0
- data/lib/action_view/template/error.rb +101 -0
- data/lib/action_view/template/handler.rb +36 -0
- data/lib/action_view/template/handlers.rb +52 -0
- data/lib/action_view/template/handlers/builder.rb +17 -0
- data/lib/action_view/template/handlers/erb.rb +53 -0
- data/lib/action_view/template/handlers/rjs.rb +18 -0
- data/lib/action_view/template/resolver.rb +165 -0
- data/lib/action_view/template/template.rb +131 -0
- data/lib/action_view/template/text.rb +38 -0
- data/lib/action_view/test_case.rb +163 -0
- metadata +236 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module ActionController
|
|
2
|
+
module RackConvenience
|
|
3
|
+
extend ActiveSupport::Concern
|
|
4
|
+
|
|
5
|
+
included do
|
|
6
|
+
delegate :headers, :status=, :location=, :content_type=,
|
|
7
|
+
:status, :location, :content_type, :to => "@_response"
|
|
8
|
+
attr_internal :request
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def dispatch(action, env)
|
|
12
|
+
@_request = ActionDispatch::Request.new(env)
|
|
13
|
+
@_response = ActionDispatch::Response.new
|
|
14
|
+
@_response.request = request
|
|
15
|
+
super
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def params
|
|
19
|
+
@_params ||= @_request.parameters
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def response_body=(body)
|
|
23
|
+
response.body = body if response
|
|
24
|
+
super
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module ActionController
|
|
2
|
+
class RedirectBackError < AbstractController::Error #:nodoc:
|
|
3
|
+
DEFAULT_MESSAGE = 'No HTTP_REFERER was set in the request to this action, so redirect_to :back could not be called successfully. If this is a test, make sure to specify request.env["HTTP_REFERER"].'
|
|
4
|
+
|
|
5
|
+
def initialize(message = nil)
|
|
6
|
+
super(message || DEFAULT_MESSAGE)
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
module Redirector
|
|
11
|
+
extend ActiveSupport::Concern
|
|
12
|
+
include AbstractController::Logger
|
|
13
|
+
|
|
14
|
+
def redirect_to(url, status) #:doc:
|
|
15
|
+
raise AbstractController::DoubleRenderError if response_body
|
|
16
|
+
logger.info("Redirected to #{url}") if logger && logger.info?
|
|
17
|
+
self.status = status
|
|
18
|
+
self.location = url.gsub(/[\r\n]/, '')
|
|
19
|
+
self.response_body = "<html><body>You are being <a href=\"#{ERB::Util.h(url)}\">redirected</a>.</body></html>"
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
module ActionController
|
|
2
|
+
module RenderOptions
|
|
3
|
+
extend ActiveSupport::Concern
|
|
4
|
+
|
|
5
|
+
included do
|
|
6
|
+
extlib_inheritable_accessor :_renderers
|
|
7
|
+
self._renderers = []
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
module ClassMethods
|
|
11
|
+
def _write_render_options
|
|
12
|
+
renderers = _renderers.map do |r|
|
|
13
|
+
<<-RUBY_EVAL
|
|
14
|
+
if options.key?(:#{r})
|
|
15
|
+
_process_options(options)
|
|
16
|
+
return render_#{r}(options[:#{r}], options)
|
|
17
|
+
end
|
|
18
|
+
RUBY_EVAL
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
|
|
22
|
+
def _handle_render_options(options)
|
|
23
|
+
#{renderers.join}
|
|
24
|
+
end
|
|
25
|
+
RUBY_EVAL
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def _add_render_option(name)
|
|
29
|
+
_renderers << name
|
|
30
|
+
_write_render_options
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def render_to_body(options)
|
|
35
|
+
_handle_render_options(options) || super
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
module RenderOption #:nodoc:
|
|
40
|
+
def self.extended(base)
|
|
41
|
+
base.extend ActiveSupport::Concern
|
|
42
|
+
base.send :include, ::ActionController::RenderOptions
|
|
43
|
+
|
|
44
|
+
def base.register_renderer(name)
|
|
45
|
+
included { _add_render_option(name) }
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
module RenderOptions
|
|
51
|
+
module Json
|
|
52
|
+
extend RenderOption
|
|
53
|
+
register_renderer :json
|
|
54
|
+
|
|
55
|
+
def render_json(json, options)
|
|
56
|
+
json = ActiveSupport::JSON.encode(json) unless json.respond_to?(:to_str)
|
|
57
|
+
json = "#{options[:callback]}(#{json})" unless options[:callback].blank?
|
|
58
|
+
self.content_type ||= Mime::JSON
|
|
59
|
+
self.response_body = json
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
module Js
|
|
64
|
+
extend RenderOption
|
|
65
|
+
register_renderer :js
|
|
66
|
+
|
|
67
|
+
def render_js(js, options)
|
|
68
|
+
self.content_type ||= Mime::JS
|
|
69
|
+
self.response_body = js.respond_to?(:to_js) ? js.to_js : js
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
module Xml
|
|
74
|
+
extend RenderOption
|
|
75
|
+
register_renderer :xml
|
|
76
|
+
|
|
77
|
+
def render_xml(xml, options)
|
|
78
|
+
self.content_type ||= Mime::XML
|
|
79
|
+
self.response_body = xml.respond_to?(:to_xml) ? xml.to_xml : xml
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
module RJS
|
|
84
|
+
extend RenderOption
|
|
85
|
+
register_renderer :update
|
|
86
|
+
|
|
87
|
+
def render_update(proc, options)
|
|
88
|
+
generator = ActionView::Helpers::PrototypeHelper::JavaScriptGenerator.new(view_context, &proc)
|
|
89
|
+
self.content_type = Mime::JS
|
|
90
|
+
self.response_body = generator.to_s
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
module All
|
|
95
|
+
extend ActiveSupport::Concern
|
|
96
|
+
|
|
97
|
+
include ActionController::RenderOptions::Json
|
|
98
|
+
include ActionController::RenderOptions::Js
|
|
99
|
+
include ActionController::RenderOptions::Xml
|
|
100
|
+
include ActionController::RenderOptions::RJS
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
module ActionController
|
|
2
|
+
module RenderingController
|
|
3
|
+
extend ActiveSupport::Concern
|
|
4
|
+
|
|
5
|
+
included do
|
|
6
|
+
include AbstractController::RenderingController
|
|
7
|
+
include AbstractController::LocalizedCache
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def process_action(*)
|
|
11
|
+
self.formats = request.formats.map {|x| x.to_sym}
|
|
12
|
+
super
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def render(options)
|
|
16
|
+
super
|
|
17
|
+
self.content_type ||= options[:_template].mime_type.to_s
|
|
18
|
+
response_body
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def render_to_body(options)
|
|
22
|
+
_process_options(options)
|
|
23
|
+
|
|
24
|
+
if options.key?(:partial)
|
|
25
|
+
options[:partial] = action_name if options[:partial] == true
|
|
26
|
+
options[:_details] = {:formats => formats}
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
super
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
def _prefix
|
|
34
|
+
controller_path
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def _determine_template(options)
|
|
38
|
+
if (options.keys & [:partial, :file, :template, :text, :inline]).empty?
|
|
39
|
+
options[:_template_name] ||= options[:action]
|
|
40
|
+
options[:_prefix] = _prefix
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
super
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def format_for_text
|
|
47
|
+
formats.first
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def _process_options(options)
|
|
51
|
+
status, content_type, location = options.values_at(:status, :content_type, :location)
|
|
52
|
+
self.status = status if status
|
|
53
|
+
self.content_type = content_type if content_type
|
|
54
|
+
self.headers["Location"] = url_for(location) if location
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
module ActionController #:nodoc:
|
|
2
|
+
class InvalidAuthenticityToken < ActionControllerError #:nodoc:
|
|
3
|
+
end
|
|
4
|
+
|
|
5
|
+
module RequestForgeryProtection
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
|
|
8
|
+
include AbstractController::Helpers, Session
|
|
9
|
+
|
|
10
|
+
included do
|
|
11
|
+
# Sets the token parameter name for RequestForgery. Calling +protect_from_forgery+
|
|
12
|
+
# sets it to <tt>:authenticity_token</tt> by default.
|
|
13
|
+
cattr_accessor :request_forgery_protection_token
|
|
14
|
+
|
|
15
|
+
# Controls whether request forgergy protection is turned on or not. Turned off by default only in test mode.
|
|
16
|
+
class_inheritable_accessor :allow_forgery_protection
|
|
17
|
+
self.allow_forgery_protection = true
|
|
18
|
+
|
|
19
|
+
helper_method :form_authenticity_token
|
|
20
|
+
helper_method :protect_against_forgery?
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Protecting controller actions from CSRF attacks by ensuring that all forms are coming from the current
|
|
24
|
+
# web application, not a forged link from another site, is done by embedding a token based on a random
|
|
25
|
+
# string stored in the session (which an attacker wouldn't know) in all forms and Ajax requests generated
|
|
26
|
+
# by Rails and then verifying the authenticity of that token in the controller. Only HTML/JavaScript
|
|
27
|
+
# requests are checked, so this will not protect your XML API (presumably you'll have a different
|
|
28
|
+
# authentication scheme there anyway). Also, GET requests are not protected as these should be
|
|
29
|
+
# idempotent anyway.
|
|
30
|
+
#
|
|
31
|
+
# This is turned on with the <tt>protect_from_forgery</tt> method, which will check the token and raise an
|
|
32
|
+
# ActionController::InvalidAuthenticityToken if it doesn't match what was expected. You can customize the
|
|
33
|
+
# error message in production by editing public/422.html. A call to this method in ApplicationController is
|
|
34
|
+
# generated by default in post-Rails 2.0 applications.
|
|
35
|
+
#
|
|
36
|
+
# The token parameter is named <tt>authenticity_token</tt> by default. If you are generating an HTML form
|
|
37
|
+
# manually (without the use of Rails' <tt>form_for</tt>, <tt>form_tag</tt> or other helpers), you have to
|
|
38
|
+
# include a hidden field named like that and set its value to what is returned by
|
|
39
|
+
# <tt>form_authenticity_token</tt>.
|
|
40
|
+
#
|
|
41
|
+
# Request forgery protection is disabled by default in test environment. If you are upgrading from Rails
|
|
42
|
+
# 1.x, add this to config/environments/test.rb:
|
|
43
|
+
#
|
|
44
|
+
# # Disable request forgery protection in test environment
|
|
45
|
+
# config.action_controller.allow_forgery_protection = false
|
|
46
|
+
#
|
|
47
|
+
# == Learn more about CSRF (Cross-Site Request Forgery) attacks
|
|
48
|
+
#
|
|
49
|
+
# Here are some resources:
|
|
50
|
+
# * http://isc.sans.org/diary.html?storyid=1750
|
|
51
|
+
# * http://en.wikipedia.org/wiki/Cross-site_request_forgery
|
|
52
|
+
#
|
|
53
|
+
# Keep in mind, this is NOT a silver-bullet, plug 'n' play, warm security blanket for your rails application.
|
|
54
|
+
# There are a few guidelines you should follow:
|
|
55
|
+
#
|
|
56
|
+
# * Keep your GET requests safe and idempotent. More reading material:
|
|
57
|
+
# * http://www.xml.com/pub/a/2002/04/24/deviant.html
|
|
58
|
+
# * http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.1.1
|
|
59
|
+
# * Make sure the session cookies that Rails creates are non-persistent. Check in Firefox and look
|
|
60
|
+
# for "Expires: at end of session"
|
|
61
|
+
#
|
|
62
|
+
module ClassMethods
|
|
63
|
+
# Turn on request forgery protection. Bear in mind that only non-GET, HTML/JavaScript requests are checked.
|
|
64
|
+
#
|
|
65
|
+
# Example:
|
|
66
|
+
#
|
|
67
|
+
# class FooController < ApplicationController
|
|
68
|
+
# protect_from_forgery :except => :index
|
|
69
|
+
#
|
|
70
|
+
# # you can disable csrf protection on controller-by-controller basis:
|
|
71
|
+
# skip_before_filter :verify_authenticity_token
|
|
72
|
+
# end
|
|
73
|
+
#
|
|
74
|
+
# Valid Options:
|
|
75
|
+
#
|
|
76
|
+
# * <tt>:only/:except</tt> - Passed to the <tt>before_filter</tt> call. Set which actions are verified.
|
|
77
|
+
def protect_from_forgery(options = {})
|
|
78
|
+
self.request_forgery_protection_token ||= :authenticity_token
|
|
79
|
+
before_filter :verify_authenticity_token, options
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
protected
|
|
84
|
+
# The actual before_filter that is used. Modify this to change how you handle unverified requests.
|
|
85
|
+
def verify_authenticity_token
|
|
86
|
+
verified_request? || raise(ActionController::InvalidAuthenticityToken)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Returns true or false if a request is verified. Checks:
|
|
90
|
+
#
|
|
91
|
+
# * is the format restricted? By default, only HTML requests are checked.
|
|
92
|
+
# * is it a GET request? Gets should be safe and idempotent
|
|
93
|
+
# * Does the form_authenticity_token match the given token value from the params?
|
|
94
|
+
def verified_request?
|
|
95
|
+
!protect_against_forgery? || request.forgery_whitelisted? ||
|
|
96
|
+
form_authenticity_token == params[request_forgery_protection_token]
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Sets the token value for the current session.
|
|
100
|
+
def form_authenticity_token
|
|
101
|
+
session[:_csrf_token] ||= ActiveSupport::SecureRandom.base64(32)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def protect_against_forgery?
|
|
105
|
+
allow_forgery_protection
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module ActionController #:nodoc:
|
|
2
|
+
module Rescue
|
|
3
|
+
extend ActiveSupport::Concern
|
|
4
|
+
include ActiveSupport::Rescuable
|
|
5
|
+
|
|
6
|
+
private
|
|
7
|
+
def process_action(*args)
|
|
8
|
+
super
|
|
9
|
+
rescue Exception => exception
|
|
10
|
+
rescue_with_handler(exception) || raise(exception)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
module ActionController #:nodoc:
|
|
2
|
+
# Responder is responsible to expose a resource for different mime requests,
|
|
3
|
+
# usually depending on the HTTP verb. The responder is triggered when
|
|
4
|
+
# respond_with is called. The simplest case to study is a GET request:
|
|
5
|
+
#
|
|
6
|
+
# class PeopleController < ApplicationController
|
|
7
|
+
# respond_to :html, :xml, :json
|
|
8
|
+
#
|
|
9
|
+
# def index
|
|
10
|
+
# @people = Person.find(:all)
|
|
11
|
+
# respond_with(@people)
|
|
12
|
+
# end
|
|
13
|
+
# end
|
|
14
|
+
#
|
|
15
|
+
# When a request comes, for example with format :xml, three steps happen:
|
|
16
|
+
#
|
|
17
|
+
# 1) respond_with searches for a template at people/index.xml;
|
|
18
|
+
#
|
|
19
|
+
# 2) if the template is not available, it will create a responder, passing
|
|
20
|
+
# the controller and the resource and invoke :to_xml on it;
|
|
21
|
+
#
|
|
22
|
+
# 3) if the responder does not respond_to :to_xml, call to_format on it.
|
|
23
|
+
#
|
|
24
|
+
# === Builtin HTTP verb semantics
|
|
25
|
+
#
|
|
26
|
+
# Rails default responder holds semantics for each HTTP verb. Depending on the
|
|
27
|
+
# content type, verb and the resource status, it will behave differently.
|
|
28
|
+
#
|
|
29
|
+
# Using Rails default responder, a POST request for creating an object could
|
|
30
|
+
# be written as:
|
|
31
|
+
#
|
|
32
|
+
# def create
|
|
33
|
+
# @user = User.new(params[:user])
|
|
34
|
+
# flash[:notice] = 'User was successfully created.' if @user.save
|
|
35
|
+
# respond_with(@user)
|
|
36
|
+
# end
|
|
37
|
+
#
|
|
38
|
+
# Which is exactly the same as:
|
|
39
|
+
#
|
|
40
|
+
# def create
|
|
41
|
+
# @user = User.new(params[:user])
|
|
42
|
+
#
|
|
43
|
+
# respond_to do |format|
|
|
44
|
+
# if @user.save
|
|
45
|
+
# flash[:notice] = 'User was successfully created.'
|
|
46
|
+
# format.html { redirect_to(@user) }
|
|
47
|
+
# format.xml { render :xml => @user, :status => :created, :location => @user }
|
|
48
|
+
# else
|
|
49
|
+
# format.html { render :action => "new" }
|
|
50
|
+
# format.xml { render :xml => @user.errors, :status => :unprocessable_entity }
|
|
51
|
+
# end
|
|
52
|
+
# end
|
|
53
|
+
# end
|
|
54
|
+
#
|
|
55
|
+
# The same happens for PUT and DELETE requests.
|
|
56
|
+
#
|
|
57
|
+
# === Nested resources
|
|
58
|
+
#
|
|
59
|
+
# You can given nested resource as you do in form_for and polymorphic_url.
|
|
60
|
+
# Consider the project has many tasks example. The create action for
|
|
61
|
+
# TasksController would be like:
|
|
62
|
+
#
|
|
63
|
+
# def create
|
|
64
|
+
# @project = Project.find(params[:project_id])
|
|
65
|
+
# @task = @project.comments.build(params[:task])
|
|
66
|
+
# flash[:notice] = 'Task was successfully created.' if @task.save
|
|
67
|
+
# respond_with(@project, @task)
|
|
68
|
+
# end
|
|
69
|
+
#
|
|
70
|
+
# Giving an array of resources, you ensure that the responder will redirect to
|
|
71
|
+
# project_task_url instead of task_url.
|
|
72
|
+
#
|
|
73
|
+
# Namespaced and singleton resources requires a symbol to be given, as in
|
|
74
|
+
# polymorphic urls. If a project has one manager which has many tasks, it
|
|
75
|
+
# should be invoked as:
|
|
76
|
+
#
|
|
77
|
+
# respond_with(@project, :manager, @task)
|
|
78
|
+
#
|
|
79
|
+
# Check polymorphic_url documentation for more examples.
|
|
80
|
+
#
|
|
81
|
+
class Responder
|
|
82
|
+
attr_reader :controller, :request, :format, :resource, :resources, :options
|
|
83
|
+
|
|
84
|
+
def initialize(controller, resources, options={})
|
|
85
|
+
@controller = controller
|
|
86
|
+
@request = controller.request
|
|
87
|
+
@format = controller.formats.first
|
|
88
|
+
@resource = resources.is_a?(Array) ? resources.last : resources
|
|
89
|
+
@resources = resources
|
|
90
|
+
@options = options
|
|
91
|
+
@default_response = options.delete(:default_response)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
delegate :head, :render, :redirect_to, :to => :controller
|
|
95
|
+
delegate :get?, :post?, :put?, :delete?, :to => :request
|
|
96
|
+
|
|
97
|
+
# Undefine :to_json since it's defined on Object
|
|
98
|
+
undef_method(:to_json) if method_defined?(:to_json)
|
|
99
|
+
|
|
100
|
+
# Initializes a new responder an invoke the proper format. If the format is
|
|
101
|
+
# not defined, call to_format.
|
|
102
|
+
#
|
|
103
|
+
def self.call(*args)
|
|
104
|
+
responder = new(*args)
|
|
105
|
+
method = :"to_#{responder.format}"
|
|
106
|
+
responder.respond_to?(method) ? responder.send(method) : responder.to_format
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# HTML format does not render the resource, it always attempt to render a
|
|
110
|
+
# template.
|
|
111
|
+
#
|
|
112
|
+
def to_html
|
|
113
|
+
default_render
|
|
114
|
+
rescue ActionView::MissingTemplate
|
|
115
|
+
if get?
|
|
116
|
+
raise
|
|
117
|
+
elsif has_errors?
|
|
118
|
+
render :action => default_action
|
|
119
|
+
else
|
|
120
|
+
redirect_to resource_location
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# All others formats follow the procedure below. First we try to render a
|
|
125
|
+
# template, if the template is not available, we verify if the resource
|
|
126
|
+
# responds to :to_format and display it.
|
|
127
|
+
#
|
|
128
|
+
def to_format
|
|
129
|
+
default_render
|
|
130
|
+
rescue ActionView::MissingTemplate
|
|
131
|
+
raise unless resourceful?
|
|
132
|
+
|
|
133
|
+
if get?
|
|
134
|
+
display resource
|
|
135
|
+
elsif has_errors?
|
|
136
|
+
display resource.errors, :status => :unprocessable_entity
|
|
137
|
+
elsif post?
|
|
138
|
+
display resource, :status => :created, :location => resource_location
|
|
139
|
+
else
|
|
140
|
+
head :ok
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
protected
|
|
145
|
+
|
|
146
|
+
# Checks whether the resource responds to the current format or not.
|
|
147
|
+
#
|
|
148
|
+
def resourceful?
|
|
149
|
+
resource.respond_to?(:"to_#{format}")
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
# Returns the resource location by retrieving it from the options or
|
|
153
|
+
# returning the resources array.
|
|
154
|
+
#
|
|
155
|
+
def resource_location
|
|
156
|
+
options[:location] || resources
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# If a given response block was given, use it, otherwise call render on
|
|
160
|
+
# controller.
|
|
161
|
+
#
|
|
162
|
+
def default_render
|
|
163
|
+
@default_response.call
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
# display is just a shortcut to render a resource with the current format.
|
|
167
|
+
#
|
|
168
|
+
# display @user, :status => :ok
|
|
169
|
+
#
|
|
170
|
+
# For xml request is equivalent to:
|
|
171
|
+
#
|
|
172
|
+
# render :xml => @user, :status => :ok
|
|
173
|
+
#
|
|
174
|
+
# Options sent by the user are also used:
|
|
175
|
+
#
|
|
176
|
+
# respond_with(@user, :status => :created)
|
|
177
|
+
# display(@user, :status => :ok)
|
|
178
|
+
#
|
|
179
|
+
# Results in:
|
|
180
|
+
#
|
|
181
|
+
# render :xml => @user, :status => :created
|
|
182
|
+
#
|
|
183
|
+
def display(resource, given_options={})
|
|
184
|
+
controller.render given_options.merge!(options).merge!(format => resource)
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
# Check if the resource has errors or not.
|
|
188
|
+
#
|
|
189
|
+
def has_errors?
|
|
190
|
+
resource.respond_to?(:errors) && !resource.errors.empty?
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
# By default, render the :edit action for html requests with failure, unless
|
|
194
|
+
# the verb is post.
|
|
195
|
+
#
|
|
196
|
+
def default_action
|
|
197
|
+
request.post? ? :new : :edit
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
end
|