提交 3f1d04e3 编写于 作者: J Jeremy Kemper

Fix string/gid collision in job arguments

Serialize Global IDs as special objects, distinguishable from Strings
上级 391cfc20
......@@ -35,12 +35,15 @@ def deserialize(arguments)
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 @@ def deserialize_argument(argument)
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
......
......@@ -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
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册