1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Fix string/gid collision in job arguments

Serialize Global IDs as special objects, distinguishable from Strings
This commit is contained in:
Jeremy Kemper 2014-09-14 19:34:17 -07:00
parent 391cfc2054
commit 3f1d04e3bb
2 changed files with 38 additions and 6 deletions

View file

@ -35,12 +35,15 @@ module ActiveJob
end
private
GLOBALID_KEY = '_aj_globalid'.freeze
private_constant :GLOBALID_KEY
def serialize_argument(argument)
case argument
when *TYPE_WHITELIST
argument
when GlobalID::Identification
argument.to_global_id.to_s
{ GLOBALID_KEY => argument.to_global_id.to_s }
when Array
argument.map { |arg| serialize_argument(arg) }
when Hash
@ -61,16 +64,37 @@ module ActiveJob
when Array
argument.map { |arg| deserialize_argument(arg) }
when Hash
argument.each_with_object({}.with_indifferent_access) do |(key, value), hash|
hash[key] = deserialize_argument(value)
if serialized_global_id?(argument)
deserialize_global_id argument
else
deserialize_hash argument
end
else
raise ArgumentError, "Can only deserialize primitive arguments: #{argument.inspect}"
end
end
def serialized_global_id?(hash)
hash.size == 1 and hash.include?(GLOBALID_KEY)
end
def deserialize_global_id(hash)
GlobalID::Locator.locate hash[GLOBALID_KEY]
end
def deserialize_hash(serialized_hash)
serialized_hash.each_with_object({}.with_indifferent_access) do |(key, value), hash|
hash[key] = deserialize_argument(value)
end
end
RESERVED_KEYS = [GLOBALID_KEY, GLOBALID_KEY.to_sym]
private_constant :RESERVED_KEYS
def serialize_hash_key(key)
case key
when *RESERVED_KEYS
raise SerializationError.new("Can't serialize a Hash with reserved key #{key.inspect}")
when String, Symbol
key.to_s
else

View file

@ -31,12 +31,12 @@ class ArgumentSerializationTest < ActiveSupport::TestCase
end
test 'should convert records to Global IDs' do
assert_arguments_roundtrip [@person], [@person.to_gid.to_s]
assert_arguments_roundtrip [@person], ['_aj_globalid' => @person.to_gid.to_s]
end
test 'should dive deep into arrays and hashes' do
assert_arguments_roundtrip [3, [@person]], [3, [@person.to_gid.to_s]]
assert_arguments_roundtrip [{ 'a' => @person }], [{ 'a' => @person.to_gid.to_s }.with_indifferent_access]
assert_arguments_roundtrip [3, [@person]], [3, ['_aj_globalid' => @person.to_gid.to_s]]
assert_arguments_roundtrip [{ 'a' => @person }], [{ 'a' => { '_aj_globalid' => @person.to_gid.to_s }}.with_indifferent_access]
end
test 'should stringify symbol hash keys' do
@ -51,6 +51,14 @@ class ArgumentSerializationTest < ActiveSupport::TestCase
assert_raises ActiveJob::SerializationError do
ActiveJob::Arguments.serialize [ { :a => [{ 2 => 3 }] } ]
end
assert_raises ActiveJob::SerializationError do
ActiveJob::Arguments.serialize [ '_aj_globalid' => 1 ]
end
assert_raises ActiveJob::SerializationError do
ActiveJob::Arguments.serialize [ :_aj_globalid => 1 ]
end
end
test 'should not allow non-primitive objects' do