From c061898b4201967f57b9ccbe73c14da167c23b97 Mon Sep 17 00:00:00 2001 From: Vasily Fedoseyev Date: Thu, 21 Jul 2022 21:51:16 +0300 Subject: [PATCH] Check for dry-types type existence and prevent top level const lookup --- CHANGELOG.md | 1 + .../validations/types/primitive_coercer.rb | 18 ++++++++++++------ .../types/primitive_coercer_spec.rb | 9 +++++++++ 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 01811fc15d..f1be3b1d96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ * [#2249](https://github.com/ruby-grape/grape/pull/2251): Upgraded to RuboCop 1.25.1 - [@dblock](https://github.com/dblock). * [#2271](https://github.com/ruby-grape/grape/pull/2271): Fixed validation regression on Numeric type introduced in 1.3 - [@vasfed](https://github.com/Vasfed). * [#2267](https://github.com/ruby-grape/grape/pull/2267): Standardized English error messages - [@dblock](https://github.com/dblock). +* [#2272](https://github.com/ruby-grape/grape/pull/2272): Added error on param init when provided type does not have `[]` coercion method, previously validation silently failed for any value - [@vasfed](https://github.com/Vasfed). * Your contribution here. #### Fixes diff --git a/lib/grape/validations/types/primitive_coercer.rb b/lib/grape/validations/types/primitive_coercer.rb index 58fd77743c..e2e3f9df54 100644 --- a/lib/grape/validations/types/primitive_coercer.rb +++ b/lib/grape/validations/types/primitive_coercer.rb @@ -13,6 +13,8 @@ class PrimitiveCoercer < DryTypeCoercer Grape::API::Boolean => DryTypes::Params::Bool, BigDecimal => DryTypes::Params::Decimal, Numeric => DryTypes::Params::Integer | DryTypes::Params::Float | DryTypes::Params::Decimal, + TrueClass => DryTypes::Params::Bool.constrained(eql: true), + FalseClass => DryTypes::Params::Bool.constrained(eql: false), # unfortunately, a +Params+ scope doesn't contain String String => DryTypes::Coercible::String @@ -21,7 +23,9 @@ class PrimitiveCoercer < DryTypeCoercer STRICT_MAPPING = { Grape::API::Boolean => DryTypes::Strict::Bool, BigDecimal => DryTypes::Strict::Decimal, - Numeric => DryTypes::Strict::Integer | DryTypes::Strict::Float | DryTypes::Strict::Decimal + Numeric => DryTypes::Strict::Integer | DryTypes::Strict::Float | DryTypes::Strict::Decimal, + TrueClass => DryTypes::Strict::Bool.constrained(eql: true), + FalseClass => DryTypes::Strict::Bool.constrained(eql: false) }.freeze def initialize(type, strict = false) @@ -29,11 +33,13 @@ def initialize(type, strict = false) @type = type - @coercer = if strict - STRICT_MAPPING.fetch(type) { scope.const_get(type.name) } - else - MAPPING.fetch(type) { scope.const_get(type.name) } - end + @coercer = (strict ? STRICT_MAPPING : MAPPING).fetch(type) do + scope.const_get(type.name, false) + rescue NameError + raise ArgumentError, "type #{type} should support coercion via `[]`" unless type.respond_to?(:[]) + + type + end end def call(val) diff --git a/spec/grape/validations/types/primitive_coercer_spec.rb b/spec/grape/validations/types/primitive_coercer_spec.rb index 11b28fcdcb..cc0dd19959 100644 --- a/spec/grape/validations/types/primitive_coercer_spec.rb +++ b/spec/grape/validations/types/primitive_coercer_spec.rb @@ -110,6 +110,15 @@ end end + context 'a type unknown in Dry-types' do + let(:type) { Complex } + + it 'raises error on init' do + expect(DryTypes::Params.constants).not_to include(type.name.to_sym) + expect { subject }.to raise_error(/type Complex should support coercion/) + end + end + context 'the strict mode' do let(:strict) { true }