openapi_parser_firetail 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/ci.yaml +25 -0
  3. data/.gitignore +15 -0
  4. data/.rspec +3 -0
  5. data/.rubocop.yml +13 -0
  6. data/.rubocop_ignore.yml +6 -0
  7. data/.ruby-version +1 -0
  8. data/CHANGELOG.md +132 -0
  9. data/CODE_OF_CONDUCT.md +74 -0
  10. data/Gemfile +6 -0
  11. data/LICENSE.txt +21 -0
  12. data/README.md +112 -0
  13. data/Rakefile +10 -0
  14. data/Steepfile +11 -0
  15. data/bin/console +14 -0
  16. data/bin/setup +8 -0
  17. data/lib/openapi_parser/concern.rb +5 -0
  18. data/lib/openapi_parser/concerns/expandable.rb +87 -0
  19. data/lib/openapi_parser/concerns/findable.rb +54 -0
  20. data/lib/openapi_parser/concerns/media_type_selectable.rb +29 -0
  21. data/lib/openapi_parser/concerns/parameter_validatable.rb +62 -0
  22. data/lib/openapi_parser/concerns/parser/core.rb +21 -0
  23. data/lib/openapi_parser/concerns/parser/hash.rb +10 -0
  24. data/lib/openapi_parser/concerns/parser/hash_body.rb +12 -0
  25. data/lib/openapi_parser/concerns/parser/list.rb +10 -0
  26. data/lib/openapi_parser/concerns/parser/object.rb +14 -0
  27. data/lib/openapi_parser/concerns/parser/value.rb +14 -0
  28. data/lib/openapi_parser/concerns/parser.rb +45 -0
  29. data/lib/openapi_parser/concerns/schema_loader/base.rb +28 -0
  30. data/lib/openapi_parser/concerns/schema_loader/creator.rb +48 -0
  31. data/lib/openapi_parser/concerns/schema_loader/hash_body_loader.rb +37 -0
  32. data/lib/openapi_parser/concerns/schema_loader/hash_objects_loader.rb +29 -0
  33. data/lib/openapi_parser/concerns/schema_loader/list_loader.rb +28 -0
  34. data/lib/openapi_parser/concerns/schema_loader/objects_loader.rb +21 -0
  35. data/lib/openapi_parser/concerns/schema_loader/values_loader.rb +10 -0
  36. data/lib/openapi_parser/concerns/schema_loader.rb +58 -0
  37. data/lib/openapi_parser/config.rb +55 -0
  38. data/lib/openapi_parser/errors.rb +281 -0
  39. data/lib/openapi_parser/parameter_validator.rb +33 -0
  40. data/lib/openapi_parser/path_item_finder.rb +161 -0
  41. data/lib/openapi_parser/reference_expander.rb +9 -0
  42. data/lib/openapi_parser/request_operation.rb +90 -0
  43. data/lib/openapi_parser/schema_validator/all_of_validator.rb +40 -0
  44. data/lib/openapi_parser/schema_validator/any_of_validator.rb +18 -0
  45. data/lib/openapi_parser/schema_validator/array_validator.rb +32 -0
  46. data/lib/openapi_parser/schema_validator/base.rb +39 -0
  47. data/lib/openapi_parser/schema_validator/boolean_validator.rb +29 -0
  48. data/lib/openapi_parser/schema_validator/enumable.rb +13 -0
  49. data/lib/openapi_parser/schema_validator/float_validator.rb +34 -0
  50. data/lib/openapi_parser/schema_validator/integer_validator.rb +32 -0
  51. data/lib/openapi_parser/schema_validator/minimum_maximum.rb +38 -0
  52. data/lib/openapi_parser/schema_validator/nil_validator.rb +11 -0
  53. data/lib/openapi_parser/schema_validator/object_validator.rb +56 -0
  54. data/lib/openapi_parser/schema_validator/one_of_validator.rb +22 -0
  55. data/lib/openapi_parser/schema_validator/options.rb +29 -0
  56. data/lib/openapi_parser/schema_validator/string_validator.rb +108 -0
  57. data/lib/openapi_parser/schema_validator/unspecified_type_validator.rb +8 -0
  58. data/lib/openapi_parser/schema_validator.rb +164 -0
  59. data/lib/openapi_parser/schemas/base.rb +28 -0
  60. data/lib/openapi_parser/schemas/classes.rb +22 -0
  61. data/lib/openapi_parser/schemas/components.rb +32 -0
  62. data/lib/openapi_parser/schemas/discriminator.rb +11 -0
  63. data/lib/openapi_parser/schemas/header.rb +18 -0
  64. data/lib/openapi_parser/schemas/info.rb +6 -0
  65. data/lib/openapi_parser/schemas/media_type.rb +18 -0
  66. data/lib/openapi_parser/schemas/openapi.rb +63 -0
  67. data/lib/openapi_parser/schemas/operation.rb +50 -0
  68. data/lib/openapi_parser/schemas/parameter.rb +20 -0
  69. data/lib/openapi_parser/schemas/path_item.rb +22 -0
  70. data/lib/openapi_parser/schemas/paths.rb +7 -0
  71. data/lib/openapi_parser/schemas/reference.rb +7 -0
  72. data/lib/openapi_parser/schemas/request_body.rb +34 -0
  73. data/lib/openapi_parser/schemas/response.rb +54 -0
  74. data/lib/openapi_parser/schemas/responses.rb +56 -0
  75. data/lib/openapi_parser/schemas/schema.rb +117 -0
  76. data/lib/openapi_parser/schemas/security.rb +7 -0
  77. data/lib/openapi_parser/schemas/security_schemes.rb +20 -0
  78. data/lib/openapi_parser/schemas.rb +20 -0
  79. data/lib/openapi_parser/version.rb +3 -0
  80. data/lib/openapi_parser.rb +108 -0
  81. data/openapi_parser.gemspec +43 -0
  82. data/sig/openapi_parser/config.rbs +19 -0
  83. data/sig/openapi_parser/errors.rbs +22 -0
  84. data/sig/openapi_parser/reference_expander.rbs +3 -0
  85. data/sig/openapi_parser/schema_validator.rbs +46 -0
  86. data/sig/openapi_parser/schema_validators/base.rbs +18 -0
  87. data/sig/openapi_parser/schema_validators/options.rbs +17 -0
  88. data/sig/openapi_parser/schemas/base.rbs +17 -0
  89. data/sig/openapi_parser/version.rbs +3 -0
  90. data/sig/openapi_parser.rbs +19 -0
  91. data/sig/types.rbs +13 -0
  92. data/sig/wip_types.rbs +64 -0
  93. metadata +288 -0
@@ -0,0 +1,39 @@
1
+ class OpenAPIParser::SchemaValidator
2
+ class Base
3
+ def initialize(validatable, coerce_value)
4
+ @validatable = validatable
5
+ @coerce_value = coerce_value
6
+ end
7
+
8
+ attr_reader :validatable
9
+
10
+ # need override
11
+ def coerce_and_validate(_value, _schema, **_keyword_args)
12
+ raise 'need implement'
13
+ end
14
+
15
+ def validate_discriminator_schema(discriminator, value, parent_discriminator_schemas: [])
16
+ property_name = discriminator.property_name
17
+ if property_name.nil? || !value.key?(property_name)
18
+ return [nil, OpenAPIParser::NotExistDiscriminatorPropertyName.new(discriminator.property_name, value, discriminator.object_reference)]
19
+ end
20
+ mapping_key = value[property_name]
21
+
22
+ # it's allowed to have discriminator without mapping, then we need to lookup discriminator.property_name
23
+ # but the format is not the full path, just model name in the components
24
+ mapping_target = discriminator.mapping&.[](mapping_key) || "#/components/schemas/#{mapping_key}"
25
+
26
+ # Find object does O(n) search at worst, then caches the result, so this is ok for repeated search
27
+ resolved_schema = discriminator.root.find_object(mapping_target)
28
+
29
+ unless resolved_schema
30
+ return [nil, OpenAPIParser::NotExistDiscriminatorMappedSchema.new(mapping_target, discriminator.object_reference)]
31
+ end
32
+ validatable.validate_schema(
33
+ value,
34
+ resolved_schema,
35
+ **{discriminator_property_name: discriminator.property_name, parent_discriminator_schemas: parent_discriminator_schemas}
36
+ )
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,29 @@
1
+ class OpenAPIParser::SchemaValidator
2
+ class BooleanValidator < Base
3
+ include ::OpenAPIParser::SchemaValidator::Enumable
4
+
5
+ TRUE_VALUES = ['true', '1'].freeze
6
+ FALSE_VALUES = ['false', '0'].freeze
7
+
8
+ def coerce_and_validate(value, schema, **_keyword_args)
9
+ value = coerce(value) if @coerce_value
10
+
11
+ return OpenAPIParser::ValidateError.build_error_result(value, schema) unless value.kind_of?(TrueClass) || value.kind_of?(FalseClass)
12
+
13
+ value, err = check_enum_include(value, schema)
14
+ return [nil, err] if err
15
+
16
+ [value, nil]
17
+ end
18
+
19
+ private
20
+
21
+ def coerce(value)
22
+ return true if TRUE_VALUES.include?(value)
23
+
24
+ return false if FALSE_VALUES.include?(value)
25
+
26
+ value
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,13 @@
1
+ class OpenAPIParser::SchemaValidator
2
+ module Enumable
3
+ # check enum value by schema
4
+ # @param [Object] value
5
+ # @param [OpenAPIParser::Schemas::Schema] schema
6
+ def check_enum_include(value, schema)
7
+ return [value, nil] unless schema.enum
8
+ return [value, nil] if schema.enum.include?(value)
9
+
10
+ [nil, OpenAPIParser::NotEnumInclude.new(value, schema.object_reference)]
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,34 @@
1
+ class OpenAPIParser::SchemaValidator
2
+ class FloatValidator < Base
3
+ include ::OpenAPIParser::SchemaValidator::Enumable
4
+ include ::OpenAPIParser::SchemaValidator::MinimumMaximum
5
+
6
+ # validate float value by schema
7
+ # @param [Object] value
8
+ # @param [OpenAPIParser::Schemas::Schema] schema
9
+ def coerce_and_validate(value, schema, **_keyword_args)
10
+ value = coerce(value) if @coerce_value
11
+
12
+ return validatable.validate_integer(value, schema) if value.kind_of?(Integer)
13
+
14
+ coercer_and_validate_numeric(value, schema)
15
+ end
16
+
17
+ private
18
+
19
+ def coercer_and_validate_numeric(value, schema)
20
+ return OpenAPIParser::ValidateError.build_error_result(value, schema) unless value.kind_of?(Numeric)
21
+
22
+ value, err = check_enum_include(value, schema)
23
+ return [nil, err] if err
24
+
25
+ check_minimum_maximum(value, schema)
26
+ end
27
+
28
+ def coerce(value)
29
+ Float(value)
30
+ rescue ArgumentError, TypeError
31
+ value
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,32 @@
1
+ class OpenAPIParser::SchemaValidator
2
+ class IntegerValidator < Base
3
+ include ::OpenAPIParser::SchemaValidator::Enumable
4
+ include ::OpenAPIParser::SchemaValidator::MinimumMaximum
5
+
6
+ # validate integer value by schema
7
+ # @param [Object] value
8
+ # @param [OpenAPIParser::Schemas::Schema] schema
9
+ def coerce_and_validate(value, schema, **_keyword_args)
10
+ value = coerce(value) if @coerce_value
11
+
12
+ return OpenAPIParser::ValidateError.build_error_result(value, schema) unless value.kind_of?(Integer)
13
+
14
+ value, err = check_enum_include(value, schema)
15
+ return [nil, err] if err
16
+
17
+ check_minimum_maximum(value, schema)
18
+ end
19
+
20
+ private
21
+
22
+ def coerce(value)
23
+ return value if value.kind_of?(Integer)
24
+
25
+ begin
26
+ Integer(value)
27
+ rescue ArgumentError, TypeError
28
+ value
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,38 @@
1
+ class OpenAPIParser::SchemaValidator
2
+ module MinimumMaximum
3
+ # check minimum and maximum value by schema
4
+ # @param [Object] value
5
+ # @param [OpenAPIParser::Schemas::Schema] schema
6
+ def check_minimum_maximum(value, schema)
7
+ include_min_max = schema.minimum || schema.maximum
8
+ return [value, nil] unless include_min_max
9
+
10
+ validate(value, schema)
11
+ [value, nil]
12
+ rescue OpenAPIParser::OpenAPIError => e
13
+ return [nil, e]
14
+ end
15
+
16
+ private
17
+
18
+ def validate(value, schema)
19
+ reference = schema.object_reference
20
+
21
+ if schema.minimum
22
+ if schema.exclusiveMinimum && value <= schema.minimum
23
+ raise OpenAPIParser::LessThanExclusiveMinimum.new(value, reference)
24
+ elsif value < schema.minimum
25
+ raise OpenAPIParser::LessThanMinimum.new(value, reference)
26
+ end
27
+ end
28
+
29
+ if schema.maximum
30
+ if schema.exclusiveMaximum && value >= schema.maximum
31
+ raise OpenAPIParser::MoreThanExclusiveMaximum.new(value, reference)
32
+ elsif value > schema.maximum
33
+ raise OpenAPIParser::MoreThanMaximum.new(value, reference)
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,11 @@
1
+ class OpenAPIParser::SchemaValidator
2
+ class NilValidator < Base
3
+ # @param [Object] value
4
+ # @param [OpenAPIParser::Schemas::Schema] schema
5
+ def coerce_and_validate(value, schema, **_keyword_args)
6
+ return [value, nil] if schema.nullable
7
+
8
+ [nil, OpenAPIParser::NotNullError.new(schema.object_reference)]
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,56 @@
1
+ class OpenAPIParser::SchemaValidator
2
+ class ObjectValidator < Base
3
+ # @param [Hash] value
4
+ # @param [OpenAPIParser::Schemas::Schema] schema
5
+ # @param [Boolean] parent_all_of true if component is nested under allOf
6
+ # @param [String, nil] discriminator_property_name discriminator.property_name to ignore checking additional_properties
7
+ def coerce_and_validate(value, schema, parent_all_of: false, parent_discriminator_schemas: [], discriminator_property_name: nil)
8
+ return OpenAPIParser::ValidateError.build_error_result(value, schema) unless value.kind_of?(Hash)
9
+
10
+ properties = schema.properties || {}
11
+
12
+ required_set = schema.required ? schema.required.to_set : Set.new
13
+ remaining_keys = value.keys
14
+
15
+ if schema.discriminator && !parent_discriminator_schemas.include?(schema)
16
+ return validate_discriminator_schema(
17
+ schema.discriminator,
18
+ value,
19
+ parent_discriminator_schemas: parent_discriminator_schemas + [schema]
20
+ )
21
+ else
22
+ remaining_keys.delete('discriminator')
23
+ end
24
+
25
+ coerced_values = value.map do |name, v|
26
+ s = properties[name]
27
+ coerced, err = if s
28
+ remaining_keys.delete(name)
29
+ validatable.validate_schema(v, s)
30
+ else
31
+ # TODO: we need to perform a validation based on schema.additional_properties here, if
32
+ # additionalProperties are defined
33
+ [v, nil]
34
+ end
35
+
36
+ return [nil, err] if err
37
+
38
+ required_set.delete(name)
39
+ [name, coerced]
40
+ end
41
+
42
+ remaining_keys.delete(discriminator_property_name) if discriminator_property_name
43
+
44
+ if !remaining_keys.empty? && !parent_all_of && !schema.additional_properties
45
+ # If object is nested in all of, the validation is already done in allOf validator. Or if
46
+ # additionalProperties are defined, we will validate using that
47
+ return [nil, OpenAPIParser::NotExistPropertyDefinition.new(remaining_keys, schema.object_reference)]
48
+ end
49
+ return [nil, OpenAPIParser::NotExistRequiredKey.new(required_set.to_a, schema.object_reference)] unless required_set.empty?
50
+
51
+ value.merge!(coerced_values.to_h) if @coerce_value
52
+
53
+ [value, nil]
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,22 @@
1
+ class OpenAPIParser::SchemaValidator
2
+ class OneOfValidator < Base
3
+ # @param [Object] value
4
+ # @param [OpenAPIParser::Schemas::Schema] schema
5
+ def coerce_and_validate(value, schema, **_keyword_args)
6
+ if schema.discriminator
7
+ return validate_discriminator_schema(schema.discriminator, value)
8
+ end
9
+
10
+ # if multiple schemas are satisfied, it's not valid
11
+ result = schema.one_of.one? do |s|
12
+ _coerced, err = validatable.validate_schema(value, s)
13
+ err.nil?
14
+ end
15
+ if result
16
+ [value, nil]
17
+ else
18
+ [nil, OpenAPIParser::NotOneOf.new(value, schema.object_reference)]
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,29 @@
1
+ class OpenAPIParser::SchemaValidator
2
+ class Options
3
+ # @!attribute [r] coerce_value
4
+ # @return [Boolean] coerce value option on/off
5
+ # @!attribute [r] datetime_coerce_class
6
+ # @return [Object, nil] coerce datetime string by this Object class
7
+ # @!attribute [r] validate_header
8
+ # @return [Boolean] validate header or not
9
+ attr_reader :coerce_value, :datetime_coerce_class, :validate_header
10
+
11
+ def initialize(coerce_value: nil, datetime_coerce_class: nil, validate_header: true)
12
+ @coerce_value = coerce_value
13
+ @datetime_coerce_class = datetime_coerce_class
14
+ @validate_header = validate_header
15
+ end
16
+ end
17
+
18
+ # response body validation option
19
+ class ResponseValidateOptions
20
+ # @!attribute [r] strict
21
+ # @return [Boolean] validate by strict (when not exist definition, raise error)
22
+ attr_reader :strict, :validate_header
23
+
24
+ def initialize(strict: false, validate_header: true)
25
+ @strict = strict
26
+ @validate_header = validate_header
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,108 @@
1
+ class OpenAPIParser::SchemaValidator
2
+ class StringValidator < Base
3
+ include ::OpenAPIParser::SchemaValidator::Enumable
4
+
5
+ def initialize(validator, coerce_value, datetime_coerce_class)
6
+ super(validator, coerce_value)
7
+ @datetime_coerce_class = datetime_coerce_class
8
+ end
9
+
10
+ def coerce_and_validate(value, schema, **_keyword_args)
11
+ return OpenAPIParser::ValidateError.build_error_result(value, schema) unless value.kind_of?(String)
12
+
13
+ value, err = check_enum_include(value, schema)
14
+ return [nil, err] if err
15
+
16
+ value, err = pattern_validate(value, schema)
17
+ return [nil, err] if err
18
+
19
+ value, err = validate_max_min_length(value, schema)
20
+ return [nil, err] if err
21
+
22
+ value, err = validate_email_format(value, schema)
23
+ return [nil, err] if err
24
+
25
+ value, err = validate_uuid_format(value, schema)
26
+ return [nil, err] if err
27
+
28
+ value, err = validate_date_format(value, schema)
29
+ return [nil, err] if err
30
+
31
+ value, err = validate_datetime_format(value, schema)
32
+ return [nil, err] if err
33
+
34
+ [value, nil]
35
+ end
36
+
37
+ private
38
+
39
+ # @param [OpenAPIParser::Schemas::Schema] schema
40
+ def pattern_validate(value, schema)
41
+ # pattern support string only so put this
42
+ return [value, nil] unless schema.pattern
43
+ return [value, nil] if value =~ /#{schema.pattern}/
44
+
45
+ [nil, OpenAPIParser::InvalidPattern.new(value, schema.pattern, schema.object_reference, schema.example)]
46
+ end
47
+
48
+ def validate_max_min_length(value, schema)
49
+ return [nil, OpenAPIParser::MoreThanMaxLength.new(value, schema.object_reference)] if schema.maxLength && value.size > schema.maxLength
50
+ return [nil, OpenAPIParser::LessThanMinLength.new(value, schema.object_reference)] if schema.minLength && value.size < schema.minLength
51
+
52
+ [value, nil]
53
+ end
54
+
55
+ def validate_email_format(value, schema)
56
+ return [value, nil] unless schema.format == 'email'
57
+
58
+ # match? method is good performance.
59
+ # So when we drop ruby 2.3 support we use match? method because this method add ruby 2.4
60
+ #return [value, nil] if value.match?(URI::MailTo::EMAIL_REGEXP)
61
+ return [value, nil] if value.match(URI::MailTo::EMAIL_REGEXP)
62
+
63
+ return [nil, OpenAPIParser::InvalidEmailFormat.new(value, schema.object_reference)]
64
+ end
65
+
66
+ def validate_uuid_format(value, schema)
67
+ return [value, nil] unless schema.format == 'uuid'
68
+
69
+ return [value, nil] if value.match(/[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}/)
70
+
71
+ return [nil, OpenAPIParser::InvalidUUIDFormat.new(value, schema.object_reference)]
72
+ end
73
+
74
+ def validate_date_format(value, schema)
75
+ return [value, nil] unless schema.format == 'date'
76
+
77
+ begin
78
+ Date.strptime(value, "%Y-%m-%d")
79
+ rescue ArgumentError
80
+ return [nil, OpenAPIParser::InvalidDateFormat.new(value, schema.object_reference)]
81
+ end
82
+
83
+ return [value, nil]
84
+ end
85
+
86
+ def validate_datetime_format(value, schema)
87
+ return [value, nil] unless schema.format == 'date-time'
88
+
89
+ begin
90
+ if @datetime_coerce_class.nil?
91
+ # validate only
92
+ DateTime.rfc3339(value)
93
+ [value, nil]
94
+ else
95
+ # validate and coerce
96
+ if @datetime_coerce_class == Time
97
+ [DateTime.rfc3339(value).to_time, nil]
98
+ else
99
+ [@datetime_coerce_class.rfc3339(value), nil]
100
+ end
101
+ end
102
+ rescue ArgumentError
103
+ # when rfc3339(value) failed
104
+ [nil, OpenAPIParser::InvalidDateTimeFormat.new(value, schema.object_reference)]
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,8 @@
1
+ class OpenAPIParser::SchemaValidator
2
+ class UnspecifiedTypeValidator < Base
3
+ # @param [Object] value
4
+ def coerce_and_validate(value, _schema, **_keyword_args)
5
+ [value, nil]
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,164 @@
1
+ require_relative 'schema_validator/options'
2
+ require_relative 'schema_validator/enumable'
3
+ require_relative 'schema_validator/minimum_maximum'
4
+ require_relative 'schema_validator/base'
5
+ require_relative 'schema_validator/string_validator'
6
+ require_relative 'schema_validator/integer_validator'
7
+ require_relative 'schema_validator/float_validator'
8
+ require_relative 'schema_validator/boolean_validator'
9
+ require_relative 'schema_validator/object_validator'
10
+ require_relative 'schema_validator/array_validator'
11
+ require_relative 'schema_validator/any_of_validator'
12
+ require_relative 'schema_validator/all_of_validator'
13
+ require_relative 'schema_validator/one_of_validator'
14
+ require_relative 'schema_validator/nil_validator'
15
+ require_relative 'schema_validator/unspecified_type_validator'
16
+
17
+ class OpenAPIParser::SchemaValidator
18
+ # validate value by schema
19
+ # this module for SchemaValidators::Base
20
+ # @param [Object] value
21
+ # @param [OpenAPIParser::Schemas::Schema] schema
22
+ module Validatable
23
+ def validate_schema(value, schema, **keyword_args)
24
+ raise 'implement'
25
+ end
26
+
27
+ # validate integer value by schema
28
+ # this method use from float_validator because number allow float and integer
29
+ # @param [Object] _value
30
+ # @param [OpenAPIParser::Schemas::Schema] _schema
31
+ def validate_integer(_value, _schema)
32
+ raise 'implement'
33
+ end
34
+ end
35
+
36
+ include Validatable
37
+
38
+ class << self
39
+ # validate schema data
40
+ # @param [Hash] value
41
+ # @param [OpenAPIParser::Schemas:v:Schema]
42
+ # @param [OpenAPIParser::SchemaValidator::Options] options
43
+ # @return [Object] coerced or original params
44
+ def validate(value, schema, options)
45
+ new(value, schema, options).validate_data
46
+ end
47
+ end
48
+
49
+ # @param [Hash] value
50
+ # @param [OpenAPIParser::Schemas::Schema] schema
51
+ # @param [OpenAPIParser::SchemaValidator::Options] options
52
+ def initialize(value, schema, options)
53
+ @value = value
54
+ @schema = schema
55
+ @coerce_value = options.coerce_value
56
+ @datetime_coerce_class = options.datetime_coerce_class
57
+ end
58
+
59
+ # execute validate data
60
+ # @return [Object] coerced or original params
61
+ def validate_data
62
+ coerced, err = validate_schema(@value, @schema)
63
+ raise err if err
64
+
65
+ coerced
66
+ end
67
+
68
+ # validate value eby schema
69
+ # @param [Object] value
70
+ # @param [OpenAPIParser::Schemas::Schema] schema
71
+ def validate_schema(value, schema, **keyword_args)
72
+ return [value, nil] unless schema
73
+
74
+ if (v = validator(value, schema))
75
+ if keyword_args.empty?
76
+ return v.coerce_and_validate(value, schema)
77
+ else
78
+ return v.coerce_and_validate(value, schema, **keyword_args)
79
+ end
80
+ end
81
+
82
+ # unknown return error
83
+ OpenAPIParser::ValidateError.build_error_result(value, schema)
84
+ end
85
+
86
+ # validate integer value by schema
87
+ # this method use from float_validator because number allow float and integer
88
+ # @param [Object] value
89
+ # @param [OpenAPIParser::Schemas::Schema] schema
90
+ def validate_integer(value, schema)
91
+ integer_validator.coerce_and_validate(value, schema)
92
+ end
93
+
94
+ private
95
+
96
+ # @return [OpenAPIParser::SchemaValidator::Base, nil]
97
+ def validator(value, schema)
98
+ return any_of_validator if schema.any_of
99
+ return all_of_validator if schema.all_of
100
+ return one_of_validator if schema.one_of
101
+ return nil_validator if value.nil?
102
+
103
+ case schema.type
104
+ when 'string'
105
+ string_validator
106
+ when 'integer'
107
+ integer_validator
108
+ when 'boolean'
109
+ boolean_validator
110
+ when 'number'
111
+ float_validator
112
+ when 'object'
113
+ object_validator
114
+ when 'array'
115
+ array_validator
116
+ else
117
+ unspecified_type_validator
118
+ end
119
+ end
120
+
121
+ def string_validator
122
+ @string_validator ||= OpenAPIParser::SchemaValidator::StringValidator.new(self, @coerce_value, @datetime_coerce_class)
123
+ end
124
+
125
+ def integer_validator
126
+ @integer_validator ||= OpenAPIParser::SchemaValidator::IntegerValidator.new(self, @coerce_value)
127
+ end
128
+
129
+ def float_validator
130
+ @float_validator ||= OpenAPIParser::SchemaValidator::FloatValidator.new(self, @coerce_value)
131
+ end
132
+
133
+ def boolean_validator
134
+ @boolean_validator ||= OpenAPIParser::SchemaValidator::BooleanValidator.new(self, @coerce_value)
135
+ end
136
+
137
+ def object_validator
138
+ @object_validator ||= OpenAPIParser::SchemaValidator::ObjectValidator.new(self, @coerce_value)
139
+ end
140
+
141
+ def array_validator
142
+ @array_validator ||= OpenAPIParser::SchemaValidator::ArrayValidator.new(self, @coerce_value)
143
+ end
144
+
145
+ def any_of_validator
146
+ @any_of_validator ||= OpenAPIParser::SchemaValidator::AnyOfValidator.new(self, @coerce_value)
147
+ end
148
+
149
+ def all_of_validator
150
+ @all_of_validator ||= OpenAPIParser::SchemaValidator::AllOfValidator.new(self, @coerce_value)
151
+ end
152
+
153
+ def one_of_validator
154
+ @one_of_validator ||= OpenAPIParser::SchemaValidator::OneOfValidator.new(self, @coerce_value)
155
+ end
156
+
157
+ def nil_validator
158
+ @nil_validator ||= OpenAPIParser::SchemaValidator::NilValidator.new(self, @coerce_value)
159
+ end
160
+
161
+ def unspecified_type_validator
162
+ @unspecified_type_validator ||= OpenAPIParser::SchemaValidator::UnspecifiedTypeValidator.new(self, @coerce_value)
163
+ end
164
+ end
@@ -0,0 +1,28 @@
1
+ module OpenAPIParser::Schemas
2
+ class Base
3
+ include OpenAPIParser::Parser
4
+ include OpenAPIParser::Findable
5
+ include OpenAPIParser::Expandable
6
+
7
+ attr_reader :parent, :raw_schema, :object_reference, :root
8
+
9
+ # @param [OpenAPIParser::Schemas::Base]
10
+ def initialize(object_reference, parent, root, raw_schema)
11
+ @raw_schema = raw_schema
12
+ @parent = parent
13
+ @root = root
14
+ @object_reference = object_reference
15
+
16
+ load_data
17
+ after_init
18
+ end
19
+
20
+ # override
21
+ def after_init
22
+ end
23
+
24
+ def inspect
25
+ @object_reference
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,22 @@
1
+ # We want to use class name for DSL in class definition so we should define first...
2
+
3
+ module OpenAPIParser::Schemas
4
+ class Base; end
5
+ class Discriminator < Base; end
6
+ class OpenAPI < Base; end
7
+ class Operation < Base; end
8
+ class Parameter < Base; end
9
+ class PathItem < Base; end
10
+ class Paths < Base; end
11
+ class Reference < Base; end
12
+ class RequestBody < Base; end
13
+ class Responses < Base; end
14
+ class Response < Base; end
15
+ class MediaType < Base; end
16
+ class Schema < Base; end
17
+ class Components < Base; end
18
+ class Header < Base; end
19
+ class SecuritySchemes < Base; end
20
+ class Info < Base; end
21
+ class Security < Base; end
22
+ end
@@ -0,0 +1,32 @@
1
+ # TODO: examples
2
+ # TODO: securitySchemes
3
+ # TODO: links
4
+ # TODO: callbacks
5
+
6
+ module OpenAPIParser::Schemas
7
+ class Components < Base
8
+ # @!attribute [r] parameters
9
+ # @return [Hash{String => Parameter}, nil]
10
+ openapi_attr_hash_object :parameters, Parameter, reference: true
11
+
12
+ # @!attribute [r] parameters
13
+ # @return [Hash{String => Parameter}, nil]
14
+ openapi_attr_hash_object :schemas, Schema, reference: true
15
+
16
+ # @!attribute [r] responses
17
+ # @return [Hash{String => Response}, nil]
18
+ openapi_attr_hash_object :responses, Response, reference: true
19
+
20
+ # @!attribute [r] request_bodies
21
+ # @return [Hash{String => RequestBody}, nil]
22
+ openapi_attr_hash_object :request_bodies, RequestBody, reference: true, schema_key: :requestBodies
23
+
24
+ # @!attribute [r] headers
25
+ # @return [Hash{String => Header}, nil] header objects
26
+ openapi_attr_hash_object :headers, Header, reference: true
27
+
28
+ # @!attribute [r] security_schemes
29
+ # @return [Hash{String => Header}, nil]
30
+ openapi_attr_hash_object :security_schemes, SecuritySchemes, reference: true, schema_key: :securitySchemes
31
+ end
32
+ end