Skip to content

Commit

Permalink
restrict validator.
Browse files Browse the repository at this point in the history
  • Loading branch information
dhruvCW committed May 12, 2024
1 parent dea3e2e commit ded1efc
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 10 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
* [#2436](https://github.com/ruby-grape/grape/pull/2436): Update coverallsapp github-action - [@ericproulx](https://github.com/ericproulx).
* [#2434](https://github.com/ruby-grape/grape/pull/2434): Implement nested `with` support in parameter dsl - [@numbata](https://github.com/numbata).
* [#2438](https://github.com/ruby-grape/grape/pull/2438): Fix some Rack::Lint - [@ericproulx](https://github.com/ericproulx).
* [#2437](https://github.com/ruby-grape/grape/pull/2437): Add Length Validator - [@dhruvCW](https://github.com/dhruvCW).
* [#2437](https://github.com/ruby-grape/grape/pull/2437): Add length Validator - [@dhruvCW](https://github.com/dhruvCW).
* Your contribution here.

#### Fixes
Expand Down
9 changes: 4 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1713,15 +1713,14 @@ end

#### `length`

Parameters can be restricted from having a specific length or size with the `:length` option.
Parameters of type `String` or `Array` can be restricted to have a specific length or size with the `:length` option.

the validator accepts `:min` or `:max` or both options to validate that they parameter is within
the given limits.
The validator accepts `:min` or `:max` or both options to validate that the value of the parameter is within the given limits.

```ruby
params do
requires :str, length: { min: 3 }
requires :list, length: { min: 3, max: 5}
requires :str, type: String, length: { min: 3 }
requires :list, type: [Integer], length: { min: 3, max: 5 }
end
```

Expand Down
5 changes: 4 additions & 1 deletion lib/grape/validations/validators/length_validator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,17 @@ def initialize(attrs, options, required, scope, **opts)

super

raise ArgumentError, 'min must be an integer greater than or equal to zero' if !@min.nil? && (!@min.is_a?(Integer) || @min.negative?)
raise ArgumentError, 'max must be an integer greater than or equal to zero' if !@max.nil? && (!@max.is_a?(Integer) || @max.negative?)
raise ArgumentError, "min #{@min} cannot be greater than max #{@max}" if !@min.nil? && !@max.nil? && @min > @max
end

def validate_param!(attr_name, params)
param = params[attr_name]
param = param.compact if param.respond_to?(:compact)

return unless param.respond_to?(:length)
raise ArgumentError, "parameter #{param} has an unsupported type. Only strings & arrays are supported" unless params.is_a?(String) || param.is_a?(Array)

return unless (!@min.nil? && param.length < @min) || (!@max.nil? && param.length > @max)

raise Grape::Exceptions::Validation.new(params: [@scope.full_name(attr_name)], message: build_message)
Expand Down
78 changes: 75 additions & 3 deletions spec/grape/validations/validators/length_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,36 @@
post 'type_is_not_array' do
end

params do
requires :list, type: Hash, length: { max: 3 }
end
post 'type_supports_length' do
end

params do
requires :list, type: [Integer], length: { min: -3 }
end
post 'negative_min' do
end

params do
requires :list, type: [Integer], length: { max: -3 }
end
post 'negative_max' do
end

params do
requires :list, type: [Integer], length: { min: 2.5 }
end
post 'float_min' do
end

params do
requires :list, type: [Integer], length: { max: 2.5 }
end
post 'float_max' do
end

params do
requires :list, type: [Integer], length: { min: 15, max: 3 }
end
Expand Down Expand Up @@ -160,9 +190,51 @@
describe '/type_is_not_array' do
context 'is no op' do
it do
post 'type_is_not_array', list: 12
expect(last_response.status).to eq(201)
expect(last_response.body).to eq('')
expect do
post 'type_is_not_array', list: 12
end.to raise_error(ArgumentError, 'parameter 12 has an unsupported type. Only strings & arrays are supported')
end
end
end

describe '/type_supports_length' do
context 'raises an error' do
it do
expect do
post 'type_supports_length', list: { key: 'value' }
end.to raise_error(ArgumentError, 'parameter {"key"=>"value"} has an unsupported type. Only strings & arrays are supported')
end
end
end

describe '/negative_min' do
context 'when min is negative' do
it do
expect { post 'negative_min', list: [12] }.to raise_error(ArgumentError, 'min must be an integer greater than or equal to zero')
end
end
end

describe '/negative_max' do
context 'it raises an error' do
it do
expect { post 'negative_max', list: [12] }.to raise_error(ArgumentError, 'max must be an integer greater than or equal to zero')
end
end
end

describe '/float_min' do
context 'when min is not an integer' do
it do
expect { post 'float_min', list: [12] }.to raise_error(ArgumentError, 'min must be an integer greater than or equal to zero')
end
end
end

describe '/float_max' do
context 'when max is not an integer' do
it do
expect { post 'float_max', list: [12] }.to raise_error(ArgumentError, 'max must be an integer greater than or equal to zero')
end
end
end
Expand Down

0 comments on commit ded1efc

Please sign in to comment.