actionpack 3.2.19 → 4.2.11.3

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of actionpack might be problematic. Click here for more details.

Files changed (244) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +412 -503
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +11 -294
  5. data/lib/abstract_controller/asset_paths.rb +2 -2
  6. data/lib/abstract_controller/base.rb +52 -18
  7. data/lib/abstract_controller/callbacks.rb +87 -89
  8. data/lib/abstract_controller/collector.rb +17 -3
  9. data/lib/abstract_controller/helpers.rb +41 -14
  10. data/lib/abstract_controller/logger.rb +1 -2
  11. data/lib/abstract_controller/railties/routes_helpers.rb +3 -3
  12. data/lib/abstract_controller/rendering.rb +65 -118
  13. data/lib/abstract_controller/translation.rb +16 -1
  14. data/lib/abstract_controller/url_for.rb +7 -7
  15. data/lib/abstract_controller.rb +2 -10
  16. data/lib/action_controller/base.rb +61 -28
  17. data/lib/action_controller/caching/fragments.rb +30 -54
  18. data/lib/action_controller/caching.rb +38 -35
  19. data/lib/action_controller/log_subscriber.rb +35 -18
  20. data/lib/action_controller/metal/conditional_get.rb +103 -34
  21. data/lib/action_controller/metal/data_streaming.rb +20 -26
  22. data/lib/action_controller/metal/etag_with_template_digest.rb +50 -0
  23. data/lib/action_controller/metal/exceptions.rb +19 -6
  24. data/lib/action_controller/metal/flash.rb +41 -9
  25. data/lib/action_controller/metal/force_ssl.rb +70 -12
  26. data/lib/action_controller/metal/head.rb +30 -7
  27. data/lib/action_controller/metal/helpers.rb +11 -11
  28. data/lib/action_controller/metal/hide_actions.rb +0 -1
  29. data/lib/action_controller/metal/http_authentication.rb +140 -94
  30. data/lib/action_controller/metal/implicit_render.rb +1 -1
  31. data/lib/action_controller/metal/instrumentation.rb +11 -7
  32. data/lib/action_controller/metal/live.rb +328 -0
  33. data/lib/action_controller/metal/mime_responds.rb +161 -152
  34. data/lib/action_controller/metal/params_wrapper.rb +126 -81
  35. data/lib/action_controller/metal/rack_delegation.rb +10 -4
  36. data/lib/action_controller/metal/redirecting.rb +44 -41
  37. data/lib/action_controller/metal/renderers.rb +48 -19
  38. data/lib/action_controller/metal/rendering.rb +46 -11
  39. data/lib/action_controller/metal/request_forgery_protection.rb +250 -29
  40. data/lib/action_controller/metal/streaming.rb +30 -38
  41. data/lib/action_controller/metal/strong_parameters.rb +669 -0
  42. data/lib/action_controller/metal/testing.rb +12 -18
  43. data/lib/action_controller/metal/url_for.rb +31 -29
  44. data/lib/action_controller/metal.rb +31 -40
  45. data/lib/action_controller/model_naming.rb +12 -0
  46. data/lib/action_controller/railtie.rb +38 -18
  47. data/lib/action_controller/railties/helpers.rb +22 -0
  48. data/lib/action_controller/test_case.rb +359 -173
  49. data/lib/action_controller.rb +9 -16
  50. data/lib/action_dispatch/http/cache.rb +64 -11
  51. data/lib/action_dispatch/http/filter_parameters.rb +20 -10
  52. data/lib/action_dispatch/http/filter_redirect.rb +38 -0
  53. data/lib/action_dispatch/http/headers.rb +85 -17
  54. data/lib/action_dispatch/http/mime_negotiation.rb +55 -5
  55. data/lib/action_dispatch/http/mime_type.rb +167 -114
  56. data/lib/action_dispatch/http/mime_types.rb +2 -1
  57. data/lib/action_dispatch/http/parameter_filter.rb +44 -46
  58. data/lib/action_dispatch/http/parameters.rb +30 -46
  59. data/lib/action_dispatch/http/rack_cache.rb +2 -3
  60. data/lib/action_dispatch/http/request.rb +108 -45
  61. data/lib/action_dispatch/http/response.rb +247 -48
  62. data/lib/action_dispatch/http/upload.rb +60 -29
  63. data/lib/action_dispatch/http/url.rb +135 -45
  64. data/lib/action_dispatch/journey/backwards.rb +5 -0
  65. data/lib/action_dispatch/journey/formatter.rb +166 -0
  66. data/lib/action_dispatch/journey/gtg/builder.rb +162 -0
  67. data/lib/action_dispatch/journey/gtg/simulator.rb +47 -0
  68. data/lib/action_dispatch/journey/gtg/transition_table.rb +157 -0
  69. data/lib/action_dispatch/journey/nfa/builder.rb +76 -0
  70. data/lib/action_dispatch/journey/nfa/dot.rb +36 -0
  71. data/lib/action_dispatch/journey/nfa/simulator.rb +47 -0
  72. data/lib/action_dispatch/journey/nfa/transition_table.rb +163 -0
  73. data/lib/action_dispatch/journey/nodes/node.rb +128 -0
  74. data/lib/action_dispatch/journey/parser.rb +198 -0
  75. data/lib/action_dispatch/journey/parser.y +49 -0
  76. data/lib/action_dispatch/journey/parser_extras.rb +23 -0
  77. data/lib/action_dispatch/journey/path/pattern.rb +193 -0
  78. data/lib/action_dispatch/journey/route.rb +125 -0
  79. data/lib/action_dispatch/journey/router/strexp.rb +27 -0
  80. data/lib/action_dispatch/journey/router/utils.rb +93 -0
  81. data/lib/action_dispatch/journey/router.rb +144 -0
  82. data/lib/action_dispatch/journey/routes.rb +80 -0
  83. data/lib/action_dispatch/journey/scanner.rb +61 -0
  84. data/lib/action_dispatch/journey/visitors.rb +221 -0
  85. data/lib/action_dispatch/journey/visualizer/fsm.css +30 -0
  86. data/lib/action_dispatch/journey/visualizer/fsm.js +134 -0
  87. data/lib/action_dispatch/journey/visualizer/index.html.erb +52 -0
  88. data/lib/action_dispatch/journey.rb +5 -0
  89. data/lib/action_dispatch/middleware/callbacks.rb +16 -11
  90. data/lib/action_dispatch/middleware/cookies.rb +346 -125
  91. data/lib/action_dispatch/middleware/debug_exceptions.rb +52 -24
  92. data/lib/action_dispatch/middleware/exception_wrapper.rb +75 -9
  93. data/lib/action_dispatch/middleware/flash.rb +85 -72
  94. data/lib/action_dispatch/middleware/params_parser.rb +16 -31
  95. data/lib/action_dispatch/middleware/public_exceptions.rb +39 -14
  96. data/lib/action_dispatch/middleware/reloader.rb +16 -7
  97. data/lib/action_dispatch/middleware/remote_ip.rb +132 -40
  98. data/lib/action_dispatch/middleware/request_id.rb +3 -7
  99. data/lib/action_dispatch/middleware/session/abstract_store.rb +22 -20
  100. data/lib/action_dispatch/middleware/session/cache_store.rb +3 -3
  101. data/lib/action_dispatch/middleware/session/cookie_store.rb +84 -29
  102. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +8 -3
  103. data/lib/action_dispatch/middleware/show_exceptions.rb +15 -44
  104. data/lib/action_dispatch/middleware/ssl.rb +72 -0
  105. data/lib/action_dispatch/middleware/stack.rb +6 -1
  106. data/lib/action_dispatch/middleware/static.rb +80 -23
  107. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +34 -0
  108. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +23 -0
  109. data/lib/action_dispatch/middleware/templates/rescues/_source.erb +27 -0
  110. data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +52 -0
  111. data/lib/action_dispatch/middleware/templates/rescues/_trace.text.erb +9 -0
  112. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +16 -0
  113. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +9 -0
  114. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +133 -5
  115. data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +11 -0
  116. data/lib/action_dispatch/middleware/templates/rescues/missing_template.text.erb +3 -0
  117. data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +32 -0
  118. data/lib/action_dispatch/middleware/templates/rescues/routing_error.text.erb +11 -0
  119. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +20 -0
  120. data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +7 -0
  121. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +6 -0
  122. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +3 -0
  123. data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +16 -0
  124. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +200 -0
  125. data/lib/action_dispatch/railtie.rb +19 -6
  126. data/lib/action_dispatch/request/session.rb +193 -0
  127. data/lib/action_dispatch/request/utils.rb +35 -0
  128. data/lib/action_dispatch/routing/endpoint.rb +10 -0
  129. data/lib/action_dispatch/routing/inspector.rb +234 -0
  130. data/lib/action_dispatch/routing/mapper.rb +897 -436
  131. data/lib/action_dispatch/routing/polymorphic_routes.rb +213 -92
  132. data/lib/action_dispatch/routing/redirection.rb +97 -37
  133. data/lib/action_dispatch/routing/route_set.rb +432 -239
  134. data/lib/action_dispatch/routing/routes_proxy.rb +7 -4
  135. data/lib/action_dispatch/routing/url_for.rb +63 -34
  136. data/lib/action_dispatch/routing.rb +57 -89
  137. data/lib/action_dispatch/testing/assertions/dom.rb +2 -36
  138. data/lib/action_dispatch/testing/assertions/response.rb +24 -38
  139. data/lib/action_dispatch/testing/assertions/routing.rb +55 -54
  140. data/lib/action_dispatch/testing/assertions/selector.rb +2 -434
  141. data/lib/action_dispatch/testing/assertions/tag.rb +2 -137
  142. data/lib/action_dispatch/testing/assertions.rb +11 -7
  143. data/lib/action_dispatch/testing/integration.rb +88 -72
  144. data/lib/action_dispatch/testing/test_process.rb +9 -6
  145. data/lib/action_dispatch/testing/test_request.rb +13 -9
  146. data/lib/action_dispatch/testing/test_response.rb +1 -5
  147. data/lib/action_dispatch.rb +24 -21
  148. data/lib/action_pack/gem_version.rb +15 -0
  149. data/lib/action_pack/version.rb +5 -7
  150. data/lib/action_pack.rb +1 -1
  151. metadata +181 -292
  152. data/lib/abstract_controller/layouts.rb +0 -423
  153. data/lib/abstract_controller/view_paths.rb +0 -96
  154. data/lib/action_controller/caching/actions.rb +0 -185
  155. data/lib/action_controller/caching/pages.rb +0 -187
  156. data/lib/action_controller/caching/sweeping.rb +0 -97
  157. data/lib/action_controller/deprecated/integration_test.rb +0 -2
  158. data/lib/action_controller/deprecated/performance_test.rb +0 -1
  159. data/lib/action_controller/deprecated.rb +0 -3
  160. data/lib/action_controller/metal/compatibility.rb +0 -65
  161. data/lib/action_controller/metal/responder.rb +0 -286
  162. data/lib/action_controller/metal/session_management.rb +0 -14
  163. data/lib/action_controller/railties/paths.rb +0 -25
  164. data/lib/action_controller/record_identifier.rb +0 -85
  165. data/lib/action_controller/vendor/html-scanner/html/document.rb +0 -68
  166. data/lib/action_controller/vendor/html-scanner/html/node.rb +0 -532
  167. data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +0 -177
  168. data/lib/action_controller/vendor/html-scanner/html/selector.rb +0 -830
  169. data/lib/action_controller/vendor/html-scanner/html/tokenizer.rb +0 -107
  170. data/lib/action_controller/vendor/html-scanner/html/version.rb +0 -11
  171. data/lib/action_controller/vendor/html-scanner.rb +0 -20
  172. data/lib/action_dispatch/middleware/best_standards_support.rb +0 -30
  173. data/lib/action_dispatch/middleware/body_proxy.rb +0 -30
  174. data/lib/action_dispatch/middleware/head.rb +0 -18
  175. data/lib/action_dispatch/middleware/rescue.rb +0 -26
  176. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb +0 -31
  177. data/lib/action_dispatch/middleware/templates/rescues/_trace.erb +0 -26
  178. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb +0 -10
  179. data/lib/action_dispatch/middleware/templates/rescues/missing_template.erb +0 -2
  180. data/lib/action_dispatch/middleware/templates/rescues/routing_error.erb +0 -15
  181. data/lib/action_dispatch/middleware/templates/rescues/template_error.erb +0 -17
  182. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.erb +0 -2
  183. data/lib/action_dispatch/testing/performance_test.rb +0 -10
  184. data/lib/action_view/asset_paths.rb +0 -142
  185. data/lib/action_view/base.rb +0 -220
  186. data/lib/action_view/buffers.rb +0 -43
  187. data/lib/action_view/context.rb +0 -36
  188. data/lib/action_view/flows.rb +0 -79
  189. data/lib/action_view/helpers/active_model_helper.rb +0 -50
  190. data/lib/action_view/helpers/asset_paths.rb +0 -7
  191. data/lib/action_view/helpers/asset_tag_helper.rb +0 -457
  192. data/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb +0 -146
  193. data/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb +0 -93
  194. data/lib/action_view/helpers/asset_tag_helpers/javascript_tag_helpers.rb +0 -193
  195. data/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb +0 -148
  196. data/lib/action_view/helpers/atom_feed_helper.rb +0 -200
  197. data/lib/action_view/helpers/cache_helper.rb +0 -64
  198. data/lib/action_view/helpers/capture_helper.rb +0 -203
  199. data/lib/action_view/helpers/controller_helper.rb +0 -25
  200. data/lib/action_view/helpers/csrf_helper.rb +0 -32
  201. data/lib/action_view/helpers/date_helper.rb +0 -1062
  202. data/lib/action_view/helpers/debug_helper.rb +0 -40
  203. data/lib/action_view/helpers/form_helper.rb +0 -1486
  204. data/lib/action_view/helpers/form_options_helper.rb +0 -658
  205. data/lib/action_view/helpers/form_tag_helper.rb +0 -685
  206. data/lib/action_view/helpers/javascript_helper.rb +0 -110
  207. data/lib/action_view/helpers/number_helper.rb +0 -622
  208. data/lib/action_view/helpers/output_safety_helper.rb +0 -38
  209. data/lib/action_view/helpers/record_tag_helper.rb +0 -111
  210. data/lib/action_view/helpers/rendering_helper.rb +0 -90
  211. data/lib/action_view/helpers/sanitize_helper.rb +0 -259
  212. data/lib/action_view/helpers/tag_helper.rb +0 -160
  213. data/lib/action_view/helpers/text_helper.rb +0 -426
  214. data/lib/action_view/helpers/translation_helper.rb +0 -91
  215. data/lib/action_view/helpers/url_helper.rb +0 -693
  216. data/lib/action_view/helpers.rb +0 -60
  217. data/lib/action_view/locale/en.yml +0 -160
  218. data/lib/action_view/log_subscriber.rb +0 -28
  219. data/lib/action_view/lookup_context.rb +0 -254
  220. data/lib/action_view/path_set.rb +0 -89
  221. data/lib/action_view/railtie.rb +0 -55
  222. data/lib/action_view/renderer/abstract_renderer.rb +0 -41
  223. data/lib/action_view/renderer/partial_renderer.rb +0 -415
  224. data/lib/action_view/renderer/renderer.rb +0 -54
  225. data/lib/action_view/renderer/streaming_template_renderer.rb +0 -106
  226. data/lib/action_view/renderer/template_renderer.rb +0 -94
  227. data/lib/action_view/template/error.rb +0 -128
  228. data/lib/action_view/template/handlers/builder.rb +0 -26
  229. data/lib/action_view/template/handlers/erb.rb +0 -125
  230. data/lib/action_view/template/handlers.rb +0 -50
  231. data/lib/action_view/template/resolver.rb +0 -272
  232. data/lib/action_view/template/text.rb +0 -30
  233. data/lib/action_view/template.rb +0 -337
  234. data/lib/action_view/test_case.rb +0 -245
  235. data/lib/action_view/testing/resolvers.rb +0 -50
  236. data/lib/action_view.rb +0 -84
  237. data/lib/sprockets/assets.rake +0 -99
  238. data/lib/sprockets/bootstrap.rb +0 -37
  239. data/lib/sprockets/compressors.rb +0 -83
  240. data/lib/sprockets/helpers/isolated_helper.rb +0 -13
  241. data/lib/sprockets/helpers/rails_helper.rb +0 -182
  242. data/lib/sprockets/helpers.rb +0 -6
  243. data/lib/sprockets/railtie.rb +0 -62
  244. data/lib/sprockets/static_compiler.rb +0 -56
@@ -0,0 +1,669 @@
1
+ require 'active_support/core_ext/hash/indifferent_access'
2
+ require 'active_support/core_ext/array/wrap'
3
+ require 'active_support/core_ext/string/filters'
4
+ require 'active_support/deprecation'
5
+ require 'active_support/rescuable'
6
+ require 'action_dispatch/http/upload'
7
+ require 'stringio'
8
+ require 'set'
9
+
10
+ module ActionController
11
+ # Raised when a required parameter is missing.
12
+ #
13
+ # params = ActionController::Parameters.new(a: {})
14
+ # params.fetch(:b)
15
+ # # => ActionController::ParameterMissing: param not found: b
16
+ # params.require(:a)
17
+ # # => ActionController::ParameterMissing: param not found: a
18
+ class ParameterMissing < KeyError
19
+ attr_reader :param # :nodoc:
20
+
21
+ def initialize(param) # :nodoc:
22
+ @param = param
23
+ super("param is missing or the value is empty: #{param}")
24
+ end
25
+ end
26
+
27
+ # Raised when a supplied parameter is not expected and
28
+ # ActionController::Parameters.action_on_unpermitted_parameters
29
+ # is set to <tt>:raise</tt>.
30
+ #
31
+ # params = ActionController::Parameters.new(a: "123", b: "456")
32
+ # params.permit(:c)
33
+ # # => ActionController::UnpermittedParameters: found unpermitted parameters: a, b
34
+ class UnpermittedParameters < IndexError
35
+ attr_reader :params # :nodoc:
36
+
37
+ def initialize(params) # :nodoc:
38
+ @params = params
39
+ super("found unpermitted parameter#{'s' if params.size > 1 }: #{params.join(", ")}")
40
+ end
41
+ end
42
+
43
+ # == Action Controller \Parameters
44
+ #
45
+ # Allows to choose which attributes should be whitelisted for mass updating
46
+ # and thus prevent accidentally exposing that which shouldn't be exposed.
47
+ # Provides two methods for this purpose: #require and #permit. The former is
48
+ # used to mark parameters as required. The latter is used to set the parameter
49
+ # as permitted and limit which attributes should be allowed for mass updating.
50
+ #
51
+ # params = ActionController::Parameters.new({
52
+ # person: {
53
+ # name: 'Francesco',
54
+ # age: 22,
55
+ # role: 'admin'
56
+ # }
57
+ # })
58
+ #
59
+ # permitted = params.require(:person).permit(:name, :age)
60
+ # permitted # => {"name"=>"Francesco", "age"=>22}
61
+ # permitted.class # => ActionController::Parameters
62
+ # permitted.permitted? # => true
63
+ #
64
+ # Person.first.update!(permitted)
65
+ # # => #<Person id: 1, name: "Francesco", age: 22, role: "user">
66
+ #
67
+ # It provides two options that controls the top-level behavior of new instances:
68
+ #
69
+ # * +permit_all_parameters+ - If it's +true+, all the parameters will be
70
+ # permitted by default. The default is +false+.
71
+ # * +action_on_unpermitted_parameters+ - Allow to control the behavior when parameters
72
+ # that are not explicitly permitted are found. The values can be <tt>:log</tt> to
73
+ # write a message on the logger or <tt>:raise</tt> to raise
74
+ # ActionController::UnpermittedParameters exception. The default value is <tt>:log</tt>
75
+ # in test and development environments, +false+ otherwise.
76
+ #
77
+ # Examples:
78
+ #
79
+ # params = ActionController::Parameters.new
80
+ # params.permitted? # => false
81
+ #
82
+ # ActionController::Parameters.permit_all_parameters = true
83
+ #
84
+ # params = ActionController::Parameters.new
85
+ # params.permitted? # => true
86
+ #
87
+ # params = ActionController::Parameters.new(a: "123", b: "456")
88
+ # params.permit(:c)
89
+ # # => {}
90
+ #
91
+ # ActionController::Parameters.action_on_unpermitted_parameters = :raise
92
+ #
93
+ # params = ActionController::Parameters.new(a: "123", b: "456")
94
+ # params.permit(:c)
95
+ # # => ActionController::UnpermittedParameters: found unpermitted keys: a, b
96
+ #
97
+ # Please note that these options *are not thread-safe*. In a multi-threaded
98
+ # environment they should only be set once at boot-time and never mutated at
99
+ # runtime.
100
+ #
101
+ # <tt>ActionController::Parameters</tt> inherits from
102
+ # <tt>ActiveSupport::HashWithIndifferentAccess</tt>, this means
103
+ # that you can fetch values using either <tt>:key</tt> or <tt>"key"</tt>.
104
+ #
105
+ # params = ActionController::Parameters.new(key: 'value')
106
+ # params[:key] # => "value"
107
+ # params["key"] # => "value"
108
+ class Parameters < ActiveSupport::HashWithIndifferentAccess
109
+ cattr_accessor :permit_all_parameters, instance_accessor: false
110
+ cattr_accessor :action_on_unpermitted_parameters, instance_accessor: false
111
+
112
+ # By default, never raise an UnpermittedParameters exception if these
113
+ # params are present. The default includes both 'controller' and 'action'
114
+ # because they are added by Rails and should be of no concern. One way
115
+ # to change these is to specify `always_permitted_parameters` in your
116
+ # config. For instance:
117
+ #
118
+ # config.always_permitted_parameters = %w( controller action format )
119
+ cattr_accessor :always_permitted_parameters
120
+ self.always_permitted_parameters = %w( controller action )
121
+
122
+ def self.const_missing(const_name)
123
+ super unless const_name == :NEVER_UNPERMITTED_PARAMS
124
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
125
+ `ActionController::Parameters::NEVER_UNPERMITTED_PARAMS` has been deprecated.
126
+ Use `ActionController::Parameters.always_permitted_parameters` instead.
127
+ MSG
128
+
129
+ always_permitted_parameters
130
+ end
131
+
132
+ # Returns a new instance of <tt>ActionController::Parameters</tt>.
133
+ # Also, sets the +permitted+ attribute to the default value of
134
+ # <tt>ActionController::Parameters.permit_all_parameters</tt>.
135
+ #
136
+ # class Person < ActiveRecord::Base
137
+ # end
138
+ #
139
+ # params = ActionController::Parameters.new(name: 'Francesco')
140
+ # params.permitted? # => false
141
+ # Person.new(params) # => ActiveModel::ForbiddenAttributesError
142
+ #
143
+ # ActionController::Parameters.permit_all_parameters = true
144
+ #
145
+ # params = ActionController::Parameters.new(name: 'Francesco')
146
+ # params.permitted? # => true
147
+ # Person.new(params) # => #<Person id: nil, name: "Francesco">
148
+ def initialize(attributes = nil)
149
+ super(attributes)
150
+ @permitted = self.class.permit_all_parameters
151
+ end
152
+
153
+ # Returns a safe +Hash+ representation of this parameter with all
154
+ # unpermitted keys removed.
155
+ #
156
+ # params = ActionController::Parameters.new({
157
+ # name: 'Senjougahara Hitagi',
158
+ # oddity: 'Heavy stone crab'
159
+ # })
160
+ # params.to_h # => {}
161
+ #
162
+ # safe_params = params.permit(:name)
163
+ # safe_params.to_h # => {"name"=>"Senjougahara Hitagi"}
164
+ def to_h
165
+ if permitted?
166
+ to_hash
167
+ else
168
+ slice(*self.class.always_permitted_parameters).permit!.to_h
169
+ end
170
+ end
171
+
172
+ # Returns an unsafe, unfiltered +Hash+ representation of this parameter.
173
+ def to_unsafe_h
174
+ to_hash
175
+ end
176
+ alias_method :to_unsafe_hash, :to_unsafe_h
177
+
178
+ # Convert all hashes in values into parameters, then yield each pair like
179
+ # the same way as <tt>Hash#each_pair</tt>
180
+ def each_pair(&block)
181
+ super do |key, value|
182
+ convert_hashes_to_parameters(key, value)
183
+ end
184
+
185
+ super
186
+ end
187
+
188
+ alias_method :each, :each_pair
189
+
190
+ # Attribute that keeps track of converted arrays, if any, to avoid double
191
+ # looping in the common use case permit + mass-assignment. Defined in a
192
+ # method to instantiate it only if needed.
193
+ #
194
+ # Testing membership still loops, but it's going to be faster than our own
195
+ # loop that converts values. Also, we are not going to build a new array
196
+ # object per fetch.
197
+ def converted_arrays
198
+ @converted_arrays ||= Set.new
199
+ end
200
+
201
+ # Returns +true+ if the parameter is permitted, +false+ otherwise.
202
+ #
203
+ # params = ActionController::Parameters.new
204
+ # params.permitted? # => false
205
+ # params.permit!
206
+ # params.permitted? # => true
207
+ def permitted?
208
+ @permitted
209
+ end
210
+
211
+ # Sets the +permitted+ attribute to +true+. This can be used to pass
212
+ # mass assignment. Returns +self+.
213
+ #
214
+ # class Person < ActiveRecord::Base
215
+ # end
216
+ #
217
+ # params = ActionController::Parameters.new(name: 'Francesco')
218
+ # params.permitted? # => false
219
+ # Person.new(params) # => ActiveModel::ForbiddenAttributesError
220
+ # params.permit!
221
+ # params.permitted? # => true
222
+ # Person.new(params) # => #<Person id: nil, name: "Francesco">
223
+ def permit!
224
+ each_pair do |key, value|
225
+ Array.wrap(value).each do |v|
226
+ v.permit! if v.respond_to? :permit!
227
+ end
228
+ end
229
+
230
+ @permitted = true
231
+ self
232
+ end
233
+
234
+ # Ensures that a parameter is present. If it's present, returns
235
+ # the parameter at the given +key+, otherwise raises an
236
+ # <tt>ActionController::ParameterMissing</tt> error.
237
+ #
238
+ # ActionController::Parameters.new(person: { name: 'Francesco' }).require(:person)
239
+ # # => {"name"=>"Francesco"}
240
+ #
241
+ # ActionController::Parameters.new(person: nil).require(:person)
242
+ # # => ActionController::ParameterMissing: param not found: person
243
+ #
244
+ # ActionController::Parameters.new(person: {}).require(:person)
245
+ # # => ActionController::ParameterMissing: param not found: person
246
+ def require(key)
247
+ value = self[key]
248
+ if value.present? || value == false
249
+ value
250
+ else
251
+ raise ParameterMissing.new(key)
252
+ end
253
+ end
254
+
255
+ # Alias of #require.
256
+ alias :required :require
257
+
258
+ # Returns a new <tt>ActionController::Parameters</tt> instance that
259
+ # includes only the given +filters+ and sets the +permitted+ attribute
260
+ # for the object to +true+. This is useful for limiting which attributes
261
+ # should be allowed for mass updating.
262
+ #
263
+ # params = ActionController::Parameters.new(user: { name: 'Francesco', age: 22, role: 'admin' })
264
+ # permitted = params.require(:user).permit(:name, :age)
265
+ # permitted.permitted? # => true
266
+ # permitted.has_key?(:name) # => true
267
+ # permitted.has_key?(:age) # => true
268
+ # permitted.has_key?(:role) # => false
269
+ #
270
+ # Only permitted scalars pass the filter. For example, given
271
+ #
272
+ # params.permit(:name)
273
+ #
274
+ # +:name+ passes it is a key of +params+ whose associated value is of type
275
+ # +String+, +Symbol+, +NilClass+, +Numeric+, +TrueClass+, +FalseClass+,
276
+ # +Date+, +Time+, +DateTime+, +StringIO+, +IO+,
277
+ # +ActionDispatch::Http::UploadedFile+ or +Rack::Test::UploadedFile+.
278
+ # Otherwise, the key +:name+ is filtered out.
279
+ #
280
+ # You may declare that the parameter should be an array of permitted scalars
281
+ # by mapping it to an empty array:
282
+ #
283
+ # params = ActionController::Parameters.new(tags: ['rails', 'parameters'])
284
+ # params.permit(tags: [])
285
+ #
286
+ # You can also use +permit+ on nested parameters, like:
287
+ #
288
+ # params = ActionController::Parameters.new({
289
+ # person: {
290
+ # name: 'Francesco',
291
+ # age: 22,
292
+ # pets: [{
293
+ # name: 'Purplish',
294
+ # category: 'dogs'
295
+ # }]
296
+ # }
297
+ # })
298
+ #
299
+ # permitted = params.permit(person: [ :name, { pets: :name } ])
300
+ # permitted.permitted? # => true
301
+ # permitted[:person][:name] # => "Francesco"
302
+ # permitted[:person][:age] # => nil
303
+ # permitted[:person][:pets][0][:name] # => "Purplish"
304
+ # permitted[:person][:pets][0][:category] # => nil
305
+ #
306
+ # Note that if you use +permit+ in a key that points to a hash,
307
+ # it won't allow all the hash. You also need to specify which
308
+ # attributes inside the hash should be whitelisted.
309
+ #
310
+ # params = ActionController::Parameters.new({
311
+ # person: {
312
+ # contact: {
313
+ # email: 'none@test.com',
314
+ # phone: '555-1234'
315
+ # }
316
+ # }
317
+ # })
318
+ #
319
+ # params.require(:person).permit(:contact)
320
+ # # => {}
321
+ #
322
+ # params.require(:person).permit(contact: :phone)
323
+ # # => {"contact"=>{"phone"=>"555-1234"}}
324
+ #
325
+ # params.require(:person).permit(contact: [ :email, :phone ])
326
+ # # => {"contact"=>{"email"=>"none@test.com", "phone"=>"555-1234"}}
327
+ def permit(*filters)
328
+ params = self.class.new
329
+
330
+ filters.flatten.each do |filter|
331
+ case filter
332
+ when Symbol, String
333
+ permitted_scalar_filter(params, filter)
334
+ when Hash then
335
+ hash_filter(params, filter)
336
+ end
337
+ end
338
+
339
+ unpermitted_parameters!(params) if self.class.action_on_unpermitted_parameters
340
+
341
+ params.permit!
342
+ end
343
+
344
+ # Returns a parameter for the given +key+. If not found,
345
+ # returns +nil+.
346
+ #
347
+ # params = ActionController::Parameters.new(person: { name: 'Francesco' })
348
+ # params[:person] # => {"name"=>"Francesco"}
349
+ # params[:none] # => nil
350
+ def [](key)
351
+ convert_hashes_to_parameters(key, super)
352
+ end
353
+
354
+ # Returns a parameter for the given +key+. If the +key+
355
+ # can't be found, there are several options: With no other arguments,
356
+ # it will raise an <tt>ActionController::ParameterMissing</tt> error;
357
+ # if more arguments are given, then that will be returned; if a block
358
+ # is given, then that will be run and its result returned.
359
+ #
360
+ # params = ActionController::Parameters.new(person: { name: 'Francesco' })
361
+ # params.fetch(:person) # => {"name"=>"Francesco"}
362
+ # params.fetch(:none) # => ActionController::ParameterMissing: param not found: none
363
+ # params.fetch(:none, 'Francesco') # => "Francesco"
364
+ # params.fetch(:none) { 'Francesco' } # => "Francesco"
365
+ def fetch(key, *args)
366
+ convert_hashes_to_parameters(key, super, false)
367
+ rescue KeyError
368
+ raise ActionController::ParameterMissing.new(key)
369
+ end
370
+
371
+ # Returns a new <tt>ActionController::Parameters</tt> instance that
372
+ # includes only the given +keys+. If the given +keys+
373
+ # don't exist, returns an empty hash.
374
+ #
375
+ # params = ActionController::Parameters.new(a: 1, b: 2, c: 3)
376
+ # params.slice(:a, :b) # => {"a"=>1, "b"=>2}
377
+ # params.slice(:d) # => {}
378
+ def slice(*keys)
379
+ new_instance_with_inherited_permitted_status(super)
380
+ end
381
+
382
+ # Removes and returns the key/value pairs matching the given keys.
383
+ #
384
+ # params = ActionController::Parameters.new(a: 1, b: 2, c: 3)
385
+ # params.extract!(:a, :b) # => {"a"=>1, "b"=>2}
386
+ # params # => {"c"=>3}
387
+ def extract!(*keys)
388
+ new_instance_with_inherited_permitted_status(super)
389
+ end
390
+
391
+ # Returns a new <tt>ActionController::Parameters</tt> with the results of
392
+ # running +block+ once for every value. The keys are unchanged.
393
+ #
394
+ # params = ActionController::Parameters.new(a: 1, b: 2, c: 3)
395
+ # params.transform_values { |x| x * 2 }
396
+ # # => {"a"=>2, "b"=>4, "c"=>6}
397
+ def transform_values
398
+ if block_given?
399
+ new_instance_with_inherited_permitted_status(super)
400
+ else
401
+ super
402
+ end
403
+ end
404
+
405
+ # This method is here only to make sure that the returned object has the
406
+ # correct +permitted+ status. It should not matter since the parent of
407
+ # this object is +HashWithIndifferentAccess+
408
+ def transform_keys # :nodoc:
409
+ if block_given?
410
+ new_instance_with_inherited_permitted_status(super)
411
+ else
412
+ super
413
+ end
414
+ end
415
+
416
+ # Deletes and returns a key-value pair from +Parameters+ whose key is equal
417
+ # to key. If the key is not found, returns the default value. If the
418
+ # optional code block is given and the key is not found, pass in the key
419
+ # and return the result of block.
420
+ def delete(key, &block)
421
+ convert_hashes_to_parameters(key, super, false)
422
+ end
423
+
424
+ # Equivalent to Hash#keep_if, but returns nil if no changes were made.
425
+ def select!(&block)
426
+ convert_value_to_parameters(super)
427
+ end
428
+
429
+ # Returns an exact copy of the <tt>ActionController::Parameters</tt>
430
+ # instance. +permitted+ state is kept on the duped object.
431
+ #
432
+ # params = ActionController::Parameters.new(a: 1)
433
+ # params.permit!
434
+ # params.permitted? # => true
435
+ # copy_params = params.dup # => {"a"=>1}
436
+ # copy_params.permitted? # => true
437
+ def dup
438
+ super.tap do |duplicate|
439
+ duplicate.permitted = @permitted
440
+ end
441
+ end
442
+
443
+ protected
444
+ def permitted=(new_permitted)
445
+ @permitted = new_permitted
446
+ end
447
+
448
+ private
449
+ def new_instance_with_inherited_permitted_status(hash)
450
+ self.class.new(hash).tap do |new_instance|
451
+ new_instance.permitted = @permitted
452
+ end
453
+ end
454
+
455
+ def convert_hashes_to_parameters(key, value, assign_if_converted=true)
456
+ converted = convert_value_to_parameters(value)
457
+ self[key] = converted if assign_if_converted && !converted.equal?(value)
458
+ converted
459
+ end
460
+
461
+ def convert_value_to_parameters(value)
462
+ if value.is_a?(Array) && !converted_arrays.member?(value)
463
+ converted = value.map { |_| convert_value_to_parameters(_) }
464
+ converted_arrays << converted
465
+ converted
466
+ elsif value.is_a?(Parameters) || !value.is_a?(Hash)
467
+ value
468
+ else
469
+ self.class.new(value)
470
+ end
471
+ end
472
+
473
+ def each_element(object)
474
+ if object.is_a?(Array)
475
+ object.map { |el| yield el }.compact
476
+ elsif fields_for_style?(object)
477
+ hash = object.class.new
478
+ object.each { |k,v| hash[k] = yield v }
479
+ hash
480
+ else
481
+ yield object
482
+ end
483
+ end
484
+
485
+ def fields_for_style?(object)
486
+ object.is_a?(Hash) && object.all? { |k, v| k =~ /\A-?\d+\z/ && v.is_a?(Hash) }
487
+ end
488
+
489
+ def unpermitted_parameters!(params)
490
+ unpermitted_keys = unpermitted_keys(params)
491
+ if unpermitted_keys.any?
492
+ case self.class.action_on_unpermitted_parameters
493
+ when :log
494
+ name = "unpermitted_parameters.action_controller"
495
+ ActiveSupport::Notifications.instrument(name, keys: unpermitted_keys)
496
+ when :raise
497
+ raise ActionController::UnpermittedParameters.new(unpermitted_keys)
498
+ end
499
+ end
500
+ end
501
+
502
+ def unpermitted_keys(params)
503
+ self.keys - params.keys - self.always_permitted_parameters
504
+ end
505
+
506
+ #
507
+ # --- Filtering ----------------------------------------------------------
508
+ #
509
+
510
+ # This is a white list of permitted scalar types that includes the ones
511
+ # supported in XML and JSON requests.
512
+ #
513
+ # This list is in particular used to filter ordinary requests, String goes
514
+ # as first element to quickly short-circuit the common case.
515
+ #
516
+ # If you modify this collection please update the API of +permit+ above.
517
+ PERMITTED_SCALAR_TYPES = [
518
+ String,
519
+ Symbol,
520
+ NilClass,
521
+ Numeric,
522
+ TrueClass,
523
+ FalseClass,
524
+ Date,
525
+ Time,
526
+ # DateTimes are Dates, we document the type but avoid the redundant check.
527
+ StringIO,
528
+ IO,
529
+ ActionDispatch::Http::UploadedFile,
530
+ Rack::Test::UploadedFile,
531
+ ]
532
+
533
+ def permitted_scalar?(value)
534
+ PERMITTED_SCALAR_TYPES.any? {|type| value.is_a?(type)}
535
+ end
536
+
537
+ def permitted_scalar_filter(params, key)
538
+ if has_key?(key) && permitted_scalar?(self[key])
539
+ params[key] = self[key]
540
+ end
541
+
542
+ keys.grep(/\A#{Regexp.escape(key)}\(\d+[if]?\)\z/) do |k|
543
+ if permitted_scalar?(self[k])
544
+ params[k] = self[k]
545
+ end
546
+ end
547
+ end
548
+
549
+ def array_of_permitted_scalars?(value)
550
+ if value.is_a?(Array)
551
+ value.all? {|element| permitted_scalar?(element)}
552
+ end
553
+ end
554
+
555
+ def array_of_permitted_scalars_filter(params, key)
556
+ if has_key?(key) && array_of_permitted_scalars?(self[key])
557
+ params[key] = self[key]
558
+ end
559
+ end
560
+
561
+ EMPTY_ARRAY = []
562
+ def hash_filter(params, filter)
563
+ filter = filter.with_indifferent_access
564
+
565
+ # Slicing filters out non-declared keys.
566
+ slice(*filter.keys).each do |key, value|
567
+ next unless value
568
+
569
+ if filter[key] == EMPTY_ARRAY
570
+ # Declaration { comment_ids: [] }.
571
+ array_of_permitted_scalars_filter(params, key)
572
+ else
573
+ # Declaration { user: :name } or { user: [:name, :age, { address: ... }] }.
574
+ params[key] = each_element(value) do |element|
575
+ if element.is_a?(Hash)
576
+ element = self.class.new(element) unless element.respond_to?(:permit)
577
+ element.permit(*Array.wrap(filter[key]))
578
+ end
579
+ end
580
+ end
581
+ end
582
+ end
583
+ end
584
+
585
+ # == Strong \Parameters
586
+ #
587
+ # It provides an interface for protecting attributes from end-user
588
+ # assignment. This makes Action Controller parameters forbidden
589
+ # to be used in Active Model mass assignment until they have been
590
+ # whitelisted.
591
+ #
592
+ # In addition, parameters can be marked as required and flow through a
593
+ # predefined raise/rescue flow to end up as a 400 Bad Request with no
594
+ # effort.
595
+ #
596
+ # class PeopleController < ActionController::Base
597
+ # # Using "Person.create(params[:person])" would raise an
598
+ # # ActiveModel::ForbiddenAttributes exception because it'd
599
+ # # be using mass assignment without an explicit permit step.
600
+ # # This is the recommended form:
601
+ # def create
602
+ # Person.create(person_params)
603
+ # end
604
+ #
605
+ # # This will pass with flying colors as long as there's a person key in the
606
+ # # parameters, otherwise it'll raise an ActionController::MissingParameter
607
+ # # exception, which will get caught by ActionController::Base and turned
608
+ # # into a 400 Bad Request reply.
609
+ # def update
610
+ # redirect_to current_account.people.find(params[:id]).tap { |person|
611
+ # person.update!(person_params)
612
+ # }
613
+ # end
614
+ #
615
+ # private
616
+ # # Using a private method to encapsulate the permissible parameters is
617
+ # # just a good pattern since you'll be able to reuse the same permit
618
+ # # list between create and update. Also, you can specialize this method
619
+ # # with per-user checking of permissible attributes.
620
+ # def person_params
621
+ # params.require(:person).permit(:name, :age)
622
+ # end
623
+ # end
624
+ #
625
+ # In order to use <tt>accepts_nested_attributes_for</tt> with Strong \Parameters, you
626
+ # will need to specify which nested attributes should be whitelisted.
627
+ #
628
+ # class Person
629
+ # has_many :pets
630
+ # accepts_nested_attributes_for :pets
631
+ # end
632
+ #
633
+ # class PeopleController < ActionController::Base
634
+ # def create
635
+ # Person.create(person_params)
636
+ # end
637
+ #
638
+ # ...
639
+ #
640
+ # private
641
+ #
642
+ # def person_params
643
+ # # It's mandatory to specify the nested attributes that should be whitelisted.
644
+ # # If you use `permit` with just the key that points to the nested attributes hash,
645
+ # # it will return an empty hash.
646
+ # params.require(:person).permit(:name, :age, pets_attributes: [ :name, :category ])
647
+ # end
648
+ # end
649
+ #
650
+ # See ActionController::Parameters.require and ActionController::Parameters.permit
651
+ # for more information.
652
+ module StrongParameters
653
+ extend ActiveSupport::Concern
654
+ include ActiveSupport::Rescuable
655
+
656
+ # Returns a new ActionController::Parameters object that
657
+ # has been instantiated with the <tt>request.parameters</tt>.
658
+ def params
659
+ @_params ||= Parameters.new(request.parameters)
660
+ end
661
+
662
+ # Assigns the given +value+ to the +params+ hash. If +value+
663
+ # is a Hash, this will create an ActionController::Parameters
664
+ # object that has been instantiated with the given +value+ hash.
665
+ def params=(value)
666
+ @_params = value.is_a?(Hash) ? Parameters.new(value) : value
667
+ end
668
+ end
669
+ end
@@ -4,30 +4,24 @@ module ActionController
4
4
 
5
5
  include RackDelegation
6
6
 
7
- def recycle!
8
- @_url_options = nil
9
- end
10
-
11
-
12
- # TODO: Clean this up
13
- def process_with_new_base_test(request, response)
14
- @_request = request
15
- @_response = response
16
- @_response.request = request
17
- ret = process(request.parameters[:action])
18
- if cookies = @_request.env['action_dispatch.cookies']
19
- cookies.write(@_response)
20
- end
21
- @_response.prepare!
22
- ret
23
- end
24
-
25
7
  # TODO : Rewrite tests using controller.headers= to use Rack env
26
8
  def headers=(new_headers)
27
9
  @_response ||= ActionDispatch::Response.new
28
10
  @_response.headers.replace(new_headers)
29
11
  end
30
12
 
13
+ # Behavior specific to functional tests
14
+ module Functional # :nodoc:
15
+ def set_response!(request)
16
+ end
17
+
18
+ def recycle!
19
+ @_url_options = nil
20
+ self.formats = nil
21
+ self.params = nil
22
+ end
23
+ end
24
+
31
25
  module ClassMethods
32
26
  def before_filters
33
27
  _process_action_callbacks.find_all{|x| x.kind == :before}.map{|x| x.name}