activesupport 3.2.22.5 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +364 -135
- data/MIT-LICENSE +1 -1
- data/README.rdoc +6 -4
- data/lib/active_support/backtrace_cleaner.rb +33 -25
- data/lib/active_support/basic_object.rb +7 -17
- data/lib/active_support/benchmarkable.rb +19 -15
- data/lib/active_support/buffered_logger.rb +9 -113
- data/lib/active_support/cache/file_store.rb +14 -14
- data/lib/active_support/cache/mem_cache_store.rb +24 -30
- data/lib/active_support/cache/memory_store.rb +2 -0
- data/lib/active_support/cache/strategy/local_cache.rb +48 -37
- data/lib/active_support/cache.rb +228 -183
- data/lib/active_support/callbacks.rb +201 -253
- data/lib/active_support/concern.rb +16 -23
- data/lib/active_support/concurrency/latch.rb +27 -0
- data/lib/active_support/configurable.rb +69 -12
- data/lib/active_support/core_ext/array/access.rb +17 -9
- data/lib/active_support/core_ext/array/conversions.rb +115 -55
- data/lib/active_support/core_ext/array/extract_options.rb +2 -2
- data/lib/active_support/core_ext/array/grouping.rb +21 -22
- data/lib/active_support/core_ext/array/uniq_by.rb +12 -9
- data/lib/active_support/core_ext/array/wrap.rb +13 -16
- data/lib/active_support/core_ext/array.rb +0 -1
- data/lib/active_support/core_ext/benchmark.rb +7 -0
- data/lib/active_support/core_ext/big_decimal/conversions.rb +8 -24
- data/lib/active_support/core_ext/class/attribute.rb +40 -32
- data/lib/active_support/core_ext/class/attribute_accessors.rb +14 -12
- data/lib/active_support/core_ext/class/delegating_attributes.rb +15 -19
- data/lib/active_support/core_ext/class/subclasses.rb +11 -5
- data/lib/active_support/core_ext/date/calculations.rb +44 -187
- data/lib/active_support/core_ext/date/conversions.rb +16 -38
- data/lib/active_support/core_ext/date/zones.rb +25 -2
- data/lib/active_support/core_ext/date.rb +5 -0
- data/lib/active_support/core_ext/date_and_time/calculations.rb +232 -0
- data/lib/active_support/core_ext/date_time/acts_like.rb +0 -1
- data/lib/active_support/core_ext/date_time/calculations.rb +77 -62
- data/lib/active_support/core_ext/date_time/conversions.rb +21 -33
- data/lib/active_support/core_ext/date_time/zones.rb +11 -8
- data/lib/active_support/core_ext/date_time.rb +4 -0
- data/lib/active_support/core_ext/enumerable.rb +26 -73
- data/lib/active_support/core_ext/file/atomic.rb +27 -11
- data/lib/active_support/core_ext/file.rb +0 -1
- data/lib/active_support/core_ext/hash/conversions.rb +145 -79
- data/lib/active_support/core_ext/hash/deep_merge.rb +14 -8
- data/lib/active_support/core_ext/hash/diff.rb +5 -4
- data/lib/active_support/core_ext/hash/except.rb +1 -9
- data/lib/active_support/core_ext/hash/indifferent_access.rb +4 -5
- data/lib/active_support/core_ext/hash/keys.rb +108 -24
- data/lib/active_support/core_ext/hash/reverse_merge.rb +2 -3
- data/lib/active_support/core_ext/hash/slice.rb +12 -12
- data/lib/active_support/core_ext/hash.rb +0 -1
- data/lib/active_support/core_ext/integer/inflections.rb +13 -1
- data/lib/active_support/core_ext/integer/time.rb +17 -12
- data/lib/active_support/core_ext/kernel/debugger.rb +2 -2
- data/lib/active_support/core_ext/kernel/reporting.rb +36 -22
- data/lib/active_support/core_ext/kernel/singleton_class.rb +0 -7
- data/lib/active_support/core_ext/load_error.rb +7 -5
- data/lib/active_support/core_ext/logger.rb +7 -23
- data/lib/active_support/core_ext/marshal.rb +21 -0
- data/lib/active_support/core_ext/module/aliasing.rb +8 -9
- data/lib/active_support/core_ext/module/anonymous.rb +2 -7
- data/lib/active_support/core_ext/module/attr_internal.rb +0 -1
- data/lib/active_support/core_ext/module/attribute_accessors.rb +12 -10
- data/lib/active_support/core_ext/module/delegation.rb +92 -49
- data/lib/active_support/core_ext/module/deprecation.rb +19 -3
- data/lib/active_support/core_ext/module/introspection.rb +17 -27
- data/lib/active_support/core_ext/module/qualified_const.rb +8 -20
- data/lib/active_support/core_ext/module/remove_method.rb +1 -5
- data/lib/active_support/core_ext/module.rb +1 -3
- data/lib/active_support/core_ext/numeric/conversions.rb +135 -0
- data/lib/active_support/core_ext/numeric/time.rb +6 -6
- data/lib/active_support/core_ext/numeric.rb +1 -0
- data/lib/active_support/core_ext/object/acts_like.rb +4 -4
- data/lib/active_support/core_ext/object/blank.rb +7 -23
- data/lib/active_support/core_ext/object/deep_dup.rb +46 -0
- data/lib/active_support/core_ext/object/duplicable.rb +1 -30
- data/lib/active_support/core_ext/object/inclusion.rb +8 -7
- data/lib/active_support/core_ext/object/instance_variables.rb +7 -12
- data/lib/active_support/core_ext/object/to_json.rb +8 -0
- data/lib/active_support/core_ext/object/to_param.rb +5 -2
- data/lib/active_support/core_ext/object/try.rb +46 -25
- data/lib/active_support/core_ext/object/with_options.rb +7 -8
- data/lib/active_support/core_ext/object.rb +1 -0
- data/lib/active_support/core_ext/proc.rb +3 -0
- data/lib/active_support/core_ext/range/conversions.rb +0 -2
- data/lib/active_support/core_ext/range/include_range.rb +3 -1
- data/lib/active_support/core_ext/range/overlaps.rb +1 -1
- data/lib/active_support/core_ext/range.rb +0 -2
- data/lib/active_support/core_ext/string/access.rb +95 -90
- data/lib/active_support/core_ext/string/conversions.rb +27 -38
- data/lib/active_support/core_ext/string/encoding.rb +6 -9
- data/lib/active_support/core_ext/string/filters.rb +24 -18
- data/lib/active_support/core_ext/string/indent.rb +43 -0
- data/lib/active_support/core_ext/string/inflections.rb +70 -60
- data/lib/active_support/core_ext/string/inquiry.rb +2 -2
- data/lib/active_support/core_ext/string/multibyte.rb +41 -64
- data/lib/active_support/core_ext/string/output_safety.rb +59 -51
- data/lib/active_support/core_ext/string/zones.rb +13 -0
- data/lib/active_support/core_ext/string.rb +2 -3
- data/lib/active_support/core_ext/struct.rb +6 -0
- data/lib/active_support/core_ext/thread.rb +74 -0
- data/lib/active_support/core_ext/time/calculations.rb +108 -184
- data/lib/active_support/core_ext/time/conversions.rb +27 -51
- data/lib/active_support/core_ext/time/marshal.rb +0 -27
- data/lib/active_support/core_ext/time/zones.rb +27 -17
- data/lib/active_support/core_ext/time.rb +5 -0
- data/lib/active_support/core_ext/uri.rb +13 -17
- data/lib/active_support/core_ext.rb +3 -2
- data/lib/active_support/dependencies/autoload.rb +47 -20
- data/lib/active_support/dependencies.rb +160 -141
- data/lib/active_support/deprecation/behaviors.rb +44 -30
- data/lib/active_support/deprecation/instance_delegator.rb +24 -0
- data/lib/active_support/deprecation/method_wrappers.rb +33 -18
- data/lib/active_support/deprecation/proxy_wrappers.rb +58 -13
- data/lib/active_support/deprecation/reporting.rb +40 -11
- data/lib/active_support/deprecation.rb +39 -14
- data/lib/active_support/descendants_tracker.rb +34 -19
- data/lib/active_support/duration.rb +6 -8
- data/lib/active_support/file_update_checker.rb +63 -47
- data/lib/active_support/gzip.rb +11 -5
- data/lib/active_support/hash_with_indifferent_access.rb +127 -42
- data/lib/active_support/i18n.rb +4 -0
- data/lib/active_support/i18n_railtie.rb +5 -22
- data/lib/active_support/inflections.rb +14 -12
- data/lib/active_support/inflector/inflections.rb +108 -71
- data/lib/active_support/inflector/methods.rb +181 -160
- data/lib/active_support/inflector/transliterate.rb +16 -17
- data/lib/active_support/json/decoding.rb +18 -17
- data/lib/active_support/json/encoding.rb +93 -39
- data/lib/active_support/json/variable.rb +10 -1
- data/lib/active_support/key_generator.rb +75 -0
- data/lib/active_support/lazy_load_hooks.rb +21 -19
- data/lib/active_support/locale/en.yml +100 -3
- data/lib/active_support/log_subscriber/test_helper.rb +18 -15
- data/lib/active_support/log_subscriber.rb +35 -52
- data/lib/active_support/logger.rb +57 -0
- data/lib/active_support/logger_silence.rb +24 -0
- data/lib/active_support/message_encryptor.rb +38 -35
- data/lib/active_support/message_verifier.rb +9 -15
- data/lib/active_support/multibyte/chars.rb +80 -333
- data/lib/active_support/multibyte/unicode.rb +74 -64
- data/lib/active_support/multibyte.rb +5 -28
- data/lib/active_support/notifications/fanout.rb +112 -18
- data/lib/active_support/notifications/instrumenter.rb +33 -14
- data/lib/active_support/notifications.rb +79 -26
- data/lib/active_support/number_helper.rb +637 -0
- data/lib/active_support/ordered_hash.rb +8 -190
- data/lib/active_support/ordered_options.rb +21 -23
- data/lib/active_support/per_thread_registry.rb +52 -0
- data/lib/active_support/proxy_object.rb +13 -0
- data/lib/active_support/rails.rb +27 -0
- data/lib/active_support/railtie.rb +12 -32
- data/lib/active_support/rescuable.rb +9 -4
- data/lib/active_support/string_inquirer.rb +13 -8
- data/lib/active_support/subscriber.rb +93 -0
- data/lib/active_support/tagged_logging.rb +51 -73
- data/lib/active_support/test_case.rb +46 -17
- data/lib/active_support/testing/assertions.rb +56 -26
- data/lib/active_support/testing/autorun.rb +5 -0
- data/lib/active_support/testing/constant_lookup.rb +54 -0
- data/lib/active_support/testing/declarative.rb +1 -1
- data/lib/active_support/testing/deprecation.rb +0 -19
- data/lib/active_support/testing/isolation.rb +29 -58
- data/lib/active_support/testing/pending.rb +5 -43
- data/lib/active_support/testing/setup_and_teardown.rb +6 -92
- data/lib/active_support/testing/tagged_logging.rb +25 -0
- data/lib/active_support/time.rb +6 -21
- data/lib/active_support/time_with_zone.rb +80 -43
- data/lib/active_support/values/time_zone.rb +81 -60
- data/lib/active_support/values/unicode_tables.dat +0 -0
- data/lib/active_support/version.rb +7 -6
- data/lib/active_support/xml_mini/jdom.rb +9 -11
- data/lib/active_support/xml_mini/libxml.rb +1 -2
- data/lib/active_support/xml_mini/libxmlsax.rb +2 -3
- data/lib/active_support/xml_mini/nokogiri.rb +1 -2
- data/lib/active_support/xml_mini/nokogirisax.rb +2 -3
- data/lib/active_support/xml_mini/rexml.rb +6 -8
- data/lib/active_support/xml_mini.rb +35 -17
- data/lib/active_support.rb +8 -21
- metadata +104 -72
- data/lib/active_support/base64.rb +0 -54
- data/lib/active_support/core_ext/array/random_access.rb +0 -30
- data/lib/active_support/core_ext/date/freeze.rb +0 -33
- data/lib/active_support/core_ext/exception.rb +0 -3
- data/lib/active_support/core_ext/file/path.rb +0 -5
- data/lib/active_support/core_ext/float/rounding.rb +0 -19
- data/lib/active_support/core_ext/float.rb +0 -1
- data/lib/active_support/core_ext/hash/deep_dup.rb +0 -18
- data/lib/active_support/core_ext/io.rb +0 -15
- data/lib/active_support/core_ext/module/method_names.rb +0 -14
- data/lib/active_support/core_ext/module/synchronization.rb +0 -45
- data/lib/active_support/core_ext/process/daemon.rb +0 -23
- data/lib/active_support/core_ext/process.rb +0 -1
- data/lib/active_support/core_ext/range/blockless_step.rb +0 -29
- data/lib/active_support/core_ext/range/cover.rb +0 -3
- data/lib/active_support/core_ext/rexml.rb +0 -46
- data/lib/active_support/core_ext/string/interpolation.rb +0 -2
- data/lib/active_support/core_ext/string/xchar.rb +0 -18
- data/lib/active_support/core_ext/time/publicize_conversion_methods.rb +0 -10
- data/lib/active_support/memoizable.rb +0 -116
- data/lib/active_support/multibyte/exceptions.rb +0 -8
- data/lib/active_support/multibyte/utils.rb +0 -60
- data/lib/active_support/ruby/shim.rb +0 -22
- data/lib/active_support/security_utils.rb +0 -27
- data/lib/active_support/testing/mochaing.rb +0 -7
- data/lib/active_support/testing/performance/jruby.rb +0 -115
- data/lib/active_support/testing/performance/rubinius.rb +0 -113
- data/lib/active_support/testing/performance/ruby/mri.rb +0 -57
- data/lib/active_support/testing/performance/ruby/yarv.rb +0 -57
- data/lib/active_support/testing/performance/ruby.rb +0 -152
- data/lib/active_support/testing/performance.rb +0 -317
- data/lib/active_support/time/autoload.rb +0 -5
- data/lib/active_support/whiny_nil.rb +0 -24
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
require 'active_support/core_ext/module/attribute_accessors'
|
|
2
2
|
require 'active_support/core_ext/class/attribute'
|
|
3
|
+
require 'active_support/subscriber'
|
|
3
4
|
|
|
4
5
|
module ActiveSupport
|
|
5
|
-
# ActiveSupport::LogSubscriber is an object set to consume
|
|
6
|
-
# with the sole purpose of logging them.
|
|
7
|
-
# a registered object based
|
|
6
|
+
# ActiveSupport::LogSubscriber is an object set to consume
|
|
7
|
+
# ActiveSupport::Notifications with the sole purpose of logging them.
|
|
8
|
+
# The log subscriber dispatches notifications to a registered object based
|
|
9
|
+
# on its given namespace.
|
|
8
10
|
#
|
|
9
|
-
# An example would be Active Record log subscriber responsible for logging
|
|
11
|
+
# An example would be Active Record log subscriber responsible for logging
|
|
12
|
+
# queries:
|
|
10
13
|
#
|
|
11
14
|
# module ActiveRecord
|
|
12
15
|
# class LogSubscriber < ActiveSupport::LogSubscriber
|
|
@@ -20,17 +23,18 @@ module ActiveSupport
|
|
|
20
23
|
#
|
|
21
24
|
# ActiveRecord::LogSubscriber.attach_to :active_record
|
|
22
25
|
#
|
|
23
|
-
# Since we need to know all instance methods before attaching the log
|
|
24
|
-
# the line above should be called after your
|
|
26
|
+
# Since we need to know all instance methods before attaching the log
|
|
27
|
+
# subscriber, the line above should be called after your
|
|
28
|
+
# <tt>ActiveRecord::LogSubscriber</tt> definition.
|
|
25
29
|
#
|
|
26
30
|
# After configured, whenever a "sql.active_record" notification is published,
|
|
27
31
|
# it will properly dispatch the event (ActiveSupport::Notifications::Event) to
|
|
28
32
|
# the sql method.
|
|
29
33
|
#
|
|
30
|
-
# Log subscriber also has some helpers to deal with logging and automatically
|
|
31
|
-
# all logs when the request finishes (via action_dispatch.callback
|
|
32
|
-
# a Rails environment.
|
|
33
|
-
class LogSubscriber
|
|
34
|
+
# Log subscriber also has some helpers to deal with logging and automatically
|
|
35
|
+
# flushes all logs when the request finishes (via action_dispatch.callback
|
|
36
|
+
# notification) in a Rails environment.
|
|
37
|
+
class LogSubscriber < Subscriber
|
|
34
38
|
# Embed in a String to clear all previous ANSI sequences.
|
|
35
39
|
CLEAR = "\e[0m"
|
|
36
40
|
BOLD = "\e[1m"
|
|
@@ -48,79 +52,58 @@ module ActiveSupport
|
|
|
48
52
|
mattr_accessor :colorize_logging
|
|
49
53
|
self.colorize_logging = true
|
|
50
54
|
|
|
51
|
-
class_attribute :logger
|
|
52
|
-
|
|
53
55
|
class << self
|
|
54
|
-
remove_method :logger
|
|
55
56
|
def logger
|
|
56
|
-
@logger ||=
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
def attach_to(namespace, log_subscriber=new, notifier=ActiveSupport::Notifications)
|
|
60
|
-
log_subscribers << log_subscriber
|
|
61
|
-
@@flushable_loggers = nil
|
|
62
|
-
|
|
63
|
-
log_subscriber.public_methods(false).each do |event|
|
|
64
|
-
next if 'call' == event.to_s
|
|
65
|
-
|
|
66
|
-
notifier.subscribe("#{event}.#{namespace}", log_subscriber)
|
|
57
|
+
@logger ||= if defined?(Rails) && Rails.respond_to?(:logger)
|
|
58
|
+
Rails.logger
|
|
67
59
|
end
|
|
68
60
|
end
|
|
69
61
|
|
|
70
|
-
|
|
71
|
-
@@log_subscribers ||= []
|
|
72
|
-
end
|
|
62
|
+
attr_writer :logger
|
|
73
63
|
|
|
74
|
-
def
|
|
75
|
-
|
|
76
|
-
loggers = log_subscribers.map(&:logger)
|
|
77
|
-
loggers.uniq!
|
|
78
|
-
loggers.select { |l| l.respond_to?(:flush) }
|
|
79
|
-
end
|
|
64
|
+
def log_subscribers
|
|
65
|
+
subscribers
|
|
80
66
|
end
|
|
81
67
|
|
|
82
68
|
# Flush all log_subscribers' logger.
|
|
83
69
|
def flush_all!
|
|
84
|
-
|
|
70
|
+
logger.flush if logger.respond_to?(:flush)
|
|
85
71
|
end
|
|
86
72
|
end
|
|
87
73
|
|
|
88
|
-
def
|
|
89
|
-
|
|
74
|
+
def logger
|
|
75
|
+
LogSubscriber.logger
|
|
76
|
+
end
|
|
90
77
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
78
|
+
def start(name, id, payload)
|
|
79
|
+
super if logger
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def finish(name, id, payload)
|
|
83
|
+
super if logger
|
|
84
|
+
rescue Exception => e
|
|
85
|
+
logger.error "Could not log #{name.inspect} event. #{e.class}: #{e.message} #{e.backtrace}"
|
|
97
86
|
end
|
|
98
87
|
|
|
99
88
|
protected
|
|
100
89
|
|
|
101
90
|
%w(info debug warn error fatal unknown).each do |level|
|
|
102
91
|
class_eval <<-METHOD, __FILE__, __LINE__ + 1
|
|
103
|
-
def #{level}(
|
|
104
|
-
|
|
105
|
-
logger.#{level}(*args, &block)
|
|
92
|
+
def #{level}(progname = nil, &block)
|
|
93
|
+
logger.#{level}(progname, &block) if logger
|
|
106
94
|
end
|
|
107
95
|
METHOD
|
|
108
96
|
end
|
|
109
97
|
|
|
110
98
|
# Set color by using a string or one of the defined constants. If a third
|
|
111
|
-
# option is set to true
|
|
99
|
+
# option is set to +true+, it also adds bold to the string. This is based
|
|
112
100
|
# on the Highline implementation and will automatically append CLEAR to the
|
|
113
101
|
# end of the returned String.
|
|
114
|
-
#
|
|
115
102
|
def color(text, color, bold=false)
|
|
116
103
|
return text unless colorize_logging
|
|
117
|
-
color = self.class.const_get(color.
|
|
104
|
+
color = self.class.const_get(color.upcase) if color.is_a?(Symbol)
|
|
118
105
|
bold = bold ? BOLD : ""
|
|
119
106
|
"#{bold}#{color}#{text}#{CLEAR}"
|
|
120
107
|
end
|
|
121
|
-
|
|
122
|
-
def format_duration(duration)
|
|
123
|
-
"%.1fms" % duration
|
|
124
|
-
end
|
|
125
108
|
end
|
|
126
109
|
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
require 'active_support/core_ext/class/attribute_accessors'
|
|
2
|
+
require 'active_support/logger_silence'
|
|
3
|
+
require 'logger'
|
|
4
|
+
|
|
5
|
+
module ActiveSupport
|
|
6
|
+
class Logger < ::Logger
|
|
7
|
+
include LoggerSilence
|
|
8
|
+
|
|
9
|
+
# Broadcasts logs to multiple loggers.
|
|
10
|
+
def self.broadcast(logger) # :nodoc:
|
|
11
|
+
Module.new do
|
|
12
|
+
define_method(:add) do |*args, &block|
|
|
13
|
+
logger.add(*args, &block)
|
|
14
|
+
super(*args, &block)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
define_method(:<<) do |x|
|
|
18
|
+
logger << x
|
|
19
|
+
super(x)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
define_method(:close) do
|
|
23
|
+
logger.close
|
|
24
|
+
super()
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
define_method(:progname=) do |name|
|
|
28
|
+
logger.progname = name
|
|
29
|
+
super(name)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
define_method(:formatter=) do |formatter|
|
|
33
|
+
logger.formatter = formatter
|
|
34
|
+
super(formatter)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
define_method(:level=) do |level|
|
|
38
|
+
logger.level = level
|
|
39
|
+
super(level)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def initialize(*args)
|
|
45
|
+
super
|
|
46
|
+
@formatter = SimpleFormatter.new
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Simple formatter which only displays the message.
|
|
50
|
+
class SimpleFormatter < ::Logger::Formatter
|
|
51
|
+
# This method is invoked when a log event occurs
|
|
52
|
+
def call(severity, timestamp, progname, msg)
|
|
53
|
+
"#{String === msg ? msg : msg.inspect}\n"
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
require 'active_support/concern'
|
|
2
|
+
|
|
3
|
+
module LoggerSilence
|
|
4
|
+
extend ActiveSupport::Concern
|
|
5
|
+
|
|
6
|
+
included do
|
|
7
|
+
cattr_accessor :silencer
|
|
8
|
+
self.silencer = true
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# Silences the logger for the duration of the block.
|
|
12
|
+
def silence(temporary_level = Logger::ERROR)
|
|
13
|
+
if silencer
|
|
14
|
+
begin
|
|
15
|
+
old_logger_level, self.level = level, temporary_level
|
|
16
|
+
yield self
|
|
17
|
+
ensure
|
|
18
|
+
self.level = old_logger_level
|
|
19
|
+
end
|
|
20
|
+
else
|
|
21
|
+
yield self
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -1,14 +1,22 @@
|
|
|
1
1
|
require 'openssl'
|
|
2
|
-
require '
|
|
2
|
+
require 'base64'
|
|
3
|
+
require 'active_support/core_ext/array/extract_options'
|
|
3
4
|
|
|
4
5
|
module ActiveSupport
|
|
5
|
-
# MessageEncryptor is a simple way to encrypt values which get stored
|
|
6
|
-
# you don't trust.
|
|
6
|
+
# MessageEncryptor is a simple way to encrypt values which get stored
|
|
7
|
+
# somewhere you don't trust.
|
|
7
8
|
#
|
|
8
|
-
# The cipher text and initialization vector are base64 encoded and returned
|
|
9
|
+
# The cipher text and initialization vector are base64 encoded and returned
|
|
10
|
+
# to you.
|
|
9
11
|
#
|
|
10
|
-
# This can be used in situations similar to the <tt>MessageVerifier</tt>, but
|
|
11
|
-
# want users to be able to determine the value of the payload.
|
|
12
|
+
# This can be used in situations similar to the <tt>MessageVerifier</tt>, but
|
|
13
|
+
# where you don't want users to be able to determine the value of the payload.
|
|
14
|
+
#
|
|
15
|
+
# salt = SecureRandom.random_bytes(64)
|
|
16
|
+
# key = ActiveSupport::KeyGenerator.new('password').generate_key(salt) # => "\x89\xE0\x156\xAC..."
|
|
17
|
+
# crypt = ActiveSupport::MessageEncryptor.new(key) # => #<ActiveSupport::MessageEncryptor ...>
|
|
18
|
+
# encrypted_data = crypt.encrypt_and_sign('my secret data') # => "NlFBTTMwOUV5UlA1QlNEN2xkY2d6eThYWWh..."
|
|
19
|
+
# crypt.decrypt_and_verify(encrypted_data) # => "my secret data"
|
|
12
20
|
class MessageEncryptor
|
|
13
21
|
module NullSerializer #:nodoc:
|
|
14
22
|
def self.load(value)
|
|
@@ -21,40 +29,36 @@ module ActiveSupport
|
|
|
21
29
|
end
|
|
22
30
|
|
|
23
31
|
class InvalidMessage < StandardError; end
|
|
24
|
-
OpenSSLCipherError = OpenSSL::Cipher
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
+
OpenSSLCipherError = OpenSSL::Cipher::CipherError
|
|
33
|
+
|
|
34
|
+
# Initialize a new MessageEncryptor. +secret+ must be at least as long as
|
|
35
|
+
# the cipher key size. For the default 'aes-256-cbc' cipher, this is 256
|
|
36
|
+
# bits. If you are using a user-entered secret, you can generate a suitable
|
|
37
|
+
# key with <tt>OpenSSL::Digest::SHA256.new(user_secret).digest</tt> or
|
|
38
|
+
# similar.
|
|
39
|
+
#
|
|
40
|
+
# Options:
|
|
41
|
+
# * <tt>:cipher</tt> - Cipher to use. Can be any cipher returned by
|
|
42
|
+
# <tt>OpenSSL::Cipher.ciphers</tt>. Default is 'aes-256-cbc'.
|
|
43
|
+
# * <tt>:serializer</tt> - Object serializer to use. Default is +Marshal+.
|
|
44
|
+
def initialize(secret, *signature_key_or_options)
|
|
45
|
+
options = signature_key_or_options.extract_options!
|
|
46
|
+
sign_secret = signature_key_or_options.first
|
|
32
47
|
@secret = secret
|
|
48
|
+
@sign_secret = sign_secret
|
|
33
49
|
@cipher = options[:cipher] || 'aes-256-cbc'
|
|
34
|
-
@verifier = MessageVerifier.new(@secret, :serializer => NullSerializer)
|
|
50
|
+
@verifier = MessageVerifier.new(@sign_secret || @secret, :serializer => NullSerializer)
|
|
35
51
|
@serializer = options[:serializer] || Marshal
|
|
36
52
|
end
|
|
37
53
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
"Please use MessageEncryptor#encrypt_and_sign instead."
|
|
41
|
-
_encrypt(value)
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def decrypt(value)
|
|
45
|
-
ActiveSupport::Deprecation.warn "MessageEncryptor#decrypt is deprecated as it is not safe without a signature. " \
|
|
46
|
-
"Please use MessageEncryptor#decrypt_and_verify instead."
|
|
47
|
-
_decrypt(value)
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
# Encrypt and sign a message. We need to sign the message in order to avoid padding attacks.
|
|
51
|
-
# Reference: http://www.limited-entropy.com/padding-oracle-attacks
|
|
54
|
+
# Encrypt and sign a message. We need to sign the message in order to avoid
|
|
55
|
+
# padding attacks. Reference: http://www.limited-entropy.com/padding-oracle-attacks.
|
|
52
56
|
def encrypt_and_sign(value)
|
|
53
57
|
verifier.generate(_encrypt(value))
|
|
54
58
|
end
|
|
55
59
|
|
|
56
|
-
# Decrypt and verify a message. We need to verify the message in order to
|
|
57
|
-
# Reference: http://www.limited-entropy.com/padding-oracle-attacks
|
|
60
|
+
# Decrypt and verify a message. We need to verify the message in order to
|
|
61
|
+
# avoid padding attacks. Reference: http://www.limited-entropy.com/padding-oracle-attacks.
|
|
58
62
|
def decrypt_and_verify(value)
|
|
59
63
|
_decrypt(verifier.verify(value))
|
|
60
64
|
end
|
|
@@ -63,12 +67,11 @@ module ActiveSupport
|
|
|
63
67
|
|
|
64
68
|
def _encrypt(value)
|
|
65
69
|
cipher = new_cipher
|
|
66
|
-
# Rely on OpenSSL for the initialization vector
|
|
67
|
-
iv = cipher.random_iv
|
|
68
|
-
|
|
69
70
|
cipher.encrypt
|
|
70
71
|
cipher.key = @secret
|
|
71
|
-
|
|
72
|
+
|
|
73
|
+
# Rely on OpenSSL for the initialization vector
|
|
74
|
+
iv = cipher.random_iv
|
|
72
75
|
|
|
73
76
|
encrypted_data = cipher.update(@serializer.dump(value))
|
|
74
77
|
encrypted_data << cipher.final
|
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
require '
|
|
2
|
-
require 'active_support/deprecation'
|
|
1
|
+
require 'base64'
|
|
3
2
|
require 'active_support/core_ext/object/blank'
|
|
4
3
|
|
|
5
4
|
module ActiveSupport
|
|
6
|
-
# +MessageVerifier+ makes it easy to generate and verify messages which are
|
|
7
|
-
# to prevent tampering.
|
|
5
|
+
# +MessageVerifier+ makes it easy to generate and verify messages which are
|
|
6
|
+
# signed to prevent tampering.
|
|
8
7
|
#
|
|
9
|
-
# This is useful for cases like remember-me tokens and auto-unsubscribe links
|
|
10
|
-
# session store isn't suitable or available.
|
|
8
|
+
# This is useful for cases like remember-me tokens and auto-unsubscribe links
|
|
9
|
+
# where the session store isn't suitable or available.
|
|
11
10
|
#
|
|
12
11
|
# Remember Me:
|
|
13
12
|
# cookies[:remember_me] = @verifier.generate([@user.id, 2.weeks.from_now])
|
|
@@ -19,20 +18,15 @@ module ActiveSupport
|
|
|
19
18
|
# self.current_user = User.find(id)
|
|
20
19
|
# end
|
|
21
20
|
#
|
|
22
|
-
# By default it uses Marshal to serialize the message. If you want to use
|
|
23
|
-
# serialization method, you can set the serializer
|
|
24
|
-
#
|
|
21
|
+
# By default it uses Marshal to serialize the message. If you want to use
|
|
22
|
+
# another serialization method, you can set the serializer in the options
|
|
23
|
+
# hash upon initialization:
|
|
25
24
|
#
|
|
26
|
-
# @verifier.serializer
|
|
25
|
+
# @verifier = ActiveSupport::MessageVerifier.new('s3Krit', serializer: YAML)
|
|
27
26
|
class MessageVerifier
|
|
28
27
|
class InvalidSignature < StandardError; end
|
|
29
28
|
|
|
30
29
|
def initialize(secret, options = {})
|
|
31
|
-
unless options.is_a?(Hash)
|
|
32
|
-
ActiveSupport::Deprecation.warn "The second parameter should be an options hash. Use :digest => 'algorithm' to specify the digest algorithm."
|
|
33
|
-
options = { :digest => options }
|
|
34
|
-
end
|
|
35
|
-
|
|
36
30
|
@secret = secret
|
|
37
31
|
@digest = options[:digest] || 'SHA1'
|
|
38
32
|
@serializer = options[:serializer] || Marshal
|