actionpack 5.2.2.1 → 5.2.5
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +92 -0
- data/lib/action_controller/metal.rb +2 -2
- data/lib/action_controller/metal/params_wrapper.rb +2 -2
- data/lib/action_controller/metal/request_forgery_protection.rb +30 -10
- data/lib/action_controller/metal/strong_parameters.rb +2 -0
- data/lib/action_controller/test_case.rb +7 -6
- data/lib/action_dispatch.rb +5 -4
- data/lib/action_dispatch/http/cache.rb +6 -4
- data/lib/action_dispatch/journey/path/pattern.rb +2 -1
- data/lib/action_dispatch/middleware/session/abstract_store.rb +14 -0
- data/lib/action_dispatch/middleware/session/cache_store.rb +11 -6
- data/lib/action_dispatch/middleware/session/cookie_store.rb +17 -7
- data/lib/action_dispatch/middleware/stack.rb +2 -2
- data/lib/action_dispatch/request/session.rb +7 -1
- data/lib/action_dispatch/testing/integration.rb +1 -0
- data/lib/action_pack/gem_version.rb +2 -2
- metadata +17 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3b9466cc66aef89ae39a6f759279293fa180454f543f7149d1ab8de9ed9ae899
|
4
|
+
data.tar.gz: a72f72e877d142cc9c377615429190f6327fbd6d8e522f7ada200c30ec02bba8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: caf16e1e2886b217f359e358d24d6eb33e692f40165c96a324571b009ceb7d1b97df22320c2e320106aad26e4f7874db26790ba7cc4f61c9a6a21fae13f9e366
|
7
|
+
data.tar.gz: 30094a122031f1a4cff32d7cc0ad6fe4a14e318267e3cfea6ff85f9ca172f8b1f6677299634c776df580c4b3a44200e494fa06f6933821d4d5b8838d9a7a4815
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,67 @@
|
|
1
|
+
## Rails 5.2.5 (March 26, 2021) ##
|
2
|
+
|
3
|
+
* No changes.
|
4
|
+
|
5
|
+
|
6
|
+
## Rails 5.2.4.5 (February 10, 2021) ##
|
7
|
+
|
8
|
+
* No changes.
|
9
|
+
|
10
|
+
|
11
|
+
## Rails 5.2.4.4 (September 09, 2020) ##
|
12
|
+
|
13
|
+
* No changes.
|
14
|
+
|
15
|
+
|
16
|
+
## Rails 5.2.4.3 (May 18, 2020) ##
|
17
|
+
|
18
|
+
* [CVE-2020-8166] HMAC raw CSRF token before masking it, so it cannot be used to reconstruct a per-form token
|
19
|
+
|
20
|
+
* [CVE-2020-8164] Return self when calling #each, #each_pair, and #each_value instead of the raw @parameters hash
|
21
|
+
|
22
|
+
|
23
|
+
## Rails 5.2.4.2 (March 19, 2020) ##
|
24
|
+
|
25
|
+
* No changes.
|
26
|
+
|
27
|
+
|
28
|
+
## Rails 5.2.4.1 (December 18, 2019) ##
|
29
|
+
|
30
|
+
* Fix possible information leak / session hijacking vulnerability.
|
31
|
+
|
32
|
+
The `ActionDispatch::Session::MemcacheStore` is still vulnerable given it requires the
|
33
|
+
gem dalli to be updated as well.
|
34
|
+
|
35
|
+
_Breaking changes:_
|
36
|
+
* `session.id` now returns an instance of `Rack::Session::SessionId` and not a String (use `session.id.public_id` to restore the old behaviour, see #38063)
|
37
|
+
* Accessing the session id using `session[:session_id]`/`session['session_id']` no longer works with
|
38
|
+
ruby 2.2 (see https://github.com/rails/rails/commit/2a52a38cb51b65d71cf91fc960777213cf96f962#commitcomment-37929811)
|
39
|
+
|
40
|
+
CVE-2019-16782.
|
41
|
+
|
42
|
+
|
43
|
+
## Rails 5.2.4 (November 27, 2019) ##
|
44
|
+
|
45
|
+
* No changes.
|
46
|
+
|
47
|
+
|
48
|
+
## Rails 5.2.3 (March 27, 2019) ##
|
49
|
+
|
50
|
+
* Allow using `public` and `no-cache` together in the the Cache Control header.
|
51
|
+
|
52
|
+
Before this change, even if `public` was specified in the Cache Control header,
|
53
|
+
it was excluded when `no-cache` was included. This change preserves the
|
54
|
+
`public` value as is.
|
55
|
+
|
56
|
+
Fixes #34780.
|
57
|
+
|
58
|
+
*Yuji Yaginuma*
|
59
|
+
|
60
|
+
* Allow `nil` params for `ActionController::TestCase`.
|
61
|
+
|
62
|
+
*Ryo Nakamura*
|
63
|
+
|
64
|
+
|
1
65
|
## Rails 5.2.2.1 (March 11, 2019) ##
|
2
66
|
|
3
67
|
* No changes.
|
@@ -169,6 +233,34 @@
|
|
169
233
|
|
170
234
|
* Matches behavior of `Hash#each` in `ActionController::Parameters#each`.
|
171
235
|
|
236
|
+
Rails 5.0 introduced a bug when looping through controller params using `each`. Only the keys of params hash were passed to the block, e.g.
|
237
|
+
|
238
|
+
# Parameters: {"param"=>"1", "param_two"=>"2"}
|
239
|
+
def index
|
240
|
+
params.each do |name|
|
241
|
+
puts name
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
# Prints
|
246
|
+
# param
|
247
|
+
# param_two
|
248
|
+
|
249
|
+
In Rails 5.2 the bug has been fixed and name will be an array (which was the behavior for all versions prior to 5.0), instead of a string.
|
250
|
+
|
251
|
+
To fix the code above simply change as per example below:
|
252
|
+
|
253
|
+
# Parameters: {"param"=>"1", "param_two"=>"2"}
|
254
|
+
def index
|
255
|
+
params.each do |name, value|
|
256
|
+
puts name
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
# Prints
|
261
|
+
# param
|
262
|
+
# param_two
|
263
|
+
|
172
264
|
*Dominic Cleal*
|
173
265
|
|
174
266
|
* Add `Referrer-Policy` header to default headers set.
|
@@ -26,10 +26,10 @@ module ActionController
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
-
def build(action, app =
|
29
|
+
def build(action, app = nil, &block)
|
30
30
|
action = action.to_s
|
31
31
|
|
32
|
-
middlewares.reverse.inject(app) do |a, middleware|
|
32
|
+
middlewares.reverse.inject(app || block) do |a, middleware|
|
33
33
|
middleware.valid?(action) ? middleware.build(a) : a
|
34
34
|
end
|
35
35
|
end
|
@@ -93,7 +93,7 @@ module ActionController
|
|
93
93
|
end
|
94
94
|
|
95
95
|
def model
|
96
|
-
super ||
|
96
|
+
super || self.model = _default_wrap_model
|
97
97
|
end
|
98
98
|
|
99
99
|
def include
|
@@ -115,7 +115,7 @@ module ActionController
|
|
115
115
|
|
116
116
|
if m.respond_to?(:nested_attributes_options) && m.nested_attributes_options.keys.any?
|
117
117
|
self.include += m.nested_attributes_options.keys.map do |key|
|
118
|
-
key.to_s.concat("_attributes")
|
118
|
+
key.to_s.dup.concat("_attributes")
|
119
119
|
end
|
120
120
|
end
|
121
121
|
|
@@ -318,13 +318,10 @@ module ActionController #:nodoc:
|
|
318
318
|
action_path = normalize_action_path(action)
|
319
319
|
per_form_csrf_token(session, action_path, method)
|
320
320
|
else
|
321
|
-
|
321
|
+
global_csrf_token(session)
|
322
322
|
end
|
323
323
|
|
324
|
-
|
325
|
-
encrypted_csrf_token = xor_byte_strings(one_time_pad, raw_token)
|
326
|
-
masked_token = one_time_pad + encrypted_csrf_token
|
327
|
-
Base64.strict_encode64(masked_token)
|
324
|
+
mask_token(raw_token)
|
328
325
|
end
|
329
326
|
|
330
327
|
# Checks the client's masked token to see if it matches the
|
@@ -336,7 +333,7 @@ module ActionController #:nodoc:
|
|
336
333
|
end
|
337
334
|
|
338
335
|
begin
|
339
|
-
masked_token = Base64.
|
336
|
+
masked_token = Base64.urlsafe_decode64(encoded_masked_token)
|
340
337
|
rescue ArgumentError # encoded_masked_token is invalid Base64
|
341
338
|
return false
|
342
339
|
end
|
@@ -354,7 +351,8 @@ module ActionController #:nodoc:
|
|
354
351
|
elsif masked_token.length == AUTHENTICITY_TOKEN_LENGTH * 2
|
355
352
|
csrf_token = unmask_token(masked_token)
|
356
353
|
|
357
|
-
|
354
|
+
compare_with_global_token(csrf_token, session) ||
|
355
|
+
compare_with_real_token(csrf_token, session) ||
|
358
356
|
valid_per_form_csrf_token?(csrf_token, session)
|
359
357
|
else
|
360
358
|
false # Token is malformed.
|
@@ -369,10 +367,21 @@ module ActionController #:nodoc:
|
|
369
367
|
xor_byte_strings(one_time_pad, encrypted_csrf_token)
|
370
368
|
end
|
371
369
|
|
370
|
+
def mask_token(raw_token) # :doc:
|
371
|
+
one_time_pad = SecureRandom.random_bytes(AUTHENTICITY_TOKEN_LENGTH)
|
372
|
+
encrypted_csrf_token = xor_byte_strings(one_time_pad, raw_token)
|
373
|
+
masked_token = one_time_pad + encrypted_csrf_token
|
374
|
+
Base64.urlsafe_encode64(masked_token).delete("=")
|
375
|
+
end
|
376
|
+
|
372
377
|
def compare_with_real_token(token, session) # :doc:
|
373
378
|
ActiveSupport::SecurityUtils.fixed_length_secure_compare(token, real_csrf_token(session))
|
374
379
|
end
|
375
380
|
|
381
|
+
def compare_with_global_token(token, session) # :doc:
|
382
|
+
ActiveSupport::SecurityUtils.fixed_length_secure_compare(token, global_csrf_token(session))
|
383
|
+
end
|
384
|
+
|
376
385
|
def valid_per_form_csrf_token?(token, session) # :doc:
|
377
386
|
if per_form_csrf_tokens
|
378
387
|
correct_token = per_form_csrf_token(
|
@@ -388,15 +397,26 @@ module ActionController #:nodoc:
|
|
388
397
|
end
|
389
398
|
|
390
399
|
def real_csrf_token(session) # :doc:
|
391
|
-
session[:_csrf_token] ||= SecureRandom.
|
392
|
-
Base64.
|
400
|
+
session[:_csrf_token] ||= SecureRandom.urlsafe_base64(AUTHENTICITY_TOKEN_LENGTH)
|
401
|
+
Base64.urlsafe_decode64(session[:_csrf_token])
|
393
402
|
end
|
394
403
|
|
395
404
|
def per_form_csrf_token(session, action_path, method) # :doc:
|
405
|
+
csrf_token_hmac(session, [action_path, method.downcase].join("#"))
|
406
|
+
end
|
407
|
+
|
408
|
+
GLOBAL_CSRF_TOKEN_IDENTIFIER = "!real_csrf_token"
|
409
|
+
private_constant :GLOBAL_CSRF_TOKEN_IDENTIFIER
|
410
|
+
|
411
|
+
def global_csrf_token(session) # :doc:
|
412
|
+
csrf_token_hmac(session, GLOBAL_CSRF_TOKEN_IDENTIFIER)
|
413
|
+
end
|
414
|
+
|
415
|
+
def csrf_token_hmac(session, identifier) # :doc:
|
396
416
|
OpenSSL::HMAC.digest(
|
397
417
|
OpenSSL::Digest::SHA256.new,
|
398
418
|
real_csrf_token(session),
|
399
|
-
|
419
|
+
identifier
|
400
420
|
)
|
401
421
|
end
|
402
422
|
|
@@ -177,12 +177,12 @@ module ActionController
|
|
177
177
|
|
178
178
|
# Methods #destroy and #load! are overridden to avoid calling methods on the
|
179
179
|
# @store object, which does not exist for the TestSession class.
|
180
|
-
class TestSession < Rack::Session::Abstract::
|
180
|
+
class TestSession < Rack::Session::Abstract::PersistedSecure::SecureSessionHash #:nodoc:
|
181
181
|
DEFAULT_OPTIONS = Rack::Session::Abstract::Persisted::DEFAULT_OPTIONS
|
182
182
|
|
183
183
|
def initialize(session = {})
|
184
184
|
super(nil, nil)
|
185
|
-
@id = SecureRandom.hex(16)
|
185
|
+
@id = Rack::Session::SessionId.new(SecureRandom.hex(16))
|
186
186
|
@data = stringify_keys(session)
|
187
187
|
@loaded = true
|
188
188
|
end
|
@@ -457,9 +457,10 @@ module ActionController
|
|
457
457
|
# respectively which will make tests more expressive.
|
458
458
|
#
|
459
459
|
# Note that the request method is not verified.
|
460
|
-
def process(action, method: "GET", params:
|
460
|
+
def process(action, method: "GET", params: nil, session: nil, body: nil, flash: {}, format: nil, xhr: false, as: nil)
|
461
461
|
check_required_ivars
|
462
462
|
|
463
|
+
action = action.to_s.dup
|
463
464
|
http_method = method.to_s.upcase
|
464
465
|
|
465
466
|
@html_document = nil
|
@@ -485,17 +486,17 @@ module ActionController
|
|
485
486
|
format ||= as
|
486
487
|
end
|
487
488
|
|
488
|
-
parameters = params.symbolize_keys
|
489
|
+
parameters = (params || {}).symbolize_keys
|
489
490
|
|
490
491
|
if format
|
491
492
|
parameters[:format] = format
|
492
493
|
end
|
493
494
|
|
494
|
-
generated_extras = @routes.generate_extras(parameters.merge(controller: controller_class_name, action: action
|
495
|
+
generated_extras = @routes.generate_extras(parameters.merge(controller: controller_class_name, action: action))
|
495
496
|
generated_path = generated_path(generated_extras)
|
496
497
|
query_string_keys = query_parameter_names(generated_extras)
|
497
498
|
|
498
|
-
@request.assign_parameters(@routes, controller_class_name, action
|
499
|
+
@request.assign_parameters(@routes, controller_class_name, action, parameters, generated_path, query_string_keys)
|
499
500
|
|
500
501
|
@request.session.update(session) if session
|
501
502
|
@request.flash.update(flash || {})
|
data/lib/action_dispatch.rb
CHANGED
@@ -83,10 +83,11 @@ module ActionDispatch
|
|
83
83
|
end
|
84
84
|
|
85
85
|
module Session
|
86
|
-
autoload :AbstractStore,
|
87
|
-
autoload :
|
88
|
-
autoload :
|
89
|
-
autoload :
|
86
|
+
autoload :AbstractStore, "action_dispatch/middleware/session/abstract_store"
|
87
|
+
autoload :AbstractSecureStore, "action_dispatch/middleware/session/abstract_store"
|
88
|
+
autoload :CookieStore, "action_dispatch/middleware/session/cookie_store"
|
89
|
+
autoload :MemCacheStore, "action_dispatch/middleware/session/mem_cache_store"
|
90
|
+
autoload :CacheStore, "action_dispatch/middleware/session/cache_store"
|
90
91
|
end
|
91
92
|
|
92
93
|
mattr_accessor :test_app
|
@@ -197,10 +197,12 @@ module ActionDispatch
|
|
197
197
|
if control.empty?
|
198
198
|
# Let middleware handle default behavior
|
199
199
|
elsif control[:no_cache]
|
200
|
-
|
201
|
-
if control[:
|
202
|
-
|
203
|
-
|
200
|
+
options = []
|
201
|
+
options << PUBLIC if control[:public]
|
202
|
+
options << NO_CACHE
|
203
|
+
options.concat(control[:extras]) if control[:extras]
|
204
|
+
|
205
|
+
self._cache_control = options.join(", ")
|
204
206
|
else
|
205
207
|
extras = control[:extras]
|
206
208
|
max_age = control[:max_age]
|
@@ -83,7 +83,21 @@ module ActionDispatch
|
|
83
83
|
include SessionObject
|
84
84
|
|
85
85
|
private
|
86
|
+
def set_cookie(request, session_id, cookie)
|
87
|
+
request.cookie_jar[key] = cookie
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
class AbstractSecureStore < Rack::Session::Abstract::PersistedSecure
|
92
|
+
include Compatibility
|
93
|
+
include StaleSessionCheck
|
94
|
+
include SessionObject
|
95
|
+
|
96
|
+
def generate_sid
|
97
|
+
Rack::Session::SessionId.new(super)
|
98
|
+
end
|
86
99
|
|
100
|
+
private
|
87
101
|
def set_cookie(request, session_id, cookie)
|
88
102
|
request.cookie_jar[key] = cookie
|
89
103
|
end
|
@@ -12,7 +12,7 @@ module ActionDispatch
|
|
12
12
|
# * <tt>cache</tt> - The cache to use. If it is not specified, <tt>Rails.cache</tt> will be used.
|
13
13
|
# * <tt>expire_after</tt> - The length of time a session will be stored before automatically expiring.
|
14
14
|
# By default, the <tt>:expires_in</tt> option of the cache is used.
|
15
|
-
class CacheStore <
|
15
|
+
class CacheStore < AbstractSecureStore
|
16
16
|
def initialize(app, options = {})
|
17
17
|
@cache = options[:cache] || Rails.cache
|
18
18
|
options[:expire_after] ||= @cache.options[:expires_in]
|
@@ -21,7 +21,7 @@ module ActionDispatch
|
|
21
21
|
|
22
22
|
# Get a session from the cache.
|
23
23
|
def find_session(env, sid)
|
24
|
-
unless sid && (session =
|
24
|
+
unless sid && (session = get_session_with_fallback(sid))
|
25
25
|
sid, session = generate_sid, {}
|
26
26
|
end
|
27
27
|
[sid, session]
|
@@ -29,7 +29,7 @@ module ActionDispatch
|
|
29
29
|
|
30
30
|
# Set a session in the cache.
|
31
31
|
def write_session(env, sid, session, options)
|
32
|
-
key = cache_key(sid)
|
32
|
+
key = cache_key(sid.private_id)
|
33
33
|
if session
|
34
34
|
@cache.write(key, session, expires_in: options[:expire_after])
|
35
35
|
else
|
@@ -40,14 +40,19 @@ module ActionDispatch
|
|
40
40
|
|
41
41
|
# Remove a session from the cache.
|
42
42
|
def delete_session(env, sid, options)
|
43
|
-
@cache.delete(cache_key(sid))
|
43
|
+
@cache.delete(cache_key(sid.private_id))
|
44
|
+
@cache.delete(cache_key(sid.public_id))
|
44
45
|
generate_sid
|
45
46
|
end
|
46
47
|
|
47
48
|
private
|
48
49
|
# Turn the session id into a cache key.
|
49
|
-
def cache_key(
|
50
|
-
"_session_id:#{
|
50
|
+
def cache_key(id)
|
51
|
+
"_session_id:#{id}"
|
52
|
+
end
|
53
|
+
|
54
|
+
def get_session_with_fallback(sid)
|
55
|
+
@cache.read(cache_key(sid.private_id)) || @cache.read(cache_key(sid.public_id))
|
51
56
|
end
|
52
57
|
end
|
53
58
|
end
|
@@ -51,7 +51,16 @@ module ActionDispatch
|
|
51
51
|
# would set the session cookie to expire automatically 14 days after creation.
|
52
52
|
# Other useful options include <tt>:key</tt>, <tt>:secure</tt> and
|
53
53
|
# <tt>:httponly</tt>.
|
54
|
-
class CookieStore <
|
54
|
+
class CookieStore < AbstractSecureStore
|
55
|
+
class SessionId < DelegateClass(Rack::Session::SessionId)
|
56
|
+
attr_reader :cookie_value
|
57
|
+
|
58
|
+
def initialize(session_id, cookie_value = {})
|
59
|
+
super(session_id)
|
60
|
+
@cookie_value = cookie_value
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
55
64
|
def initialize(app, options = {})
|
56
65
|
super(app, options.merge!(cookie_only: true))
|
57
66
|
end
|
@@ -59,7 +68,7 @@ module ActionDispatch
|
|
59
68
|
def delete_session(req, session_id, options)
|
60
69
|
new_sid = generate_sid unless options[:drop]
|
61
70
|
# Reset hash and Assign the new session id
|
62
|
-
req.set_header("action_dispatch.request.unsigned_session_cookie", new_sid ? { "session_id" => new_sid } : {})
|
71
|
+
req.set_header("action_dispatch.request.unsigned_session_cookie", new_sid ? { "session_id" => new_sid.public_id } : {})
|
63
72
|
new_sid
|
64
73
|
end
|
65
74
|
|
@@ -67,7 +76,7 @@ module ActionDispatch
|
|
67
76
|
stale_session_check! do
|
68
77
|
data = unpacked_cookie_data(req)
|
69
78
|
data = persistent_session_id!(data)
|
70
|
-
[data["session_id"], data]
|
79
|
+
[Rack::Session::SessionId.new(data["session_id"]), data]
|
71
80
|
end
|
72
81
|
end
|
73
82
|
|
@@ -75,7 +84,8 @@ module ActionDispatch
|
|
75
84
|
|
76
85
|
def extract_session_id(req)
|
77
86
|
stale_session_check! do
|
78
|
-
unpacked_cookie_data(req)["session_id"]
|
87
|
+
sid = unpacked_cookie_data(req)["session_id"]
|
88
|
+
sid && Rack::Session::SessionId.new(sid)
|
79
89
|
end
|
80
90
|
end
|
81
91
|
|
@@ -93,13 +103,13 @@ module ActionDispatch
|
|
93
103
|
|
94
104
|
def persistent_session_id!(data, sid = nil)
|
95
105
|
data ||= {}
|
96
|
-
data["session_id"] ||= sid || generate_sid
|
106
|
+
data["session_id"] ||= sid || generate_sid.public_id
|
97
107
|
data
|
98
108
|
end
|
99
109
|
|
100
110
|
def write_session(req, sid, session_data, options)
|
101
|
-
session_data["session_id"] = sid
|
102
|
-
session_data
|
111
|
+
session_data["session_id"] = sid.public_id
|
112
|
+
SessionId.new(sid, session_data)
|
103
113
|
end
|
104
114
|
|
105
115
|
def set_cookie(request, session_id, cookie)
|
@@ -97,8 +97,8 @@ module ActionDispatch
|
|
97
97
|
middlewares.push(build_middleware(klass, args, block))
|
98
98
|
end
|
99
99
|
|
100
|
-
def build(app =
|
101
|
-
middlewares.freeze.reverse.inject(app) { |a, e| e.build(a) }
|
100
|
+
def build(app = nil, &block)
|
101
|
+
middlewares.freeze.reverse.inject(app || block) { |a, e| e.build(a) }
|
102
102
|
end
|
103
103
|
|
104
104
|
private
|
@@ -90,7 +90,13 @@ module ActionDispatch
|
|
90
90
|
# +nil+ if the given key is not found in the session.
|
91
91
|
def [](key)
|
92
92
|
load_for_read!
|
93
|
-
|
93
|
+
key = key.to_s
|
94
|
+
|
95
|
+
if key == "session_id"
|
96
|
+
id && id.public_id
|
97
|
+
else
|
98
|
+
@delegate[key]
|
99
|
+
end
|
94
100
|
end
|
95
101
|
|
96
102
|
# Returns true if the session has the given key or false.
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: actionpack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.2.
|
4
|
+
version: 5.2.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Heinemeier Hansson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-03-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - '='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 5.2.
|
19
|
+
version: 5.2.5
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - '='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 5.2.
|
26
|
+
version: 5.2.5
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rack
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -31,6 +31,9 @@ dependencies:
|
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '2.0'
|
34
|
+
- - ">="
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: 2.0.8
|
34
37
|
type: :runtime
|
35
38
|
prerelease: false
|
36
39
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -38,6 +41,9 @@ dependencies:
|
|
38
41
|
- - "~>"
|
39
42
|
- !ruby/object:Gem::Version
|
40
43
|
version: '2.0'
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 2.0.8
|
41
47
|
- !ruby/object:Gem::Dependency
|
42
48
|
name: rack-test
|
43
49
|
requirement: !ruby/object:Gem::Requirement
|
@@ -92,28 +98,28 @@ dependencies:
|
|
92
98
|
requirements:
|
93
99
|
- - '='
|
94
100
|
- !ruby/object:Gem::Version
|
95
|
-
version: 5.2.
|
101
|
+
version: 5.2.5
|
96
102
|
type: :runtime
|
97
103
|
prerelease: false
|
98
104
|
version_requirements: !ruby/object:Gem::Requirement
|
99
105
|
requirements:
|
100
106
|
- - '='
|
101
107
|
- !ruby/object:Gem::Version
|
102
|
-
version: 5.2.
|
108
|
+
version: 5.2.5
|
103
109
|
- !ruby/object:Gem::Dependency
|
104
110
|
name: activemodel
|
105
111
|
requirement: !ruby/object:Gem::Requirement
|
106
112
|
requirements:
|
107
113
|
- - '='
|
108
114
|
- !ruby/object:Gem::Version
|
109
|
-
version: 5.2.
|
115
|
+
version: 5.2.5
|
110
116
|
type: :development
|
111
117
|
prerelease: false
|
112
118
|
version_requirements: !ruby/object:Gem::Requirement
|
113
119
|
requirements:
|
114
120
|
- - '='
|
115
121
|
- !ruby/object:Gem::Version
|
116
|
-
version: 5.2.
|
122
|
+
version: 5.2.5
|
117
123
|
description: Web apps on Rails. Simple, battle-tested conventions for building and
|
118
124
|
testing MVC web applications. Works with any Rack-compatible server.
|
119
125
|
email: david@loudthinking.com
|
@@ -293,8 +299,8 @@ homepage: http://rubyonrails.org
|
|
293
299
|
licenses:
|
294
300
|
- MIT
|
295
301
|
metadata:
|
296
|
-
source_code_uri: https://github.com/rails/rails/tree/v5.2.
|
297
|
-
changelog_uri: https://github.com/rails/rails/blob/v5.2.
|
302
|
+
source_code_uri: https://github.com/rails/rails/tree/v5.2.5/actionpack
|
303
|
+
changelog_uri: https://github.com/rails/rails/blob/v5.2.5/actionpack/CHANGELOG.md
|
298
304
|
post_install_message:
|
299
305
|
rdoc_options: []
|
300
306
|
require_paths:
|
@@ -311,7 +317,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
311
317
|
version: '0'
|
312
318
|
requirements:
|
313
319
|
- none
|
314
|
-
rubygems_version: 3.
|
320
|
+
rubygems_version: 3.1.2
|
315
321
|
signing_key:
|
316
322
|
specification_version: 4
|
317
323
|
summary: Web-flow and rendering framework putting the VC in MVC (part of Rails).
|