activesupport 5.0.0 → 6.1.0

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 (268) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +343 -590
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +5 -4
  5. data/lib/active_support/actionable_error.rb +48 -0
  6. data/lib/active_support/all.rb +5 -3
  7. data/lib/active_support/array_inquirer.rb +11 -5
  8. data/lib/active_support/backtrace_cleaner.rb +33 -5
  9. data/lib/active_support/benchmarkable.rb +5 -3
  10. data/lib/active_support/builder.rb +3 -1
  11. data/lib/active_support/cache/file_store.rb +45 -53
  12. data/lib/active_support/cache/mem_cache_store.rb +81 -79
  13. data/lib/active_support/cache/memory_store.rb +69 -41
  14. data/lib/active_support/cache/null_store.rb +11 -4
  15. data/lib/active_support/cache/redis_cache_store.rb +493 -0
  16. data/lib/active_support/cache/strategy/local_cache.rb +74 -37
  17. data/lib/active_support/cache/strategy/local_cache_middleware.rb +10 -9
  18. data/lib/active_support/cache.rb +332 -161
  19. data/lib/active_support/callbacks.rb +657 -586
  20. data/lib/active_support/concern.rb +79 -6
  21. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +35 -0
  22. data/lib/active_support/concurrency/share_lock.rb +59 -19
  23. data/lib/active_support/configurable.rb +15 -17
  24. data/lib/active_support/configuration_file.rb +46 -0
  25. data/lib/active_support/core_ext/array/access.rb +21 -7
  26. data/lib/active_support/core_ext/array/conversions.rb +20 -18
  27. data/lib/active_support/core_ext/array/extract.rb +21 -0
  28. data/lib/active_support/core_ext/array/extract_options.rb +2 -0
  29. data/lib/active_support/core_ext/array/grouping.rb +3 -1
  30. data/lib/active_support/core_ext/array/inquiry.rb +3 -1
  31. data/lib/active_support/core_ext/array/wrap.rb +2 -0
  32. data/lib/active_support/core_ext/array.rb +9 -7
  33. data/lib/active_support/core_ext/benchmark.rb +5 -3
  34. data/lib/active_support/core_ext/big_decimal/conversions.rb +6 -6
  35. data/lib/active_support/core_ext/big_decimal.rb +3 -1
  36. data/lib/active_support/core_ext/class/attribute.rb +52 -49
  37. data/lib/active_support/core_ext/class/attribute_accessors.rb +3 -1
  38. data/lib/active_support/core_ext/class/subclasses.rb +18 -26
  39. data/lib/active_support/core_ext/class.rb +4 -2
  40. data/lib/active_support/core_ext/date/acts_like.rb +3 -1
  41. data/lib/active_support/core_ext/date/blank.rb +3 -1
  42. data/lib/active_support/core_ext/date/calculations.rb +16 -13
  43. data/lib/active_support/core_ext/date/conversions.rb +23 -21
  44. data/lib/active_support/core_ext/date/zones.rb +4 -2
  45. data/lib/active_support/core_ext/date.rb +7 -5
  46. data/lib/active_support/core_ext/date_and_time/calculations.rb +82 -53
  47. data/lib/active_support/core_ext/date_and_time/compatibility.rb +18 -5
  48. data/lib/active_support/core_ext/date_and_time/zones.rb +9 -9
  49. data/lib/active_support/core_ext/date_time/acts_like.rb +4 -2
  50. data/lib/active_support/core_ext/date_time/blank.rb +3 -1
  51. data/lib/active_support/core_ext/date_time/calculations.rb +23 -11
  52. data/lib/active_support/core_ext/date_time/compatibility.rb +15 -2
  53. data/lib/active_support/core_ext/date_time/conversions.rb +14 -13
  54. data/lib/active_support/core_ext/date_time.rb +7 -5
  55. data/lib/active_support/core_ext/digest/uuid.rb +7 -5
  56. data/lib/active_support/core_ext/digest.rb +3 -0
  57. data/lib/active_support/core_ext/enumerable.rb +165 -29
  58. data/lib/active_support/core_ext/file/atomic.rb +7 -5
  59. data/lib/active_support/core_ext/file.rb +3 -1
  60. data/lib/active_support/core_ext/hash/conversions.rb +40 -39
  61. data/lib/active_support/core_ext/hash/deep_merge.rb +8 -12
  62. data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
  63. data/lib/active_support/core_ext/hash/except.rb +4 -2
  64. data/lib/active_support/core_ext/hash/indifferent_access.rb +3 -2
  65. data/lib/active_support/core_ext/hash/keys.rb +9 -36
  66. data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
  67. data/lib/active_support/core_ext/hash/slice.rb +8 -29
  68. data/lib/active_support/core_ext/hash.rb +10 -9
  69. data/lib/active_support/core_ext/integer/inflections.rb +3 -1
  70. data/lib/active_support/core_ext/integer/multiple.rb +3 -1
  71. data/lib/active_support/core_ext/integer/time.rb +11 -18
  72. data/lib/active_support/core_ext/integer.rb +5 -3
  73. data/lib/active_support/core_ext/kernel/concern.rb +3 -1
  74. data/lib/active_support/core_ext/kernel/reporting.rb +3 -1
  75. data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
  76. data/lib/active_support/core_ext/kernel.rb +5 -4
  77. data/lib/active_support/core_ext/load_error.rb +2 -23
  78. data/lib/active_support/core_ext/marshal.rb +6 -2
  79. data/lib/active_support/core_ext/module/aliasing.rb +5 -48
  80. data/lib/active_support/core_ext/module/anonymous.rb +2 -0
  81. data/lib/active_support/core_ext/module/attr_internal.rb +7 -5
  82. data/lib/active_support/core_ext/module/attribute_accessors.rb +53 -59
  83. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +31 -24
  84. data/lib/active_support/core_ext/module/concerning.rb +16 -11
  85. data/lib/active_support/core_ext/module/delegation.rb +159 -44
  86. data/lib/active_support/core_ext/module/deprecation.rb +2 -0
  87. data/lib/active_support/core_ext/module/introspection.rb +23 -26
  88. data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
  89. data/lib/active_support/core_ext/module/remove_method.rb +5 -23
  90. data/lib/active_support/core_ext/module.rb +13 -12
  91. data/lib/active_support/core_ext/name_error.rb +36 -2
  92. data/lib/active_support/core_ext/numeric/bytes.rb +2 -0
  93. data/lib/active_support/core_ext/numeric/conversions.rb +129 -134
  94. data/lib/active_support/core_ext/numeric/time.rb +18 -26
  95. data/lib/active_support/core_ext/numeric.rb +5 -4
  96. data/lib/active_support/core_ext/object/acts_like.rb +12 -1
  97. data/lib/active_support/core_ext/object/blank.rb +14 -2
  98. data/lib/active_support/core_ext/object/conversions.rb +6 -4
  99. data/lib/active_support/core_ext/object/deep_dup.rb +4 -2
  100. data/lib/active_support/core_ext/object/duplicable.rb +13 -62
  101. data/lib/active_support/core_ext/object/inclusion.rb +3 -1
  102. data/lib/active_support/core_ext/object/instance_variables.rb +2 -0
  103. data/lib/active_support/core_ext/object/json.rb +42 -15
  104. data/lib/active_support/core_ext/object/to_param.rb +3 -1
  105. data/lib/active_support/core_ext/object/to_query.rb +10 -5
  106. data/lib/active_support/core_ext/object/try.rb +20 -8
  107. data/lib/active_support/core_ext/object/with_options.rb +15 -2
  108. data/lib/active_support/core_ext/object.rb +14 -12
  109. data/lib/active_support/core_ext/range/compare_range.rb +82 -0
  110. data/lib/active_support/core_ext/range/conversions.rb +35 -25
  111. data/lib/active_support/core_ext/range/each.rb +5 -2
  112. data/lib/active_support/core_ext/range/include_time_with_zone.rb +28 -0
  113. data/lib/active_support/core_ext/range/overlaps.rb +2 -0
  114. data/lib/active_support/core_ext/range.rb +7 -4
  115. data/lib/active_support/core_ext/regexp.rb +10 -1
  116. data/lib/active_support/core_ext/securerandom.rb +28 -6
  117. data/lib/active_support/core_ext/string/access.rb +9 -18
  118. data/lib/active_support/core_ext/string/behavior.rb +2 -0
  119. data/lib/active_support/core_ext/string/conversions.rb +5 -2
  120. data/lib/active_support/core_ext/string/exclude.rb +2 -0
  121. data/lib/active_support/core_ext/string/filters.rb +47 -4
  122. data/lib/active_support/core_ext/string/indent.rb +6 -4
  123. data/lib/active_support/core_ext/string/inflections.rb +78 -29
  124. data/lib/active_support/core_ext/string/inquiry.rb +4 -1
  125. data/lib/active_support/core_ext/string/multibyte.rb +10 -5
  126. data/lib/active_support/core_ext/string/output_safety.rb +86 -31
  127. data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -2
  128. data/lib/active_support/core_ext/string/strip.rb +5 -1
  129. data/lib/active_support/core_ext/string/zones.rb +4 -2
  130. data/lib/active_support/core_ext/string.rb +15 -13
  131. data/lib/active_support/core_ext/symbol/starts_ends_with.rb +14 -0
  132. data/lib/active_support/core_ext/symbol.rb +3 -0
  133. data/lib/active_support/core_ext/time/acts_like.rb +3 -1
  134. data/lib/active_support/core_ext/time/calculations.rb +117 -45
  135. data/lib/active_support/core_ext/time/compatibility.rb +13 -2
  136. data/lib/active_support/core_ext/time/conversions.rb +18 -12
  137. data/lib/active_support/core_ext/time/zones.rb +9 -7
  138. data/lib/active_support/core_ext/time.rb +7 -5
  139. data/lib/active_support/core_ext/uri.rb +12 -7
  140. data/lib/active_support/core_ext.rb +3 -2
  141. data/lib/active_support/current_attributes/test_helper.rb +13 -0
  142. data/lib/active_support/current_attributes.rb +208 -0
  143. data/lib/active_support/dependencies/autoload.rb +2 -0
  144. data/lib/active_support/dependencies/interlock.rb +7 -1
  145. data/lib/active_support/dependencies/zeitwerk_integration.rb +117 -0
  146. data/lib/active_support/dependencies.rb +172 -98
  147. data/lib/active_support/deprecation/behaviors.rb +45 -13
  148. data/lib/active_support/deprecation/constant_accessor.rb +52 -0
  149. data/lib/active_support/deprecation/disallowed.rb +56 -0
  150. data/lib/active_support/deprecation/instance_delegator.rb +16 -2
  151. data/lib/active_support/deprecation/method_wrappers.rb +32 -17
  152. data/lib/active_support/deprecation/proxy_wrappers.rb +35 -7
  153. data/lib/active_support/deprecation/reporting.rb +61 -16
  154. data/lib/active_support/deprecation.rb +17 -9
  155. data/lib/active_support/descendants_tracker.rb +61 -9
  156. data/lib/active_support/digest.rb +20 -0
  157. data/lib/active_support/duration/iso8601_parser.rb +67 -66
  158. data/lib/active_support/duration/iso8601_serializer.rb +25 -17
  159. data/lib/active_support/duration.rb +349 -46
  160. data/lib/active_support/encrypted_configuration.rb +45 -0
  161. data/lib/active_support/encrypted_file.rb +117 -0
  162. data/lib/active_support/environment_inquirer.rb +20 -0
  163. data/lib/active_support/evented_file_update_checker.rb +88 -112
  164. data/lib/active_support/execution_wrapper.rb +25 -13
  165. data/lib/active_support/executor.rb +3 -1
  166. data/lib/active_support/file_update_checker.rb +56 -51
  167. data/lib/active_support/fork_tracker.rb +62 -0
  168. data/lib/active_support/gem_version.rb +4 -2
  169. data/lib/active_support/gzip.rb +7 -5
  170. data/lib/active_support/hash_with_indifferent_access.rb +153 -49
  171. data/lib/active_support/i18n.rb +9 -6
  172. data/lib/active_support/i18n_railtie.rb +30 -20
  173. data/lib/active_support/inflections.rb +13 -11
  174. data/lib/active_support/inflector/inflections.rb +28 -15
  175. data/lib/active_support/inflector/methods.rb +120 -109
  176. data/lib/active_support/inflector/transliterate.rb +60 -25
  177. data/lib/active_support/inflector.rb +7 -5
  178. data/lib/active_support/json/decoding.rb +30 -29
  179. data/lib/active_support/json/encoding.rb +22 -11
  180. data/lib/active_support/json.rb +4 -2
  181. data/lib/active_support/key_generator.rb +6 -36
  182. data/lib/active_support/lazy_load_hooks.rb +53 -20
  183. data/lib/active_support/locale/en.rb +33 -0
  184. data/lib/active_support/locale/en.yml +7 -3
  185. data/lib/active_support/log_subscriber/test_helper.rb +11 -9
  186. data/lib/active_support/log_subscriber.rb +51 -18
  187. data/lib/active_support/logger.rb +9 -22
  188. data/lib/active_support/logger_silence.rb +14 -21
  189. data/lib/active_support/logger_thread_safe_level.rb +55 -8
  190. data/lib/active_support/message_encryptor.rb +170 -53
  191. data/lib/active_support/message_verifier.rb +91 -20
  192. data/lib/active_support/messages/metadata.rb +80 -0
  193. data/lib/active_support/messages/rotation_configuration.rb +23 -0
  194. data/lib/active_support/messages/rotator.rb +57 -0
  195. data/lib/active_support/multibyte/chars.rb +24 -78
  196. data/lib/active_support/multibyte/unicode.rb +21 -352
  197. data/lib/active_support/multibyte.rb +4 -2
  198. data/lib/active_support/notifications/fanout.rb +121 -19
  199. data/lib/active_support/notifications/instrumenter.rb +78 -14
  200. data/lib/active_support/notifications.rb +80 -12
  201. data/lib/active_support/number_helper/number_converter.rb +17 -16
  202. data/lib/active_support/number_helper/number_to_currency_converter.rb +6 -9
  203. data/lib/active_support/number_helper/number_to_delimited_converter.rb +5 -3
  204. data/lib/active_support/number_helper/number_to_human_converter.rb +13 -12
  205. data/lib/active_support/number_helper/number_to_human_size_converter.rb +11 -13
  206. data/lib/active_support/number_helper/number_to_percentage_converter.rb +5 -1
  207. data/lib/active_support/number_helper/number_to_phone_converter.rb +5 -4
  208. data/lib/active_support/number_helper/number_to_rounded_converter.rb +18 -55
  209. data/lib/active_support/number_helper/rounding_helper.rb +50 -0
  210. data/lib/active_support/number_helper.rb +45 -16
  211. data/lib/active_support/option_merger.rb +25 -4
  212. data/lib/active_support/ordered_hash.rb +6 -4
  213. data/lib/active_support/ordered_options.rb +23 -9
  214. data/lib/active_support/parameter_filter.rb +133 -0
  215. data/lib/active_support/per_thread_registry.rb +7 -5
  216. data/lib/active_support/proxy_object.rb +2 -0
  217. data/lib/active_support/rails.rb +8 -9
  218. data/lib/active_support/railtie.rb +62 -11
  219. data/lib/active_support/reloader.rb +12 -11
  220. data/lib/active_support/rescuable.rb +20 -11
  221. data/lib/active_support/secure_compare_rotator.rb +51 -0
  222. data/lib/active_support/security_utils.rb +26 -15
  223. data/lib/active_support/string_inquirer.rb +12 -3
  224. data/lib/active_support/subscriber.rb +77 -23
  225. data/lib/active_support/tagged_logging.rb +52 -17
  226. data/lib/active_support/test_case.rb +106 -29
  227. data/lib/active_support/testing/assertions.rb +144 -8
  228. data/lib/active_support/testing/autorun.rb +5 -10
  229. data/lib/active_support/testing/constant_lookup.rb +2 -1
  230. data/lib/active_support/testing/declarative.rb +3 -1
  231. data/lib/active_support/testing/deprecation.rb +4 -2
  232. data/lib/active_support/testing/file_fixtures.rb +4 -0
  233. data/lib/active_support/testing/isolation.rb +19 -24
  234. data/lib/active_support/testing/method_call_assertions.rb +31 -2
  235. data/lib/active_support/testing/parallelization/server.rb +78 -0
  236. data/lib/active_support/testing/parallelization/worker.rb +100 -0
  237. data/lib/active_support/testing/parallelization.rb +51 -0
  238. data/lib/active_support/testing/setup_and_teardown.rb +13 -8
  239. data/lib/active_support/testing/stream.rb +30 -29
  240. data/lib/active_support/testing/tagged_logging.rb +3 -1
  241. data/lib/active_support/testing/time_helpers.rb +125 -24
  242. data/lib/active_support/time.rb +14 -12
  243. data/lib/active_support/time_with_zone.rb +142 -55
  244. data/lib/active_support/values/time_zone.rb +160 -53
  245. data/lib/active_support/version.rb +3 -1
  246. data/lib/active_support/xml_mini/jdom.rb +115 -114
  247. data/lib/active_support/xml_mini/libxml.rb +15 -14
  248. data/lib/active_support/xml_mini/libxmlsax.rb +16 -18
  249. data/lib/active_support/xml_mini/nokogiri.rb +13 -13
  250. data/lib/active_support/xml_mini/nokogirisax.rb +15 -16
  251. data/lib/active_support/xml_mini/rexml.rb +18 -9
  252. data/lib/active_support/xml_mini.rb +44 -42
  253. data/lib/active_support.rb +19 -10
  254. metadata +79 -37
  255. data/lib/active_support/concurrency/latch.rb +0 -19
  256. data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -7
  257. data/lib/active_support/core_ext/hash/compact.rb +0 -20
  258. data/lib/active_support/core_ext/hash/transform_values.rb +0 -29
  259. data/lib/active_support/core_ext/kernel/agnostics.rb +0 -11
  260. data/lib/active_support/core_ext/kernel/debugger.rb +0 -3
  261. data/lib/active_support/core_ext/module/method_transplanting.rb +0 -3
  262. data/lib/active_support/core_ext/module/qualified_const.rb +0 -70
  263. data/lib/active_support/core_ext/module/reachable.rb +0 -8
  264. data/lib/active_support/core_ext/numeric/inquiry.rb +0 -26
  265. data/lib/active_support/core_ext/range/include_range.rb +0 -23
  266. data/lib/active_support/core_ext/struct.rb +0 -3
  267. data/lib/active_support/core_ext/time/marshal.rb +0 -3
  268. data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -0,0 +1,133 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/object/duplicable"
4
+
5
+ module ActiveSupport
6
+ # +ParameterFilter+ allows you to specify keys for sensitive data from
7
+ # hash-like object and replace corresponding value. Filtering only certain
8
+ # sub-keys from a hash is possible by using the dot notation:
9
+ # 'credit_card.number'. If a proc is given, each key and value of a hash and
10
+ # all sub-hashes are passed to it, where the value or the key can be replaced
11
+ # using String#replace or similar methods.
12
+ #
13
+ # ActiveSupport::ParameterFilter.new([:password])
14
+ # => replaces the value to all keys matching /password/i with "[FILTERED]"
15
+ #
16
+ # ActiveSupport::ParameterFilter.new([:foo, "bar"])
17
+ # => replaces the value to all keys matching /foo|bar/i with "[FILTERED]"
18
+ #
19
+ # ActiveSupport::ParameterFilter.new(["credit_card.code"])
20
+ # => replaces { credit_card: {code: "xxxx"} } with "[FILTERED]", does not
21
+ # change { file: { code: "xxxx"} }
22
+ #
23
+ # ActiveSupport::ParameterFilter.new([-> (k, v) do
24
+ # v.reverse! if /secret/i.match?(k)
25
+ # end])
26
+ # => reverses the value to all keys matching /secret/i
27
+ class ParameterFilter
28
+ FILTERED = "[FILTERED]" # :nodoc:
29
+
30
+ # Create instance with given filters. Supported type of filters are +String+, +Regexp+, and +Proc+.
31
+ # Other types of filters are treated as +String+ using +to_s+.
32
+ # For +Proc+ filters, key, value, and optional original hash is passed to block arguments.
33
+ #
34
+ # ==== Options
35
+ #
36
+ # * <tt>:mask</tt> - A replaced object when filtered. Defaults to +"[FILTERED]"+
37
+ def initialize(filters = [], mask: FILTERED)
38
+ @filters = filters
39
+ @mask = mask
40
+ end
41
+
42
+ # Mask value of +params+ if key matches one of filters.
43
+ def filter(params)
44
+ compiled_filter.call(params)
45
+ end
46
+
47
+ # Returns filtered value for given key. For +Proc+ filters, third block argument is not populated.
48
+ def filter_param(key, value)
49
+ @filters.empty? ? value : compiled_filter.value_for_key(key, value)
50
+ end
51
+
52
+ private
53
+ def compiled_filter
54
+ @compiled_filter ||= CompiledFilter.compile(@filters, mask: @mask)
55
+ end
56
+
57
+ class CompiledFilter # :nodoc:
58
+ def self.compile(filters, mask:)
59
+ return lambda { |params| params.dup } if filters.empty?
60
+
61
+ strings, regexps, blocks, deep_regexps, deep_strings = [], [], [], nil, nil
62
+
63
+ filters.each do |item|
64
+ case item
65
+ when Proc
66
+ blocks << item
67
+ when Regexp
68
+ if item.to_s.include?("\\.")
69
+ (deep_regexps ||= []) << item
70
+ else
71
+ regexps << item
72
+ end
73
+ else
74
+ s = Regexp.escape(item.to_s)
75
+ if s.include?("\\.")
76
+ (deep_strings ||= []) << s
77
+ else
78
+ strings << s
79
+ end
80
+ end
81
+ end
82
+
83
+ regexps << Regexp.new(strings.join("|"), true) unless strings.empty?
84
+ (deep_regexps ||= []) << Regexp.new(deep_strings.join("|"), true) if deep_strings&.any?
85
+
86
+ new regexps, deep_regexps, blocks, mask: mask
87
+ end
88
+
89
+ attr_reader :regexps, :deep_regexps, :blocks
90
+
91
+ def initialize(regexps, deep_regexps, blocks, mask:)
92
+ @regexps = regexps
93
+ @deep_regexps = deep_regexps&.any? ? deep_regexps : nil
94
+ @blocks = blocks
95
+ @mask = mask
96
+ end
97
+
98
+ def call(params, parents = [], original_params = params)
99
+ filtered_params = params.class.new
100
+
101
+ params.each do |key, value|
102
+ filtered_params[key] = value_for_key(key, value, parents, original_params)
103
+ end
104
+
105
+ filtered_params
106
+ end
107
+
108
+ def value_for_key(key, value, parents = [], original_params = nil)
109
+ parents.push(key) if deep_regexps
110
+ if regexps.any? { |r| r.match?(key.to_s) }
111
+ value = @mask
112
+ elsif deep_regexps && (joined = parents.join(".")) && deep_regexps.any? { |r| r.match?(joined) }
113
+ value = @mask
114
+ elsif value.is_a?(Hash)
115
+ value = call(value, parents, original_params)
116
+ elsif value.is_a?(Array)
117
+ # If we don't pop the current parent it will be duplicated as we
118
+ # process each array value.
119
+ parents.pop if deep_regexps
120
+ value = value.map { |v| value_for_key(key, v, parents, original_params) }
121
+ # Restore the parent stack after processing the array.
122
+ parents.push(key) if deep_regexps
123
+ elsif blocks.any?
124
+ key = key.dup if key.duplicable?
125
+ value = value.dup if value.duplicable?
126
+ blocks.each { |b| b.arity == 2 ? b.call(key, value) : b.call(key, value, original_params) }
127
+ end
128
+ parents.pop if deep_regexps
129
+ value
130
+ end
131
+ end
132
+ end
133
+ end
@@ -1,7 +1,9 @@
1
- require 'active_support/core_ext/module/delegation'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/module/delegation"
2
4
 
3
5
  module ActiveSupport
4
- # NOTE: This approach has been deprecated for end-user code in favor of thread_mattr_accessor and friends.
6
+ # NOTE: This approach has been deprecated for end-user code in favor of {thread_mattr_accessor}[rdoc-ref:Module#thread_mattr_accessor] and friends.
5
7
  # Please use that approach instead.
6
8
  #
7
9
  # This module is used to encapsulate access to thread local variables.
@@ -38,15 +40,15 @@ module ActiveSupport
38
40
  # If the class has an initializer, it must accept no arguments.
39
41
  module PerThreadRegistry
40
42
  def self.extended(object)
41
- object.instance_variable_set '@per_thread_registry_key', object.name.freeze
43
+ object.instance_variable_set :@per_thread_registry_key, object.name.freeze
42
44
  end
43
45
 
44
46
  def instance
45
47
  Thread.current[@per_thread_registry_key] ||= new
46
48
  end
47
49
 
48
- protected
49
- def method_missing(name, *args, &block) # :nodoc:
50
+ private
51
+ def method_missing(name, *args, &block)
50
52
  # Caches the method definition as a singleton method of the receiver.
51
53
  #
52
54
  # By letting #delegate handle it, we avoid an enclosure that'll capture args.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveSupport
2
4
  # A class with no predefined methods that behaves similarly to Builder's
3
5
  # BlankSlate. Used for proxy classes.
@@ -1,4 +1,6 @@
1
- # This is private interface.
1
+ # frozen_string_literal: true
2
+
3
+ # This is a private interface.
2
4
  #
3
5
  # Rails components cherry pick from Active Support as needed, but there are a
4
6
  # few features that are used for sure in some way or another and it is not worth
@@ -9,19 +11,16 @@
9
11
  # Rails and can change anytime.
10
12
 
11
13
  # Defines Object#blank? and Object#present?.
12
- require 'active_support/core_ext/object/blank'
13
-
14
- # Rails own autoload, eager_load, etc.
15
- require 'active_support/dependencies/autoload'
14
+ require "active_support/core_ext/object/blank"
16
15
 
17
16
  # Support for ClassMethods and the included macro.
18
- require 'active_support/concern'
17
+ require "active_support/concern"
19
18
 
20
19
  # Defines Class#class_attribute.
21
- require 'active_support/core_ext/class/attribute'
20
+ require "active_support/core_ext/class/attribute"
22
21
 
23
22
  # Defines Module#delegate.
24
- require 'active_support/core_ext/module/delegation'
23
+ require "active_support/core_ext/module/delegation"
25
24
 
26
25
  # Defines ActiveSupport::Deprecation.
27
- require 'active_support/deprecation'
26
+ require "active_support/deprecation"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support"
2
4
  require "active_support/i18n_railtie"
3
5
 
@@ -7,10 +9,38 @@ module ActiveSupport
7
9
 
8
10
  config.eager_load_namespaces << ActiveSupport
9
11
 
12
+ initializer "active_support.set_authenticated_message_encryption" do |app|
13
+ config.after_initialize do
14
+ unless app.config.active_support.use_authenticated_message_encryption.nil?
15
+ ActiveSupport::MessageEncryptor.use_authenticated_message_encryption =
16
+ app.config.active_support.use_authenticated_message_encryption
17
+ end
18
+ end
19
+ end
20
+
21
+ initializer "active_support.reset_all_current_attributes_instances" do |app|
22
+ app.reloader.before_class_unload { ActiveSupport::CurrentAttributes.clear_all }
23
+ app.executor.to_run { ActiveSupport::CurrentAttributes.reset_all }
24
+ app.executor.to_complete { ActiveSupport::CurrentAttributes.reset_all }
25
+
26
+ ActiveSupport.on_load(:active_support_test_case) do
27
+ require "active_support/current_attributes/test_helper"
28
+ include ActiveSupport::CurrentAttributes::TestHelper
29
+ end
30
+ end
31
+
10
32
  initializer "active_support.deprecation_behavior" do |app|
11
33
  if deprecation = app.config.active_support.deprecation
12
34
  ActiveSupport::Deprecation.behavior = deprecation
13
35
  end
36
+
37
+ if disallowed_deprecation = app.config.active_support.disallowed_deprecation
38
+ ActiveSupport::Deprecation.disallowed_behavior = disallowed_deprecation
39
+ end
40
+
41
+ if disallowed_warnings = app.config.active_support.disallowed_deprecation_warnings
42
+ ActiveSupport::Deprecation.disallowed_warnings = disallowed_warnings
43
+ end
14
44
  end
15
45
 
16
46
  # Sets the default value for Time.zone
@@ -21,30 +51,51 @@ module ActiveSupport
21
51
  rescue TZInfo::DataSourceNotFound => e
22
52
  raise e.exception "tzinfo-data is not present. Please add gem 'tzinfo-data' to your Gemfile and run bundle install"
23
53
  end
24
- require 'active_support/core_ext/time/zones'
25
- zone_default = Time.find_zone!(app.config.time_zone)
26
-
27
- unless zone_default
28
- raise 'Value assigned to config.time_zone not recognized. ' \
29
- 'Run "rake time:zones:all" for a time zone names list.'
30
- end
31
-
32
- Time.zone_default = zone_default
54
+ require "active_support/core_ext/time/zones"
55
+ Time.zone_default = Time.find_zone!(app.config.time_zone)
33
56
  end
34
57
 
35
58
  # Sets the default week start
36
59
  # If assigned value is not a valid day symbol (e.g. :sunday, :monday, ...), an exception will be raised.
37
60
  initializer "active_support.initialize_beginning_of_week" do |app|
38
- require 'active_support/core_ext/date/calculations'
61
+ require "active_support/core_ext/date/calculations"
39
62
  beginning_of_week_default = Date.find_beginning_of_week!(app.config.beginning_of_week)
40
63
 
41
64
  Date.beginning_of_week_default = beginning_of_week_default
42
65
  end
43
66
 
67
+ initializer "active_support.require_master_key" do |app|
68
+ if app.config.respond_to?(:require_master_key) && app.config.require_master_key
69
+ begin
70
+ app.credentials.key
71
+ rescue ActiveSupport::EncryptedFile::MissingKeyError => error
72
+ $stderr.puts error.message
73
+ exit 1
74
+ end
75
+ end
76
+ end
77
+
44
78
  initializer "active_support.set_configs" do |app|
45
79
  app.config.active_support.each do |k, v|
46
80
  k = "#{k}="
47
- ActiveSupport.send(k, v) if ActiveSupport.respond_to? k
81
+ ActiveSupport.public_send(k, v) if ActiveSupport.respond_to? k
82
+ end
83
+ end
84
+
85
+ initializer "active_support.set_hash_digest_class" do |app|
86
+ config.after_initialize do
87
+ if app.config.active_support.use_sha1_digests
88
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
89
+ config.active_support.use_sha1_digests is deprecated and will
90
+ be removed from Rails 6.2. Use
91
+ config.active_support.hash_digest_class = ::Digest::SHA1 instead.
92
+ MSG
93
+ ActiveSupport::Digest.hash_digest_class = ::Digest::SHA1
94
+ end
95
+
96
+ if klass = app.config.active_support.hash_digest_class
97
+ ActiveSupport::Digest.hash_digest_class = klass
98
+ end
48
99
  end
49
100
  end
50
101
  end
@@ -1,4 +1,7 @@
1
- require 'active_support/execution_wrapper'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/execution_wrapper"
4
+ require "active_support/executor"
2
5
 
3
6
  module ActiveSupport
4
7
  #--
@@ -26,14 +29,17 @@ module ActiveSupport
26
29
 
27
30
  define_callbacks :class_unload
28
31
 
32
+ # Registers a callback that will run once at application startup and every time the code is reloaded.
29
33
  def self.to_prepare(*args, &block)
30
34
  set_callback(:prepare, *args, &block)
31
35
  end
32
36
 
37
+ # Registers a callback that will run immediately before the classes are unloaded.
33
38
  def self.before_class_unload(*args, &block)
34
39
  set_callback(:class_unload, *args, &block)
35
40
  end
36
41
 
42
+ # Registers a callback that will run immediately after the classes are unloaded.
37
43
  def self.after_class_unload(*args, &block)
38
44
  set_callback(:class_unload, :after, *args, &block)
39
45
  end
@@ -44,11 +50,9 @@ module ActiveSupport
44
50
  def self.reload!
45
51
  executor.wrap do
46
52
  new.tap do |instance|
47
- begin
48
- instance.run!
49
- ensure
50
- instance.complete!
51
- end
53
+ instance.run!
54
+ ensure
55
+ instance.complete!
52
56
  end
53
57
  end
54
58
  prepare!
@@ -69,11 +73,8 @@ module ActiveSupport
69
73
  end
70
74
  end
71
75
 
72
- class_attribute :executor
73
- class_attribute :check
74
-
75
- self.executor = Executor
76
- self.check = lambda { false }
76
+ class_attribute :executor, default: Executor
77
+ class_attribute :check, default: lambda { false }
77
78
 
78
79
  def self.check! # :nodoc:
79
80
  @should_reload ||= check.call
@@ -1,6 +1,8 @@
1
- require 'active_support/concern'
2
- require 'active_support/core_ext/class/attribute'
3
- require 'active_support/core_ext/string/inflections'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/concern"
4
+ require "active_support/core_ext/class/attribute"
5
+ require "active_support/core_ext/string/inflections"
4
6
 
5
7
  module ActiveSupport
6
8
  # Rescuable module adds support for easier exception handling.
@@ -8,8 +10,7 @@ module ActiveSupport
8
10
  extend Concern
9
11
 
10
12
  included do
11
- class_attribute :rescue_handlers
12
- self.rescue_handlers = []
13
+ class_attribute :rescue_handlers, default: []
13
14
  end
14
15
 
15
16
  module ClassMethods
@@ -36,7 +37,7 @@ module ActiveSupport
36
37
  # render xml: exception, status: 500
37
38
  # end
38
39
  #
39
- # protected
40
+ # private
40
41
  # def deny_access
41
42
  # ...
42
43
  # end
@@ -52,7 +53,7 @@ module ActiveSupport
52
53
  if block_given?
53
54
  with = block
54
55
  else
55
- raise ArgumentError, 'Need a handler. Pass the with: keyword argument or provide a block.'
56
+ raise ArgumentError, "Need a handler. Pass the with: keyword argument or provide a block."
56
57
  end
57
58
  end
58
59
 
@@ -74,7 +75,7 @@ module ActiveSupport
74
75
  #
75
76
  # If no handler matches the exception, check for a handler matching the
76
77
  # (optional) exception.cause. If no handler matches the exception or its
77
- # cause, this returns nil so you can deal with unhandled exceptions.
78
+ # cause, this returns +nil+, so you can deal with unhandled exceptions.
78
79
  # Be sure to re-raise unhandled exceptions if this is what you expect.
79
80
  #
80
81
  # begin
@@ -83,11 +84,19 @@ module ActiveSupport
83
84
  # rescue_with_handler(exception) || raise
84
85
  # end
85
86
  #
86
- # Returns the exception if it was handled and nil if it was not.
87
- def rescue_with_handler(exception, object: self)
87
+ # Returns the exception if it was handled and +nil+ if it was not.
88
+ def rescue_with_handler(exception, object: self, visited_exceptions: [])
89
+ visited_exceptions << exception
90
+
88
91
  if handler = handler_for_rescue(exception, object: object)
89
92
  handler.call exception
90
93
  exception
94
+ elsif exception
95
+ if visited_exceptions.include?(exception.cause)
96
+ nil
97
+ else
98
+ rescue_with_handler(exception.cause, object: object, visited_exceptions: visited_exceptions)
99
+ end
91
100
  end
92
101
  end
93
102
 
@@ -121,7 +130,7 @@ module ActiveSupport
121
130
  end
122
131
  end
123
132
 
124
- handler || find_rescue_handler(exception.cause)
133
+ handler
125
134
  end
126
135
  end
127
136
 
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/security_utils"
4
+ require "active_support/messages/rotator"
5
+
6
+ module ActiveSupport
7
+ # The ActiveSupport::SecureCompareRotator is a wrapper around +ActiveSupport::SecurityUtils.secure_compare+
8
+ # and allows you to rotate a previously defined value to a new one.
9
+ #
10
+ # It can be used as follow:
11
+ #
12
+ # rotator = ActiveSupport::SecureCompareRotator.new('new_production_value')
13
+ # rotator.rotate('previous_production_value')
14
+ # rotator.secure_compare!('previous_production_value')
15
+ #
16
+ # One real use case example would be to rotate a basic auth credentials:
17
+ #
18
+ # class MyController < ApplicationController
19
+ # def authenticate_request
20
+ # rotator = ActiveSupport::SecureComparerotator.new('new_password')
21
+ # rotator.rotate('old_password')
22
+ #
23
+ # authenticate_or_request_with_http_basic do |username, password|
24
+ # rotator.secure_compare!(password)
25
+ # rescue ActiveSupport::SecureCompareRotator::InvalidMatch
26
+ # false
27
+ # end
28
+ # end
29
+ # end
30
+ class SecureCompareRotator
31
+ include SecurityUtils
32
+ prepend Messages::Rotator
33
+
34
+ InvalidMatch = Class.new(StandardError)
35
+
36
+ def initialize(value, **_options)
37
+ @value = value
38
+ end
39
+
40
+ def secure_compare!(other_value, on_rotation: @on_rotation)
41
+ secure_compare(@value, other_value) ||
42
+ run_rotations(on_rotation) { |wrapper| wrapper.secure_compare!(other_value) } ||
43
+ raise(InvalidMatch)
44
+ end
45
+
46
+ private
47
+ def build_rotation(previous_value, _options)
48
+ self.class.new(previous_value)
49
+ end
50
+ end
51
+ end
@@ -1,27 +1,38 @@
1
- require 'digest'
1
+ # frozen_string_literal: true
2
2
 
3
3
  module ActiveSupport
4
4
  module SecurityUtils
5
- # Constant time string comparison.
5
+ # Constant time string comparison, for fixed length strings.
6
6
  #
7
7
  # The values compared should be of fixed length, such as strings
8
- # that have already been processed by HMAC. This should not be used
9
- # on variable length plaintext strings because it could leak length info
10
- # via timing attacks.
11
- def secure_compare(a, b)
12
- return false unless a.bytesize == b.bytesize
8
+ # that have already been processed by HMAC. Raises in case of length mismatch.
9
+
10
+ if defined?(OpenSSL.fixed_length_secure_compare)
11
+ def fixed_length_secure_compare(a, b)
12
+ OpenSSL.fixed_length_secure_compare(a, b)
13
+ end
14
+ else
15
+ def fixed_length_secure_compare(a, b)
16
+ raise ArgumentError, "string length mismatch." unless a.bytesize == b.bytesize
13
17
 
14
- l = a.unpack "C#{a.bytesize}"
18
+ l = a.unpack "C#{a.bytesize}"
15
19
 
16
- res = 0
17
- b.each_byte { |byte| res |= byte ^ l.shift }
18
- res == 0
20
+ res = 0
21
+ b.each_byte { |byte| res |= byte ^ l.shift }
22
+ res == 0
23
+ end
19
24
  end
20
- module_function :secure_compare
25
+ module_function :fixed_length_secure_compare
21
26
 
22
- def variable_size_secure_compare(a, b) # :nodoc:
23
- secure_compare(::Digest::SHA256.hexdigest(a), ::Digest::SHA256.hexdigest(b))
27
+ # Secure string comparison for strings of variable length.
28
+ #
29
+ # While a timing attack would not be able to discern the content of
30
+ # a secret compared via secure_compare, it is possible to determine
31
+ # the secret length. This should be considered when using secure_compare
32
+ # to compare weak, short secrets to user input.
33
+ def secure_compare(a, b)
34
+ a.length == b.length && fixed_length_secure_compare(a, b)
24
35
  end
25
- module_function :variable_size_secure_compare
36
+ module_function :secure_compare
26
37
  end
27
38
  end
@@ -1,3 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/symbol/starts_ends_with"
4
+
1
5
  module ActiveSupport
2
6
  # Wrapping a string in this class gives you a prettier way to test
3
7
  # for equality. The value returned by <tt>Rails.env</tt> is wrapped
@@ -8,15 +12,20 @@ module ActiveSupport
8
12
  # you can call this:
9
13
  #
10
14
  # Rails.env.production?
15
+ #
16
+ # == Instantiating a new StringInquirer
17
+ #
18
+ # vehicle = ActiveSupport::StringInquirer.new('car')
19
+ # vehicle.car? # => true
20
+ # vehicle.bike? # => false
11
21
  class StringInquirer < String
12
22
  private
13
-
14
23
  def respond_to_missing?(method_name, include_private = false)
15
- method_name[-1] == '?'
24
+ method_name.end_with?("?") || super
16
25
  end
17
26
 
18
27
  def method_missing(method_name, *arguments)
19
- if method_name[-1] == '?'
28
+ if method_name.end_with?("?")
20
29
  self == method_name[0..-2]
21
30
  else
22
31
  super