Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 12 additions & 6 deletions lib/hash_cast/casters/array_caster.rb
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
class HashCast::Casters::ArrayCaster

def self.cast(value, attr_name, options = {})
if value.is_a?(Array)
if options[:each]
cast_array_items(value, attr_name, options)
else
value
unless value.is_a?(Array)
raise HashCast::Errors::CastingError, "should be an array"
end

if HashCast.config.array_size_validator_enabled
if value.size > HashCast.config.array_size_validator_limit
HashCast.config.array_size_validator_callback.call(value, attr_name, options)
end
end

if options[:each]
cast_array_items(value, attr_name, options)
else
raise HashCast::Errors::CastingError, "should be an array"
value
end
end

Expand Down
6 changes: 6 additions & 0 deletions lib/hash_cast/casters/string_caster.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ def self.cast(value, attr_name, options = {})
raise HashCast::Errors::CastingError, 'contains invalid characters'
end

if HashCast.config.string_size_validator_enabled
if value.size > HashCast.config.string_size_validator_limit
HashCast.config.string_size_validator_callback.call(value, attr_name, options)
end
end

casted_value
end

Expand Down
55 changes: 54 additions & 1 deletion lib/hash_cast/config.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
class HashCast::Config
attr_accessor :input_keys, :output_keys, :validate_string_null_byte
attr_writer :input_keys, :output_keys, :validate_string_null_byte,
:array_size_validator_enabled,
:array_size_validator_limit,
:array_size_validator_callback,
:string_size_validator_enabled,
:string_size_validator_limit,
:string_size_validator_callback

DEFAULT_ARRAY_SIZE_VALIDATOR_LIMIT = 1000_000
DEFAULT_STRING_SIZE_VALIDATOR_LIMIT = 1000_000

def input_keys
@input_keys || :symbol
Expand All @@ -14,4 +23,48 @@ def validate_string_null_byte

@validate_string_null_byte
end

def array_size_validator_enabled
return false if @array_size_validator_enabled.nil?

@array_size_validator_enabled
end

def array_size_validator_limit
return DEFAULT_ARRAY_SIZE_VALIDATOR_LIMIT if @array_size_validator_limit.nil?

@array_size_validator_limit
end

def array_size_validator_callback
if @array_size_validator_callback.nil?
return lambda{ |value, name, options|
raise HashCast::Errors::CastingError, "array is too large"
}
end

@array_size_validator_callback
end

def string_size_validator_enabled
return false if @string_size_validator_enabled.nil?

@string_size_validator_enabled
end

def string_size_validator_limit
return DEFAULT_STRING_SIZE_VALIDATOR_LIMIT if @string_size_validator_limit.nil?

@string_size_validator_limit
end

def string_size_validator_callback
if @string_size_validator_callback.nil?
return lambda{ |value, name, options|
raise HashCast::Errors::CastingError, "string is too large"
}
end

@string_size_validator_callback
end
end
49 changes: 49 additions & 0 deletions spec/hash_cast/casters/array_caster_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
require 'spec_helper'

describe HashCast::Casters::ArrayCaster do
subject { HashCast::Casters::ArrayCaster }

it "should cast an array" do
result = subject.cast([1,2,3], :ids)
expect(result).to eq([1,2,3])
end

it "should raise an error for non-array" do
expect {
subject.cast(1, :ids)
}.to raise_error(HashCast::Errors::CastingError, "should be an array")
end

context "array size validation" do
after{
HashCast.config.array_size_validator_enabled = nil
HashCast.config.array_size_validator_limit = nil
}

it "should not raise an error for large array by default" do
result = subject.cast([1] * 10_000, :ids)
expect(result).to eq([1] * 10_000)
end

it "should raise an error for large array when validation is enabled" do
HashCast.config.array_size_validator_enabled = true
HashCast.config.array_size_validator_limit = 1000

expect {
subject.cast([1] * 10_000, :ids)
}.to raise_error(HashCast::Errors::CastingError, "array is too large")
end

it "should allow overriding the callback" do
HashCast.config.array_size_validator_enabled = true
HashCast.config.array_size_validator_limit = 1000
HashCast.config.array_size_validator_callback = lambda { |value, name, options|
raise HashCast::Errors::UnexpectedAttributeError, 'test'
}

expect {
subject.cast([1] * 10_000, :ids)
}.to raise_error(HashCast::Errors::UnexpectedAttributeError, "test")
end
end
end
43 changes: 43 additions & 0 deletions spec/hash_cast/casters/string_caster_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
require 'spec_helper'

describe HashCast::Casters::StringCaster do
subject { HashCast::Casters::StringCaster }

it "should cast a string" do
result = subject.cast("foobar", :name)
expect(result).to eq("foobar")
end

context "string size validation" do
after{
HashCast.config.string_size_validator_enabled = nil
HashCast.config.string_size_validator_limit = nil
}

it "should not raise an error for large string by default" do
result = subject.cast("a" * 10_000, :name)
expect(result).to eq("a" * 10_000)
end

it "should raise an error for large string when validation is enabled" do
HashCast.config.string_size_validator_enabled = true
HashCast.config.string_size_validator_limit = 1000

expect {
subject.cast("a" * 10_000, :ids)
}.to raise_error(HashCast::Errors::CastingError, "string is too large")
end

it "should allow overriding the callback" do
HashCast.config.string_size_validator_enabled = true
HashCast.config.string_size_validator_limit = 1000
HashCast.config.string_size_validator_callback = lambda { |value, name, options|
raise HashCast::Errors::UnexpectedAttributeError, 'test'
}

expect {
subject.cast("a" * 10_000, :ids)
}.to raise_error(HashCast::Errors::UnexpectedAttributeError, "test")
end
end
end
Loading