openapi-generator icon indicating copy to clipboard operation
openapi-generator copied to clipboard

[BUG] [Ruby] minLength validation fails on `null` nullable strings

Open phoenixy1 opened this issue 1 year ago • 1 comments

Description

Ruby generator applies minLength validation to nullable string fields that are null. Per everything I can find, string validation is not supposed to be applied to null values if the field is nullable, because nullable indicates that the value can be null OR a string. However, the generator is running .to_s on whatever is passed in, even if it is nil, and then validating minLength based on that, which is causing all fields with a specified minLength to fail validation if nil is passed instead of a string. I haven't checked whether this applies to other forms of string properties, like pattern and format, but it seems like there is a risk that it does.

You can see an example here where document_number is marked as nullable: https://github.com/plaid/plaid-ruby/blob/master/lib/plaid/models/watchlist_screening_search_terms.rb#L67

But is still being subjected to a length check even if it's null: https://github.com/plaid/plaid-ruby/blob/master/lib/plaid/models/watchlist_screening_search_terms.rb#L132

openapi-generator version

Using 6.3.0. I did not test on newer libraries, but I did not see a bug fix or existing bug for this submitted anywhere.

OpenAPI declaration file content or url
    WatchlistScreeningDocumentValueNullable:
      type: string
      title: WatchlistScreeningDocumentValue
      minLength: 4
      example: C31195855
      description: The numeric or alphanumeric identifier associated with this document.
      nullable: true
Generation Details
Steps to reproduce
Related issues/PRs

https://github.com/OpenAPITools/openapi-generator/issues/9141 https://github.com/OpenAPITools/openapi-generator/issues/16629

Suggest a fix

Before applying any string-based validation rules, check if the value is nil and if so, automatically pass the validation if the field has nullable:true.

phoenixy1 avatar Jun 17 '24 22:06 phoenixy1

Before applying any string-based validation rules, check if the value is nil and if so, automatically pass the validation if the field has nullable:true.

may I know if you've time to contribute a fix?

ruby model templates can be found in https://github.com/OpenAPITools/openapi-generator/blob/master/modules/openapi-generator/src/main/resources/ruby-client/partial_model_generic.mustache

wing328 avatar Jun 21 '24 08:06 wing328

did a test with the latest master and there's a nil check

@@ -266,6 +275,14 @@ module Petstore
         invalid_properties.push('invalid value for "password", the character length must be great than or equal to 10.')
       end

+      if !@password_nullable.nil? && @password_nullable.to_s.length > 64
+        invalid_properties.push('invalid value for "password_nullable", the character length must be smaller than or equal to 64.')
+      end
+
+      if !@password_nullable.nil? && @password_nullable.to_s.length < 10
+        invalid_properties.push('invalid value for "password_nullable", the character length must be great than or equal to 10.')
+      end
+
       pattern = Regexp.new(/^\d{10}$/)
       if !@pattern_with_digits.nil? && @pattern_with_digits !~ pattern
         invalid_properties.push("invalid value for \"pattern_with_digits\", must conform to the pattern #{pattern}.")
@@ -300,6 +317,8 @@ module Petstore
       return false if @password.nil?
       return false if @password.to_s.length > 64
       return false if @password.to_s.length < 10
+      return false if !@password_nullable.nil? && @password_nullable.to_s.length > 64
+      return false if !@password_nullable.nil? && @password_nullable.to_s.length < 10
       return false if !@pattern_with_digits.nil? && @pattern_with_digits !~ Regexp.new(/^\d{10}$/)
       return false if !@pattern_with_digits_and_delimiter.nil? && @pattern_with_digits_and_delimiter !~ Regexp.new(/^image_\d{1,3}$/i)
       true
@@ -428,6 +447,20 @@ module Petstore
       @password = password
     end

+    # Custom attribute writer method with validation
+    # @param [Object] password_nullable Value to be assigned
+    def password_nullable=(password_nullable)
+      if !password_nullable.nil? && password_nullable.to_s.length > 64
+        fail ArgumentError, 'invalid value for "password_nullable", the character length must be smaller than or equal to 64.'
+      end
+
+      if !password_nullable.nil? && password_nullable.to_s.length < 10
+        fail ArgumentError, 'invalid value for "password_nullable", the character length must be great than or equal to 10.'
+      end
+
+      @password_nullable = password_nullable
+    end


happy to reopen the issue if needed

wing328 avatar Nov 11 '24 09:11 wing328