mirror of https://github.com/rails/rails
YAMLColumn: use `YAML.safe_dump` if available
One particularly annoying thing with YAMLColumn type restriction is that it is only checked on load. Which means if your code insert data with unsupported types, the insert will work, but now you'll be unable to read the record, which makes it hard to fix etc. That's the reason why I implemented `YAML.safe_dump` (https://github.com/ruby/psych/pull/495). It applies exactly the same restrictions than `safe_load`, which means if you attempt to store non-permitted fields, it will fail on insertion and not on further reads, so you won't create an invalid record in your database.
This commit is contained in:
parent
d6eec533c1
commit
3635d2d9cf
|
@ -333,7 +333,7 @@ GEM
|
|||
activesupport (>= 7.0.0)
|
||||
rack
|
||||
railties (>= 7.0.0)
|
||||
psych (5.0.1)
|
||||
psych (5.1.0)
|
||||
stringio
|
||||
public_suffix (5.0.1)
|
||||
puma (6.0.2)
|
||||
|
|
|
@ -1,3 +1,14 @@
|
|||
* YAML columns use `YAML.safe_dump` is available.
|
||||
|
||||
As of `psych 5.1.0`, `YAML.safe_dump` can now apply the same permitted
|
||||
types restrictions than `YAML.safe_load`.
|
||||
|
||||
It's preferable to ensure the payload only use allowed types when we first
|
||||
try to serialize it, otherwise you may end up with invalid records in the
|
||||
database.
|
||||
|
||||
*Jean Boussier*
|
||||
|
||||
* `ActiveRecord::QueryLogs` better handle broken encoding.
|
||||
|
||||
It's not uncommon when building queries with BLOB fields to contain
|
||||
|
|
|
@ -26,11 +26,24 @@ module ActiveRecord
|
|||
@unsafe_load = coder["unsafe_load"]
|
||||
end
|
||||
|
||||
def dump(obj)
|
||||
return if obj.nil?
|
||||
if Gem::Version.new(Psych::VERSION) >= "5.1"
|
||||
def dump(obj)
|
||||
return if obj.nil?
|
||||
|
||||
assert_valid_value(obj, action: "dump")
|
||||
YAML.dump obj
|
||||
assert_valid_value(obj, action: "dump")
|
||||
if unsafe_load?
|
||||
YAML.dump(obj)
|
||||
else
|
||||
YAML.safe_dump(obj, permitted_classes: permitted_classes, aliases: true)
|
||||
end
|
||||
end
|
||||
else
|
||||
def dump(obj)
|
||||
return if obj.nil?
|
||||
|
||||
assert_valid_value(obj, action: "dump")
|
||||
YAML.dump obj
|
||||
end
|
||||
end
|
||||
|
||||
def load(yaml)
|
||||
|
|
|
@ -97,6 +97,17 @@ module ActiveRecord
|
|||
end
|
||||
end
|
||||
|
||||
def test_yaml_column_permitted_classes_are_consumed_by_safe_dump
|
||||
if Gem::Version.new(Psych::VERSION) < "5.1"
|
||||
skip "YAML.safe_dump is either missing on unavailable on #{Psych::VERSION}"
|
||||
end
|
||||
|
||||
coder = YAMLColumn.new("attr_name")
|
||||
assert_raises(Psych::DisallowedClass) do
|
||||
coder.dump([Time.new])
|
||||
end
|
||||
end
|
||||
|
||||
def test_yaml_column_permitted_classes_option
|
||||
ActiveRecord.yaml_column_permitted_classes = [Symbol]
|
||||
|
||||
|
|
Loading…
Reference in New Issue