activesupport 5.0.7.2 → 5.1.7

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

Potentially problematic release.


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

Files changed (211) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +464 -694
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +1 -1
  5. data/lib/active_support.rb +8 -4
  6. data/lib/active_support/all.rb +3 -3
  7. data/lib/active_support/array_inquirer.rb +7 -5
  8. data/lib/active_support/backtrace_cleaner.rb +4 -4
  9. data/lib/active_support/benchmarkable.rb +3 -3
  10. data/lib/active_support/builder.rb +1 -1
  11. data/lib/active_support/cache.rb +41 -48
  12. data/lib/active_support/cache/file_store.rb +11 -20
  13. data/lib/active_support/cache/mem_cache_store.rb +30 -40
  14. data/lib/active_support/cache/memory_store.rb +13 -13
  15. data/lib/active_support/cache/null_store.rb +4 -4
  16. data/lib/active_support/cache/strategy/local_cache.rb +13 -22
  17. data/lib/active_support/cache/strategy/local_cache_middleware.rb +4 -5
  18. data/lib/active_support/callbacks.rb +649 -584
  19. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +17 -0
  20. data/lib/active_support/concurrency/share_lock.rb +20 -21
  21. data/lib/active_support/configurable.rb +5 -5
  22. data/lib/active_support/core_ext.rb +1 -2
  23. data/lib/active_support/core_ext/array.rb +7 -7
  24. data/lib/active_support/core_ext/array/access.rb +1 -1
  25. data/lib/active_support/core_ext/array/conversions.rb +15 -15
  26. data/lib/active_support/core_ext/array/grouping.rb +1 -1
  27. data/lib/active_support/core_ext/array/inquiry.rb +1 -1
  28. data/lib/active_support/core_ext/array/prepend_and_append.rb +1 -1
  29. data/lib/active_support/core_ext/benchmark.rb +1 -1
  30. data/lib/active_support/core_ext/big_decimal.rb +1 -1
  31. data/lib/active_support/core_ext/big_decimal/conversions.rb +4 -6
  32. data/lib/active_support/core_ext/class.rb +2 -2
  33. data/lib/active_support/core_ext/class/attribute.rb +5 -5
  34. data/lib/active_support/core_ext/class/attribute_accessors.rb +1 -1
  35. data/lib/active_support/core_ext/class/subclasses.rb +18 -4
  36. data/lib/active_support/core_ext/date.rb +5 -5
  37. data/lib/active_support/core_ext/date/acts_like.rb +1 -1
  38. data/lib/active_support/core_ext/date/blank.rb +1 -1
  39. data/lib/active_support/core_ext/date/calculations.rb +8 -8
  40. data/lib/active_support/core_ext/date/conversions.rb +12 -12
  41. data/lib/active_support/core_ext/date/zones.rb +2 -2
  42. data/lib/active_support/core_ext/date_and_time/calculations.rb +27 -22
  43. data/lib/active_support/core_ext/date_and_time/compatibility.rb +1 -1
  44. data/lib/active_support/core_ext/date_and_time/zones.rb +7 -8
  45. data/lib/active_support/core_ext/date_time.rb +5 -5
  46. data/lib/active_support/core_ext/date_time/acts_like.rb +2 -2
  47. data/lib/active_support/core_ext/date_time/blank.rb +1 -1
  48. data/lib/active_support/core_ext/date_time/calculations.rb +20 -10
  49. data/lib/active_support/core_ext/date_time/compatibility.rb +2 -2
  50. data/lib/active_support/core_ext/date_time/conversions.rb +12 -12
  51. data/lib/active_support/core_ext/digest/uuid.rb +4 -4
  52. data/lib/active_support/core_ext/enumerable.rb +23 -12
  53. data/lib/active_support/core_ext/file.rb +1 -1
  54. data/lib/active_support/core_ext/file/atomic.rb +4 -4
  55. data/lib/active_support/core_ext/hash.rb +9 -9
  56. data/lib/active_support/core_ext/hash/compact.rb +12 -9
  57. data/lib/active_support/core_ext/hash/conversions.rb +36 -37
  58. data/lib/active_support/core_ext/hash/indifferent_access.rb +1 -2
  59. data/lib/active_support/core_ext/hash/keys.rb +6 -6
  60. data/lib/active_support/core_ext/hash/reverse_merge.rb +1 -1
  61. data/lib/active_support/core_ext/hash/slice.rb +4 -4
  62. data/lib/active_support/core_ext/hash/transform_values.rb +1 -0
  63. data/lib/active_support/core_ext/integer.rb +3 -3
  64. data/lib/active_support/core_ext/integer/inflections.rb +1 -1
  65. data/lib/active_support/core_ext/integer/time.rb +2 -2
  66. data/lib/active_support/core_ext/kernel.rb +4 -4
  67. data/lib/active_support/core_ext/kernel/concern.rb +1 -1
  68. data/lib/active_support/core_ext/kernel/reporting.rb +1 -1
  69. data/lib/active_support/core_ext/load_error.rb +1 -18
  70. data/lib/active_support/core_ext/module.rb +11 -12
  71. data/lib/active_support/core_ext/module/aliasing.rb +3 -48
  72. data/lib/active_support/core_ext/module/attr_internal.rb +4 -4
  73. data/lib/active_support/core_ext/module/attribute_accessors.rb +11 -5
  74. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +20 -13
  75. data/lib/active_support/core_ext/module/concerning.rb +1 -1
  76. data/lib/active_support/core_ext/module/delegation.rb +85 -16
  77. data/lib/active_support/core_ext/module/introspection.rb +3 -11
  78. data/lib/active_support/core_ext/module/reachable.rb +2 -2
  79. data/lib/active_support/core_ext/numeric.rb +4 -4
  80. data/lib/active_support/core_ext/numeric/conversions.rb +3 -9
  81. data/lib/active_support/core_ext/numeric/inquiry.rb +21 -21
  82. data/lib/active_support/core_ext/numeric/time.rb +5 -5
  83. data/lib/active_support/core_ext/object.rb +12 -12
  84. data/lib/active_support/core_ext/object/blank.rb +3 -1
  85. data/lib/active_support/core_ext/object/conversions.rb +4 -4
  86. data/lib/active_support/core_ext/object/deep_dup.rb +1 -1
  87. data/lib/active_support/core_ext/object/duplicable.rb +34 -4
  88. data/lib/active_support/core_ext/object/inclusion.rb +1 -1
  89. data/lib/active_support/core_ext/object/json.rb +26 -12
  90. data/lib/active_support/core_ext/object/to_param.rb +1 -1
  91. data/lib/active_support/core_ext/object/to_query.rb +8 -5
  92. data/lib/active_support/core_ext/object/try.rb +1 -1
  93. data/lib/active_support/core_ext/object/with_options.rb +12 -1
  94. data/lib/active_support/core_ext/range.rb +4 -4
  95. data/lib/active_support/core_ext/range/conversions.rb +1 -1
  96. data/lib/active_support/core_ext/regexp.rb +4 -0
  97. data/lib/active_support/core_ext/securerandom.rb +3 -3
  98. data/lib/active_support/core_ext/string.rb +13 -13
  99. data/lib/active_support/core_ext/string/access.rb +6 -6
  100. data/lib/active_support/core_ext/string/conversions.rb +2 -2
  101. data/lib/active_support/core_ext/string/filters.rb +3 -3
  102. data/lib/active_support/core_ext/string/indent.rb +4 -4
  103. data/lib/active_support/core_ext/string/inflections.rb +10 -14
  104. data/lib/active_support/core_ext/string/inquiry.rb +1 -1
  105. data/lib/active_support/core_ext/string/multibyte.rb +1 -1
  106. data/lib/active_support/core_ext/string/output_safety.rb +19 -20
  107. data/lib/active_support/core_ext/string/strip.rb +1 -1
  108. data/lib/active_support/core_ext/string/zones.rb +2 -2
  109. data/lib/active_support/core_ext/time.rb +5 -5
  110. data/lib/active_support/core_ext/time/acts_like.rb +1 -1
  111. data/lib/active_support/core_ext/time/calculations.rb +46 -29
  112. data/lib/active_support/core_ext/time/conversions.rb +15 -12
  113. data/lib/active_support/core_ext/time/zones.rb +3 -3
  114. data/lib/active_support/core_ext/uri.rb +2 -2
  115. data/lib/active_support/dependencies.rb +45 -46
  116. data/lib/active_support/dependencies/interlock.rb +1 -1
  117. data/lib/active_support/deprecation.rb +9 -8
  118. data/lib/active_support/deprecation/behaviors.rb +3 -3
  119. data/lib/active_support/deprecation/constant_accessor.rb +50 -0
  120. data/lib/active_support/deprecation/instance_delegator.rb +2 -2
  121. data/lib/active_support/deprecation/method_wrappers.rb +10 -3
  122. data/lib/active_support/deprecation/proxy_wrappers.rb +6 -4
  123. data/lib/active_support/deprecation/reporting.rb +7 -7
  124. data/lib/active_support/duration.rb +221 -28
  125. data/lib/active_support/duration/iso8601_parser.rb +66 -65
  126. data/lib/active_support/duration/iso8601_serializer.rb +11 -9
  127. data/lib/active_support/evented_file_update_checker.rb +59 -55
  128. data/lib/active_support/execution_wrapper.rb +3 -3
  129. data/lib/active_support/executor.rb +1 -1
  130. data/lib/active_support/file_update_checker.rb +54 -50
  131. data/lib/active_support/gem_version.rb +2 -2
  132. data/lib/active_support/gzip.rb +4 -4
  133. data/lib/active_support/hash_with_indifferent_access.rb +40 -28
  134. data/lib/active_support/i18n.rb +5 -5
  135. data/lib/active_support/i18n_railtie.rb +14 -9
  136. data/lib/active_support/inflections.rb +11 -11
  137. data/lib/active_support/inflector.rb +5 -5
  138. data/lib/active_support/inflector/inflections.rb +11 -9
  139. data/lib/active_support/inflector/methods.rb +52 -51
  140. data/lib/active_support/inflector/transliterate.rb +8 -11
  141. data/lib/active_support/json.rb +2 -2
  142. data/lib/active_support/json/decoding.rb +3 -3
  143. data/lib/active_support/json/encoding.rb +8 -7
  144. data/lib/active_support/key_generator.rb +17 -17
  145. data/lib/active_support/lazy_load_hooks.rb +2 -2
  146. data/lib/active_support/log_subscriber.rb +9 -7
  147. data/lib/active_support/log_subscriber/test_helper.rb +9 -9
  148. data/lib/active_support/logger.rb +3 -3
  149. data/lib/active_support/logger_silence.rb +3 -3
  150. data/lib/active_support/logger_thread_safe_level.rb +1 -1
  151. data/lib/active_support/message_encryptor.rb +77 -35
  152. data/lib/active_support/message_verifier.rb +7 -7
  153. data/lib/active_support/multibyte.rb +2 -2
  154. data/lib/active_support/multibyte/chars.rb +23 -21
  155. data/lib/active_support/multibyte/unicode.rb +68 -89
  156. data/lib/active_support/notifications.rb +7 -5
  157. data/lib/active_support/notifications/fanout.rb +3 -3
  158. data/lib/active_support/notifications/instrumenter.rb +5 -5
  159. data/lib/active_support/number_helper.rb +5 -4
  160. data/lib/active_support/number_helper/number_converter.rb +11 -11
  161. data/lib/active_support/number_helper/number_to_currency_converter.rb +3 -3
  162. data/lib/active_support/number_helper/number_to_delimited_converter.rb +1 -2
  163. data/lib/active_support/number_helper/number_to_human_converter.rb +8 -10
  164. data/lib/active_support/number_helper/number_to_human_size_converter.rb +6 -11
  165. data/lib/active_support/number_helper/number_to_percentage_converter.rb +1 -1
  166. data/lib/active_support/number_helper/number_to_phone_converter.rb +1 -3
  167. data/lib/active_support/number_helper/number_to_rounded_converter.rb +12 -32
  168. data/lib/active_support/number_helper/rounding_helper.rb +64 -0
  169. data/lib/active_support/option_merger.rb +1 -1
  170. data/lib/active_support/ordered_hash.rb +3 -3
  171. data/lib/active_support/ordered_options.rb +6 -4
  172. data/lib/active_support/per_thread_registry.rb +5 -5
  173. data/lib/active_support/rails.rb +12 -6
  174. data/lib/active_support/railtie.rb +3 -3
  175. data/lib/active_support/reloader.rb +1 -1
  176. data/lib/active_support/rescuable.rb +6 -6
  177. data/lib/active_support/security_utils.rb +1 -1
  178. data/lib/active_support/string_inquirer.rb +8 -2
  179. data/lib/active_support/subscriber.rb +9 -5
  180. data/lib/active_support/tagged_logging.rb +4 -4
  181. data/lib/active_support/test_case.rb +12 -29
  182. data/lib/active_support/testing/assertions.rb +100 -2
  183. data/lib/active_support/testing/autorun.rb +2 -2
  184. data/lib/active_support/testing/constant_lookup.rb +0 -1
  185. data/lib/active_support/testing/declarative.rb +1 -1
  186. data/lib/active_support/testing/deprecation.rb +3 -2
  187. data/lib/active_support/testing/isolation.rb +15 -22
  188. data/lib/active_support/testing/method_call_assertions.rb +1 -1
  189. data/lib/active_support/testing/setup_and_teardown.rb +2 -2
  190. data/lib/active_support/testing/stream.rb +28 -28
  191. data/lib/active_support/testing/tagged_logging.rb +1 -1
  192. data/lib/active_support/testing/time_helpers.rb +45 -11
  193. data/lib/active_support/time.rb +12 -12
  194. data/lib/active_support/time_with_zone.rb +16 -14
  195. data/lib/active_support/values/time_zone.rb +100 -31
  196. data/lib/active_support/values/unicode_tables.dat +0 -0
  197. data/lib/active_support/version.rb +1 -1
  198. data/lib/active_support/xml_mini.rb +34 -36
  199. data/lib/active_support/xml_mini/jdom.rb +112 -112
  200. data/lib/active_support/xml_mini/libxml.rb +12 -11
  201. data/lib/active_support/xml_mini/libxmlsax.rb +13 -14
  202. data/lib/active_support/xml_mini/nokogiri.rb +10 -10
  203. data/lib/active_support/xml_mini/nokogirisax.rb +12 -13
  204. data/lib/active_support/xml_mini/rexml.rb +9 -9
  205. metadata +8 -9
  206. data/lib/active_support/concurrency/latch.rb +0 -26
  207. data/lib/active_support/core_ext/kernel/debugger.rb +0 -3
  208. data/lib/active_support/core_ext/module/method_transplanting.rb +0 -3
  209. data/lib/active_support/core_ext/module/qualified_const.rb +0 -70
  210. data/lib/active_support/core_ext/struct.rb +0 -3
  211. data/lib/active_support/core_ext/time/marshal.rb +0 -3
@@ -1,9 +1,8 @@
1
- require 'active_support/core_ext/string/multibyte'
2
- require 'active_support/i18n'
1
+ require "active_support/core_ext/string/multibyte"
2
+ require "active_support/i18n"
3
3
 
4
4
  module ActiveSupport
5
5
  module Inflector
6
-
7
6
  # Replaces non-ASCII characters with an ASCII approximation, or if none
8
7
  # exists, a replacement character which defaults to "?".
9
8
  #
@@ -58,9 +57,11 @@ module ActiveSupport
58
57
  # transliterate('Jürgen')
59
58
  # # => "Juergen"
60
59
  def transliterate(string, replacement = "?".freeze)
60
+ raise ArgumentError, "Can only transliterate strings. Received #{string.class.name}" unless string.is_a?(String)
61
+
61
62
  I18n.transliterate(ActiveSupport::Multibyte::Unicode.normalize(
62
63
  ActiveSupport::Multibyte::Unicode.tidy_bytes(string), :c),
63
- :replacement => replacement)
64
+ replacement: replacement)
64
65
  end
65
66
 
66
67
  # Replaces special characters in a string so that it may be used as part of
@@ -79,11 +80,7 @@ module ActiveSupport
79
80
  # parameterize("Donald E. Knuth", preserve_case: true) # => "Donald-E-Knuth"
80
81
  # parameterize("^trés|Jolie-- ", preserve_case: true) # => "tres-Jolie"
81
82
  #
82
- def parameterize(string, sep = :unused, separator: '-', preserve_case: false)
83
- unless sep == :unused
84
- ActiveSupport::Deprecation.warn("Passing the separator argument as a positional parameter is deprecated and will soon be removed. Use `separator: '#{sep}'` instead.")
85
- separator = sep
86
- end
83
+ def parameterize(string, separator: "-", preserve_case: false)
87
84
  # Replace accented chars with their ASCII equivalents.
88
85
  parameterized_string = transliterate(string)
89
86
 
@@ -102,9 +99,9 @@ module ActiveSupport
102
99
  # No more than one of the separator in a row.
103
100
  parameterized_string.gsub!(re_duplicate_separator, separator)
104
101
  # Remove leading/trailing separator.
105
- parameterized_string.gsub!(re_leading_trailing_separator, ''.freeze)
102
+ parameterized_string.gsub!(re_leading_trailing_separator, "".freeze)
106
103
  end
107
-
104
+
108
105
  parameterized_string.downcase! unless preserve_case
109
106
  parameterized_string
110
107
  end
@@ -1,2 +1,2 @@
1
- require 'active_support/json/decoding'
2
- require 'active_support/json/encoding'
1
+ require "active_support/json/decoding"
2
+ require "active_support/json/encoding"
@@ -1,6 +1,6 @@
1
- require 'active_support/core_ext/module/attribute_accessors'
2
- require 'active_support/core_ext/module/delegation'
3
- require 'json'
1
+ require "active_support/core_ext/module/attribute_accessors"
2
+ require "active_support/core_ext/module/delegation"
3
+ require "json"
4
4
 
5
5
  module ActiveSupport
6
6
  # Look for and parse json strings that look like ISO 8601 times.
@@ -1,5 +1,5 @@
1
- require 'active_support/core_ext/object/json'
2
- require 'active_support/core_ext/module/delegation'
1
+ require "active_support/core_ext/object/json"
2
+ require "active_support/core_ext/module/delegation"
3
3
 
4
4
  module ActiveSupport
5
5
  class << self
@@ -7,7 +7,7 @@ module ActiveSupport
7
7
  :time_precision, :time_precision=,
8
8
  :escape_html_entities_in_json, :escape_html_entities_in_json=,
9
9
  :json_encoder, :json_encoder=,
10
- :to => :'ActiveSupport::JSON::Encoding'
10
+ to: :'ActiveSupport::JSON::Encoding'
11
11
  end
12
12
 
13
13
  module JSON
@@ -40,9 +40,9 @@ module ActiveSupport
40
40
  ESCAPED_CHARS = {
41
41
  "\u2028" => '\u2028',
42
42
  "\u2029" => '\u2029',
43
- '>' => '\u003e',
44
- '<' => '\u003c',
45
- '&' => '\u0026',
43
+ ">" => '\u003e',
44
+ "<" => '\u003c',
45
+ "&" => '\u0026',
46
46
  }
47
47
 
48
48
  ESCAPE_REGEX_WITH_HTML_ENTITIES = /[\u2028\u2029><&]/u
@@ -68,7 +68,8 @@ module ActiveSupport
68
68
  :ESCAPE_REGEX_WITHOUT_HTML_ENTITIES, :EscapedString
69
69
 
70
70
  # Convert an object into a "JSON-ready" representation composed of
71
- # primitives like Hash, Array, String, Numeric, and true/false/nil.
71
+ # primitives like Hash, Array, String, Numeric,
72
+ # and +true+/+false+/+nil+.
72
73
  # Recursively calls #as_json to the object to recursively build a
73
74
  # fully JSON-ready object.
74
75
  #
@@ -1,5 +1,5 @@
1
- require 'concurrent/map'
2
- require 'openssl'
1
+ require "concurrent/map"
2
+ require "openssl"
3
3
 
4
4
  module ActiveSupport
5
5
  # KeyGenerator is a simple wrapper around OpenSSL's implementation of PBKDF2.
@@ -17,7 +17,7 @@ module ActiveSupport
17
17
  # Returns a derived key suitable for use. The default key_size is chosen
18
18
  # to be compatible with the default settings of ActiveSupport::MessageVerifier.
19
19
  # i.e. OpenSSL::Digest::SHA1#block_length
20
- def generate_key(salt, key_size=64)
20
+ def generate_key(salt, key_size = 64)
21
21
  OpenSSL::PKCS5.pbkdf2_hmac_sha1(@secret, salt, @iterations, key_size)
22
22
  end
23
23
  end
@@ -51,21 +51,21 @@ module ActiveSupport
51
51
 
52
52
  private
53
53
 
54
- # To prevent users from using something insecure like "Password" we make sure that the
55
- # secret they've provided is at least 30 characters in length.
56
- def ensure_secret_secure(secret)
57
- if secret.blank?
58
- raise ArgumentError, "A secret is required to generate an integrity hash " \
59
- "for cookie session data. Set a secret_key_base of at least " \
60
- "#{SECRET_MIN_LENGTH} characters in config/secrets.yml."
61
- end
54
+ # To prevent users from using something insecure like "Password" we make sure that the
55
+ # secret they've provided is at least 30 characters in length.
56
+ def ensure_secret_secure(secret)
57
+ if secret.blank?
58
+ raise ArgumentError, "A secret is required to generate an integrity hash " \
59
+ "for cookie session data. Set a secret_key_base of at least " \
60
+ "#{SECRET_MIN_LENGTH} characters in config/secrets.yml."
61
+ end
62
62
 
63
- if secret.length < SECRET_MIN_LENGTH
64
- raise ArgumentError, "Secret should be something secure, " \
65
- "like \"#{SecureRandom.hex(16)}\". The value you " \
66
- "provided, \"#{secret}\", is shorter than the minimum length " \
67
- "of #{SECRET_MIN_LENGTH} characters."
63
+ if secret.length < SECRET_MIN_LENGTH
64
+ raise ArgumentError, "Secret should be something secure, " \
65
+ "like \"#{SecureRandom.hex(16)}\". The value you " \
66
+ "provided, \"#{secret}\", is shorter than the minimum length " \
67
+ "of #{SECRET_MIN_LENGTH} characters."
68
+ end
68
69
  end
69
- end
70
70
  end
71
71
  end
@@ -15,9 +15,9 @@ module ActiveSupport
15
15
  # end
16
16
  # end
17
17
  #
18
- # When the entirety of +activerecord/lib/active_record/base.rb+ has been
18
+ # When the entirety of +ActiveRecord::Base+ has been
19
19
  # evaluated then +run_load_hooks+ is invoked. The very last line of
20
- # +activerecord/lib/active_record/base.rb+ is:
20
+ # +ActiveRecord::Base+ is:
21
21
  #
22
22
  # ActiveSupport.run_load_hooks(:active_record, ActiveRecord::Base)
23
23
  module LazyLoadHooks
@@ -1,6 +1,6 @@
1
- require 'active_support/core_ext/module/attribute_accessors'
2
- require 'active_support/core_ext/class/attribute'
3
- require 'active_support/subscriber'
1
+ require "active_support/core_ext/module/attribute_accessors"
2
+ require "active_support/core_ext/class/attribute"
3
+ require "active_support/subscriber"
4
4
 
5
5
  module ActiveSupport
6
6
  # ActiveSupport::LogSubscriber is an object set to consume
@@ -81,11 +81,13 @@ module ActiveSupport
81
81
 
82
82
  def finish(name, id, payload)
83
83
  super if logger
84
- rescue Exception => e
85
- logger.error "Could not log #{name.inspect} event. #{e.class}: #{e.message} #{e.backtrace}"
84
+ rescue => e
85
+ if logger
86
+ logger.error "Could not log #{name.inspect} event. #{e.class}: #{e.message} #{e.backtrace}"
87
+ end
86
88
  end
87
89
 
88
- protected
90
+ private
89
91
 
90
92
  %w(info debug warn error fatal unknown).each do |level|
91
93
  class_eval <<-METHOD, __FILE__, __LINE__ + 1
@@ -99,7 +101,7 @@ module ActiveSupport
99
101
  # option is set to +true+, it also adds bold to the string. This is based
100
102
  # on the Highline implementation and will automatically append CLEAR to the
101
103
  # end of the returned String.
102
- def color(text, color, bold=false)
104
+ def color(text, color, bold = false) # :doc:
103
105
  return text unless colorize_logging
104
106
  color = self.class.const_get(color.upcase) if color.is_a?(Symbol)
105
107
  bold = bold ? BOLD : ""
@@ -1,6 +1,6 @@
1
- require 'active_support/log_subscriber'
2
- require 'active_support/logger'
3
- require 'active_support/notifications'
1
+ require "active_support/log_subscriber"
2
+ require "active_support/logger"
3
+ require "active_support/notifications"
4
4
 
5
5
  module ActiveSupport
6
6
  class LogSubscriber
@@ -58,15 +58,15 @@ module ActiveSupport
58
58
  def initialize(level = DEBUG)
59
59
  @flush_count = 0
60
60
  @level = level
61
- @logged = Hash.new { |h,k| h[k] = [] }
61
+ @logged = Hash.new { |h, k| h[k] = [] }
62
62
  end
63
63
 
64
64
  def method_missing(level, message = nil)
65
- if block_given?
66
- @logged[level] << yield
67
- else
68
- @logged[level] << message
69
- end
65
+ if block_given?
66
+ @logged[level] << yield
67
+ else
68
+ @logged[level] << message
69
+ end
70
70
  end
71
71
 
72
72
  def logged(level)
@@ -1,6 +1,6 @@
1
- require 'active_support/logger_silence'
2
- require 'active_support/logger_thread_safe_level'
3
- require 'logger'
1
+ require "active_support/logger_silence"
2
+ require "active_support/logger_thread_safe_level"
3
+ require "logger"
4
4
 
5
5
  module ActiveSupport
6
6
  class Logger < ::Logger
@@ -1,6 +1,6 @@
1
- require 'active_support/concern'
2
- require 'active_support/core_ext/module/attribute_accessors'
3
- require 'concurrent'
1
+ require "active_support/concern"
2
+ require "active_support/core_ext/module/attribute_accessors"
3
+ require "concurrent"
4
4
 
5
5
  module LoggerSilence
6
6
  extend ActiveSupport::Concern
@@ -1,4 +1,4 @@
1
- require 'active_support/concern'
1
+ require "active_support/concern"
2
2
 
3
3
  module ActiveSupport
4
4
  module LoggerThreadSafeLevel # :nodoc:
@@ -1,6 +1,7 @@
1
- require 'openssl'
2
- require 'base64'
3
- require 'active_support/core_ext/array/extract_options'
1
+ require "openssl"
2
+ require "base64"
3
+ require "active_support/core_ext/array/extract_options"
4
+ require "active_support/message_verifier"
4
5
 
5
6
  module ActiveSupport
6
7
  # MessageEncryptor is a simple way to encrypt values which get stored
@@ -30,6 +31,16 @@ module ActiveSupport
30
31
  end
31
32
  end
32
33
 
34
+ module NullVerifier #:nodoc:
35
+ def self.verify(value)
36
+ value
37
+ end
38
+
39
+ def self.generate(value)
40
+ value
41
+ end
42
+ end
43
+
33
44
  class InvalidMessage < StandardError; end
34
45
  OpenSSLCipherError = OpenSSL::Cipher::CipherError
35
46
 
@@ -39,18 +50,25 @@ module ActiveSupport
39
50
  # key by using <tt>ActiveSupport::KeyGenerator</tt> or a similar key
40
51
  # derivation function.
41
52
  #
53
+ # First additional parameter is used as the signature key for +MessageVerifier+.
54
+ # This allows you to specify keys to encrypt and sign data.
55
+ #
56
+ # ActiveSupport::MessageEncryptor.new('secret', 'signature_secret')
57
+ #
42
58
  # Options:
43
59
  # * <tt>:cipher</tt> - Cipher to use. Can be any cipher returned by
44
60
  # <tt>OpenSSL::Cipher.ciphers</tt>. Default is 'aes-256-cbc'.
45
- # * <tt>:digest</tt> - String of digest to use for signing. Default is +SHA1+.
61
+ # * <tt>:digest</tt> - String of digest to use for signing. Default is
62
+ # +SHA1+. Ignored when using an AEAD cipher like 'aes-256-gcm'.
46
63
  # * <tt>:serializer</tt> - Object serializer to use. Default is +Marshal+.
47
64
  def initialize(secret, *signature_key_or_options)
48
65
  options = signature_key_or_options.extract_options!
49
66
  sign_secret = signature_key_or_options.first
50
67
  @secret = secret
51
68
  @sign_secret = sign_secret
52
- @cipher = options[:cipher] || 'aes-256-cbc'
53
- @verifier = MessageVerifier.new(@sign_secret || @secret, digest: options[:digest] || 'SHA1', serializer: NullSerializer)
69
+ @cipher = options[:cipher] || DEFAULT_CIPHER
70
+ @digest = options[:digest] || "SHA1" unless aead_mode?
71
+ @verifier = resolve_verifier
54
72
  @serializer = options[:serializer] || Marshal
55
73
  end
56
74
 
@@ -73,42 +91,66 @@ module ActiveSupport
73
91
 
74
92
  private
75
93
 
76
- def _encrypt(value)
77
- cipher = new_cipher
78
- cipher.encrypt
79
- cipher.key = @secret
80
-
81
- # Rely on OpenSSL for the initialization vector
82
- iv = cipher.random_iv
94
+ def _encrypt(value)
95
+ cipher = new_cipher
96
+ cipher.encrypt
97
+ cipher.key = @secret
83
98
 
84
- encrypted_data = cipher.update(@serializer.dump(value))
85
- encrypted_data << cipher.final
99
+ # Rely on OpenSSL for the initialization vector
100
+ iv = cipher.random_iv
101
+ cipher.auth_data = "" if aead_mode?
86
102
 
87
- "#{::Base64.strict_encode64 encrypted_data}--#{::Base64.strict_encode64 iv}"
88
- end
103
+ encrypted_data = cipher.update(@serializer.dump(value))
104
+ encrypted_data << cipher.final
89
105
 
90
- def _decrypt(encrypted_message)
91
- cipher = new_cipher
92
- encrypted_data, iv = encrypted_message.split("--".freeze).map {|v| ::Base64.strict_decode64(v)}
106
+ blob = "#{::Base64.strict_encode64 encrypted_data}--#{::Base64.strict_encode64 iv}"
107
+ blob << "--#{::Base64.strict_encode64 cipher.auth_tag}" if aead_mode?
108
+ blob
109
+ end
93
110
 
94
- cipher.decrypt
95
- cipher.key = @secret
96
- cipher.iv = iv
111
+ def _decrypt(encrypted_message)
112
+ cipher = new_cipher
113
+ encrypted_data, iv, auth_tag = encrypted_message.split("--".freeze).map { |v| ::Base64.strict_decode64(v) }
114
+
115
+ # Currently the OpenSSL bindings do not raise an error if auth_tag is
116
+ # truncated, which would allow an attacker to easily forge it. See
117
+ # https://github.com/ruby/openssl/issues/63
118
+ raise InvalidMessage if aead_mode? && (auth_tag.nil? || auth_tag.bytes.length != 16)
119
+
120
+ cipher.decrypt
121
+ cipher.key = @secret
122
+ cipher.iv = iv
123
+ if aead_mode?
124
+ cipher.auth_tag = auth_tag
125
+ cipher.auth_data = ""
126
+ end
127
+
128
+ decrypted_data = cipher.update(encrypted_data)
129
+ decrypted_data << cipher.final
130
+
131
+ @serializer.load(decrypted_data)
132
+ rescue OpenSSLCipherError, TypeError, ArgumentError
133
+ raise InvalidMessage
134
+ end
97
135
 
98
- decrypted_data = cipher.update(encrypted_data)
99
- decrypted_data << cipher.final
136
+ def new_cipher
137
+ OpenSSL::Cipher.new(@cipher)
138
+ end
100
139
 
101
- @serializer.load(decrypted_data)
102
- rescue OpenSSLCipherError, TypeError, ArgumentError
103
- raise InvalidMessage
104
- end
140
+ def verifier
141
+ @verifier
142
+ end
105
143
 
106
- def new_cipher
107
- OpenSSL::Cipher.new(@cipher)
108
- end
144
+ def aead_mode?
145
+ @aead_mode ||= new_cipher.authenticated?
146
+ end
109
147
 
110
- def verifier
111
- @verifier
112
- end
148
+ def resolve_verifier
149
+ if aead_mode?
150
+ NullVerifier
151
+ else
152
+ MessageVerifier.new(@sign_secret || @secret, digest: @digest, serializer: NullSerializer)
153
+ end
154
+ end
113
155
  end
114
156
  end
@@ -1,6 +1,6 @@
1
- require 'base64'
2
- require 'active_support/core_ext/object/blank'
3
- require 'active_support/security_utils'
1
+ require "base64"
2
+ require "active_support/core_ext/object/blank"
3
+ require "active_support/security_utils"
4
4
 
5
5
  module ActiveSupport
6
6
  # +MessageVerifier+ makes it easy to generate and verify messages which are
@@ -34,9 +34,9 @@ module ActiveSupport
34
34
  class InvalidSignature < StandardError; end
35
35
 
36
36
  def initialize(secret, options = {})
37
- raise ArgumentError, 'Secret should not be nil.' unless secret
37
+ raise ArgumentError, "Secret should not be nil." unless secret
38
38
  @secret = secret
39
- @digest = options[:digest] || 'SHA1'
39
+ @digest = options[:digest] || "SHA1"
40
40
  @serializer = options[:serializer] || Marshal
41
41
  end
42
42
 
@@ -83,7 +83,7 @@ module ActiveSupport
83
83
  data = signed_message.split("--".freeze)[0]
84
84
  @serializer.load(decode(data))
85
85
  rescue ArgumentError => argument_error
86
- return if argument_error.message =~ %r{invalid base64}
86
+ return if argument_error.message.include?("invalid base64")
87
87
  raise
88
88
  end
89
89
  end
@@ -127,7 +127,7 @@ module ActiveSupport
127
127
  end
128
128
 
129
129
  def generate_digest(data)
130
- require 'openssl' unless defined?(OpenSSL)
130
+ require "openssl" unless defined?(OpenSSL)
131
131
  OpenSSL::HMAC.hexdigest(OpenSSL::Digest.const_get(@digest).new, @secret, data)
132
132
  end
133
133
  end