diff --git a/lib/openapi_parser.rb b/lib/openapi_parser.rb index 011d46a..92a161b 100644 --- a/lib/openapi_parser.rb +++ b/lib/openapi_parser.rb @@ -82,13 +82,13 @@ def parse_file(content, ext) def parse_yaml(content) # FIXME: when drop ruby 2.5, we should use permitted_classes - (Gem::Version.create(RUBY_VERSION) < Gem::Version.create("2.6.0")) ? - Psych.safe_load(content, [Date, Time]) : + (Gem::Version.create(RUBY_VERSION) < Gem::Version.create("2.6.0")) ? + Psych.safe_load(content, [Date, Time]) : Psych.safe_load(content, permitted_classes: [Date, Time]) end def parse_json(content) - raise "json content is nil" unless content + raise "json content is nil" unless content JSON.parse(content) end diff --git a/lib/openapi_parser/config.rb b/lib/openapi_parser/config.rb index faf6008..c8cf490 100644 --- a/lib/openapi_parser/config.rb +++ b/lib/openapi_parser/config.rb @@ -37,11 +37,17 @@ def validate_header @config.fetch(:validate_header, true) end + # TODO: in a major version update, change this to default to `ignore`. + def handle_readOnly + @config.fetch(:handle_readOnly, nil) + end + # @return [OpenAPIParser::SchemaValidator::Options] def request_validator_options @request_validator_options ||= OpenAPIParser::SchemaValidator::Options.new(coerce_value: coerce_value, datetime_coerce_class: datetime_coerce_class, - validate_header: validate_header) + validate_header: validate_header, + handle_readOnly: handle_readOnly) end alias_method :request_body_options, :request_validator_options diff --git a/lib/openapi_parser/schema_validator.rb b/lib/openapi_parser/schema_validator.rb index fd9d2af..aa5c1af 100644 --- a/lib/openapi_parser/schema_validator.rb +++ b/lib/openapi_parser/schema_validator.rb @@ -54,6 +54,7 @@ def initialize(value, schema, options) @schema = schema @coerce_value = options.coerce_value @datetime_coerce_class = options.datetime_coerce_class + @handle_readOnly = options.handle_readOnly end # execute validate data @@ -135,7 +136,7 @@ def boolean_validator end def object_validator - @object_validator ||= OpenAPIParser::SchemaValidator::ObjectValidator.new(self, @coerce_value) + @object_validator ||= OpenAPIParser::SchemaValidator::ObjectValidator.new(self, @coerce_value, @handle_readOnly) end def array_validator diff --git a/lib/openapi_parser/schema_validator/object_validator.rb b/lib/openapi_parser/schema_validator/object_validator.rb index 1ee355e..1e3be21 100644 --- a/lib/openapi_parser/schema_validator/object_validator.rb +++ b/lib/openapi_parser/schema_validator/object_validator.rb @@ -1,5 +1,10 @@ class OpenAPIParser::SchemaValidator class ObjectValidator < Base + + def initialize(validator, coerce_value, handle_readOnly) + super(validator, coerce_value) + @handle_readOnly = handle_readOnly + end # @param [Hash] value # @param [OpenAPIParser::Schemas::Schema] schema # @param [Boolean] parent_all_of true if component is nested under allOf @@ -10,6 +15,15 @@ def coerce_and_validate(value, schema, parent_all_of: false, parent_discriminato properties = schema.properties || {} required_set = schema.required ? schema.required.to_set : Set.new + + if @handle_readOnly == :ignore + schema.properties.each do |name, property_value| + next unless property_value.read_only + required_set.delete(name) + value.delete(name) + end + end + remaining_keys = value.keys if schema.discriminator && !parent_discriminator_schemas.include?(schema) diff --git a/lib/openapi_parser/schema_validator/options.rb b/lib/openapi_parser/schema_validator/options.rb index 6824f03..0d24aea 100644 --- a/lib/openapi_parser/schema_validator/options.rb +++ b/lib/openapi_parser/schema_validator/options.rb @@ -6,12 +6,15 @@ class Options # @return [Object, nil] coerce datetime string by this Object class # @!attribute [r] validate_header # @return [Boolean] validate header or not - attr_reader :coerce_value, :datetime_coerce_class, :validate_header + # @!attribute [r] handle_readOnly + # @return [Object, nil] How to use readOnly property to process requests. Either :ignore or :raise + attr_reader :coerce_value, :datetime_coerce_class, :validate_header, :handle_readOnly - def initialize(coerce_value: nil, datetime_coerce_class: nil, validate_header: true) + def initialize(coerce_value: nil, datetime_coerce_class: nil, validate_header: true, handle_readOnly: nil) @coerce_value = coerce_value @datetime_coerce_class = datetime_coerce_class @validate_header = validate_header + @handle_readOnly = handle_readOnly end end