committee 3.1.0 → 3.1.1

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 (78) hide show
  1. checksums.yaml +4 -4
  2. data/bin/committee-stub +1 -0
  3. data/lib/committee.rb +12 -34
  4. data/lib/committee/bin/committee_stub.rb +6 -4
  5. data/lib/committee/drivers.rb +15 -67
  6. data/lib/committee/drivers/driver.rb +47 -0
  7. data/lib/committee/drivers/hyper_schema.rb +8 -171
  8. data/lib/committee/drivers/hyper_schema/driver.rb +105 -0
  9. data/lib/committee/drivers/hyper_schema/link.rb +68 -0
  10. data/lib/committee/drivers/hyper_schema/schema.rb +22 -0
  11. data/lib/committee/drivers/open_api_2.rb +9 -416
  12. data/lib/committee/drivers/open_api_2/driver.rb +253 -0
  13. data/lib/committee/drivers/open_api_2/header_schema_builder.rb +33 -0
  14. data/lib/committee/drivers/open_api_2/link.rb +36 -0
  15. data/lib/committee/drivers/open_api_2/parameter_schema_builder.rb +83 -0
  16. data/lib/committee/drivers/open_api_2/schema.rb +26 -0
  17. data/lib/committee/drivers/open_api_2/schema_builder.rb +33 -0
  18. data/lib/committee/drivers/open_api_3.rb +7 -75
  19. data/lib/committee/drivers/open_api_3/driver.rb +51 -0
  20. data/lib/committee/drivers/open_api_3/schema.rb +41 -0
  21. data/lib/committee/drivers/schema.rb +23 -0
  22. data/lib/committee/errors.rb +2 -0
  23. data/lib/committee/middleware.rb +11 -0
  24. data/lib/committee/middleware/base.rb +38 -34
  25. data/lib/committee/middleware/request_validation.rb +51 -30
  26. data/lib/committee/middleware/response_validation.rb +49 -26
  27. data/lib/committee/middleware/stub.rb +55 -51
  28. data/lib/committee/request_unpacker.rb +3 -1
  29. data/lib/committee/schema_validator.rb +23 -0
  30. data/lib/committee/schema_validator/hyper_schema.rb +85 -74
  31. data/lib/committee/schema_validator/hyper_schema/parameter_coercer.rb +60 -54
  32. data/lib/committee/schema_validator/hyper_schema/request_validator.rb +43 -37
  33. data/lib/committee/schema_validator/hyper_schema/response_generator.rb +86 -80
  34. data/lib/committee/schema_validator/hyper_schema/response_validator.rb +65 -59
  35. data/lib/committee/schema_validator/hyper_schema/router.rb +35 -29
  36. data/lib/committee/schema_validator/hyper_schema/string_params_coercer.rb +87 -81
  37. data/lib/committee/schema_validator/open_api_3.rb +71 -61
  38. data/lib/committee/schema_validator/open_api_3/operation_wrapper.rb +121 -115
  39. data/lib/committee/schema_validator/open_api_3/request_validator.rb +24 -18
  40. data/lib/committee/schema_validator/open_api_3/response_validator.rb +22 -16
  41. data/lib/committee/schema_validator/open_api_3/router.rb +30 -24
  42. data/lib/committee/schema_validator/option.rb +42 -38
  43. data/lib/committee/test/methods.rb +55 -51
  44. data/lib/committee/validation_error.rb +2 -0
  45. data/test/bin/committee_stub_test.rb +3 -1
  46. data/test/bin_test.rb +3 -1
  47. data/test/committee_test.rb +3 -1
  48. data/test/drivers/hyper_schema/driver_test.rb +49 -0
  49. data/test/drivers/{hyper_schema_test.rb → hyper_schema/link_test.rb} +2 -45
  50. data/test/drivers/open_api_2/driver_test.rb +156 -0
  51. data/test/drivers/open_api_2/header_schema_builder_test.rb +26 -0
  52. data/test/drivers/open_api_2/link_test.rb +52 -0
  53. data/test/drivers/open_api_2/parameter_schema_builder_test.rb +195 -0
  54. data/test/drivers/{open_api_3_test.rb → open_api_3/driver_test.rb} +5 -3
  55. data/test/drivers_test.rb +12 -10
  56. data/test/middleware/base_test.rb +3 -1
  57. data/test/middleware/request_validation_open_api_3_test.rb +4 -2
  58. data/test/middleware/request_validation_test.rb +46 -5
  59. data/test/middleware/response_validation_open_api_3_test.rb +3 -1
  60. data/test/middleware/response_validation_test.rb +39 -4
  61. data/test/middleware/stub_test.rb +3 -1
  62. data/test/request_unpacker_test.rb +2 -2
  63. data/test/schema_validator/hyper_schema/parameter_coercer_test.rb +2 -2
  64. data/test/schema_validator/hyper_schema/request_validator_test.rb +3 -1
  65. data/test/schema_validator/hyper_schema/response_generator_test.rb +3 -1
  66. data/test/schema_validator/hyper_schema/response_validator_test.rb +3 -1
  67. data/test/schema_validator/hyper_schema/router_test.rb +5 -3
  68. data/test/schema_validator/hyper_schema/string_params_coercer_test.rb +3 -1
  69. data/test/schema_validator/open_api_3/operation_wrapper_test.rb +3 -1
  70. data/test/schema_validator/open_api_3/request_validator_test.rb +11 -1
  71. data/test/schema_validator/open_api_3/response_validator_test.rb +3 -1
  72. data/test/test/methods_new_version_test.rb +3 -1
  73. data/test/test/methods_test.rb +4 -2
  74. data/test/test_helper.rb +16 -16
  75. data/test/validation_error_test.rb +3 -1
  76. metadata +52 -6
  77. data/lib/committee/schema_validator/schema_validator.rb +0 -15
  78. data/test/drivers/open_api_2_test.rb +0 -416
@@ -1,27 +1,33 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Committee
2
- class SchemaValidator::OpenAPI3::RequestValidator
3
- # @param [SchemaValidator::OpenAPI3::OperationWrapper] operation_object
4
- # @param [Committee::SchemaValidator::Option] validator_option
5
- def initialize(operation_object, validator_option:)
6
- @operation_object = operation_object
7
- @validator_option = validator_option
8
- end
4
+ module SchemaValidator
5
+ class OpenAPI3
6
+ class RequestValidator
7
+ # @param [SchemaValidator::OpenAPI3::OperationWrapper] operation_object
8
+ # @param [Committee::SchemaValidator::Option] validator_option
9
+ def initialize(operation_object, validator_option:)
10
+ @operation_object = operation_object
11
+ @validator_option = validator_option
12
+ end
9
13
 
10
- def call(request, params, headers)
11
- content_type = ::Committee::SchemaValidator.request_media_type(request)
12
- check_content_type(request, content_type) if @validator_option.check_content_type
14
+ def call(request, params, headers)
15
+ content_type = ::Committee::SchemaValidator.request_media_type(request)
16
+ check_content_type(request, content_type) if @validator_option.check_content_type
13
17
 
14
- @operation_object.validate_request_params(params, headers, @validator_option)
15
- end
18
+ @operation_object.validate_request_params(params, headers, @validator_option)
19
+ end
16
20
 
17
- private
21
+ private
18
22
 
19
- def check_content_type(request, content_type)
20
- # support post, put, patch only
21
- return true unless request.post? || request.put? || request.patch?
22
- return true if @operation_object.valid_request_content_type?(content_type)
23
+ def check_content_type(request, content_type)
24
+ # support post, put, patch only
25
+ return true unless request.post? || request.put? || request.patch?
26
+ return true if @operation_object.valid_request_content_type?(content_type)
23
27
 
24
- raise Committee::InvalidRequest, %{"Content-Type" request header must be set to "#{@operation_object}".}
28
+ raise Committee::InvalidRequest, %{"Content-Type" request header must be set to "#{@operation_object}".}
29
+ end
30
+ end
25
31
  end
26
32
  end
27
33
  end
@@ -1,24 +1,30 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Committee
2
- class SchemaValidator::OpenAPI3::ResponseValidator
3
- attr_reader :validate_success_only
4
+ module SchemaValidator
5
+ class OpenAPI3
6
+ class ResponseValidator
7
+ attr_reader :validate_success_only
4
8
 
5
- # @param [Committee::SchemaValidator::Options] validator_option
6
- # @param [Committee::SchemaValidator::OpenAPI3::OperationWrapper] operation_wrapper
7
- def initialize(operation_wrapper, validator_option)
8
- @operation_wrapper = operation_wrapper
9
- @validate_success_only = validator_option.validate_success_only
10
- @check_header = validator_option.check_header
11
- end
9
+ # @param [Committee::SchemaValidator::Options] validator_option
10
+ # @param [Committee::SchemaValidator::OpenAPI3::OperationWrapper] operation_wrapper
11
+ def initialize(operation_wrapper, validator_option)
12
+ @operation_wrapper = operation_wrapper
13
+ @validate_success_only = validator_option.validate_success_only
14
+ @check_header = validator_option.check_header
15
+ end
12
16
 
13
- def call(status, headers, response_data, strict)
14
- return unless Committee::Middleware::ResponseValidation.validate?(status, validate_success_only)
17
+ def call(status, headers, response_data, strict)
18
+ return unless Committee::Middleware::ResponseValidation.validate?(status, validate_success_only)
15
19
 
16
- #content_type = headers['Content-Type'].to_s.split(";").first.to_s
17
- operation_wrapper.validate_response_params(status, headers, response_data, strict, check_header)
18
- end
20
+ #content_type = headers['Content-Type'].to_s.split(";").first.to_s
21
+ operation_wrapper.validate_response_params(status, headers, response_data, strict, check_header)
22
+ end
19
23
 
20
- private
24
+ private
21
25
 
22
- attr_reader :operation_wrapper, :check_header
26
+ attr_reader :operation_wrapper, :check_header
27
+ end
28
+ end
23
29
  end
24
30
  end
@@ -1,37 +1,43 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Committee
2
- class SchemaValidator::OpenAPI3::Router
3
- # @param [Committee::SchemaValidator::Option] validator_option
4
- def initialize(schema, validator_option)
5
- @schema = schema
6
- @prefix_regexp = ::Committee::SchemaValidator.build_prefix_regexp(validator_option.prefix)
7
- @validator_option = validator_option
8
- end
4
+ module SchemaValidator
5
+ class OpenAPI3
6
+ class Router
7
+ # @param [Committee::SchemaValidator::Option] validator_option
8
+ def initialize(schema, validator_option)
9
+ @schema = schema
10
+ @prefix_regexp = ::Committee::SchemaValidator.build_prefix_regexp(validator_option.prefix)
11
+ @validator_option = validator_option
12
+ end
9
13
 
10
- def includes_request?(request)
11
- return true unless @prefix_regexp
14
+ def includes_request?(request)
15
+ return true unless @prefix_regexp
12
16
 
13
- prefix_request?(request)
14
- end
17
+ prefix_request?(request)
18
+ end
15
19
 
16
- def build_schema_validator(request)
17
- Committee::SchemaValidator::OpenAPI3.new(self, request, @validator_option)
18
- end
20
+ def build_schema_validator(request)
21
+ Committee::SchemaValidator::OpenAPI3.new(self, request, @validator_option)
22
+ end
19
23
 
20
- def operation_object(request)
21
- path = request.path
22
- path = path.gsub(@prefix_regexp, '') if prefix_request?(request)
24
+ def operation_object(request)
25
+ path = request.path
26
+ path = path.gsub(@prefix_regexp, '') if prefix_request?(request)
23
27
 
24
- request_method = request.request_method.downcase
28
+ request_method = request.request_method.downcase
25
29
 
26
- @schema.operation_object(path, request_method)
27
- end
30
+ @schema.operation_object(path, request_method)
31
+ end
28
32
 
29
- private
33
+ private
30
34
 
31
- def prefix_request?(request)
32
- return false unless @prefix_regexp
35
+ def prefix_request?(request)
36
+ return false unless @prefix_regexp
33
37
 
34
- request.path =~ @prefix_regexp
38
+ request.path =~ @prefix_regexp
39
+ end
40
+ end
35
41
  end
36
42
  end
37
43
  end
@@ -1,45 +1,49 @@
1
- class Committee::SchemaValidator
2
- class Option
3
- # Boolean Options
4
- attr_reader :allow_form_params,
5
- :allow_get_body,
6
- :allow_query_params,
7
- :check_content_type,
8
- :check_header,
9
- :coerce_date_times,
10
- :coerce_form_params,
11
- :coerce_path_params,
12
- :coerce_query_params,
13
- :coerce_recursive,
14
- :optimistic_json,
15
- :validate_success_only
1
+ # frozen_string_literal: true
16
2
 
17
- # Non-boolean options:
18
- attr_reader :headers_key,
19
- :params_key,
20
- :prefix
3
+ module Committee
4
+ module SchemaValidator
5
+ class Option
6
+ # Boolean Options
7
+ attr_reader :allow_form_params,
8
+ :allow_get_body,
9
+ :allow_query_params,
10
+ :check_content_type,
11
+ :check_header,
12
+ :coerce_date_times,
13
+ :coerce_form_params,
14
+ :coerce_path_params,
15
+ :coerce_query_params,
16
+ :coerce_recursive,
17
+ :optimistic_json,
18
+ :validate_success_only
21
19
 
22
- def initialize(options, schema, schema_type)
23
- # Non-boolean options
24
- @headers_key = options[:headers_key] || "committee.headers"
25
- @params_key = options[:params_key] || "committee.params"
26
- @prefix = options[:prefix]
20
+ # Non-boolean options:
21
+ attr_reader :headers_key,
22
+ :params_key,
23
+ :prefix
27
24
 
28
- # Boolean options and have a common value by default
29
- @allow_form_params = options.fetch(:allow_form_params, true)
30
- @allow_query_params = options.fetch(:allow_query_params, true)
31
- @check_content_type = options.fetch(:check_content_type, true)
32
- @check_header = options.fetch(:check_header, true)
33
- @coerce_recursive = options.fetch(:coerce_recursive, true)
34
- @optimistic_json = options.fetch(:optimistic_json, false)
25
+ def initialize(options, schema, schema_type)
26
+ # Non-boolean options
27
+ @headers_key = options[:headers_key] || "committee.headers"
28
+ @params_key = options[:params_key] || "committee.params"
29
+ @prefix = options[:prefix]
35
30
 
36
- # Boolean options and have a different value by default
37
- @allow_get_body = options.fetch(:allow_get_body, schema.driver.default_allow_get_body)
38
- @coerce_date_times = options.fetch(:coerce_date_times, schema.driver.default_coerce_date_times)
39
- @coerce_form_params = options.fetch(:coerce_form_params, schema.driver.default_coerce_form_params)
40
- @coerce_path_params = options.fetch(:coerce_path_params, schema.driver.default_path_params)
41
- @coerce_query_params = options.fetch(:coerce_query_params, schema.driver.default_query_params)
42
- @validate_success_only = options.fetch(:validate_success_only, schema.driver.default_validate_success_only)
31
+ # Boolean options and have a common value by default
32
+ @allow_form_params = options.fetch(:allow_form_params, true)
33
+ @allow_query_params = options.fetch(:allow_query_params, true)
34
+ @check_content_type = options.fetch(:check_content_type, true)
35
+ @check_header = options.fetch(:check_header, true)
36
+ @coerce_recursive = options.fetch(:coerce_recursive, true)
37
+ @optimistic_json = options.fetch(:optimistic_json, false)
38
+
39
+ # Boolean options and have a different value by default
40
+ @allow_get_body = options.fetch(:allow_get_body, schema.driver.default_allow_get_body)
41
+ @coerce_date_times = options.fetch(:coerce_date_times, schema.driver.default_coerce_date_times)
42
+ @coerce_form_params = options.fetch(:coerce_form_params, schema.driver.default_coerce_form_params)
43
+ @coerce_path_params = options.fetch(:coerce_path_params, schema.driver.default_path_params)
44
+ @coerce_query_params = options.fetch(:coerce_query_params, schema.driver.default_query_params)
45
+ @validate_success_only = options.fetch(:validate_success_only, schema.driver.default_validate_success_only)
46
+ end
43
47
  end
44
48
  end
45
49
  end
@@ -1,69 +1,73 @@
1
- module Committee::Test
2
- module Methods
3
- def assert_schema_conform
4
- assert_request_schema_confirm unless old_behavior
5
- assert_response_schema_confirm
6
- end
1
+ # frozen_string_literal: true
7
2
 
8
- def assert_request_schema_confirm
9
- unless schema_validator.link_exist?
10
- request = "`#{request_object.request_method} #{request_object.path_info}` undefined in schema."
11
- raise Committee::InvalidRequest.new(request)
3
+ module Committee
4
+ module Test
5
+ module Methods
6
+ def assert_schema_conform
7
+ assert_request_schema_confirm unless old_behavior
8
+ assert_response_schema_confirm
12
9
  end
13
10
 
14
- schema_validator.request_validate(request_object)
15
- end
11
+ def assert_request_schema_confirm
12
+ unless schema_validator.link_exist?
13
+ request = "`#{request_object.request_method} #{request_object.path_info}` undefined in schema."
14
+ raise Committee::InvalidRequest.new(request)
15
+ end
16
16
 
17
- def assert_response_schema_confirm
18
- unless schema_validator.link_exist?
19
- response = "`#{request_object.request_method} #{request_object.path_info}` undefined in schema."
20
- raise Committee::InvalidResponse.new(response)
17
+ schema_validator.request_validate(request_object)
21
18
  end
22
19
 
23
- status, headers, body = response_data
24
- schema_validator.response_validate(status, headers, [body], true) if validate_response?(status)
25
- end
20
+ def assert_response_schema_confirm
21
+ unless schema_validator.link_exist?
22
+ response = "`#{request_object.request_method} #{request_object.path_info}` undefined in schema."
23
+ raise Committee::InvalidResponse.new(response)
24
+ end
26
25
 
27
- def committee_options
28
- raise "please set options"
29
- end
26
+ status, headers, body = response_data
27
+ schema_validator.response_validate(status, headers, [body], true) if validate_response?(status)
28
+ end
30
29
 
31
- def request_object
32
- raise "please set object like 'last_request'"
33
- end
30
+ def committee_options
31
+ raise "please set options"
32
+ end
34
33
 
35
- def response_data
36
- raise "please set response data like 'last_response.status, last_response.headers, last_response.body'"
37
- end
34
+ def request_object
35
+ raise "please set object like 'last_request'"
36
+ end
38
37
 
39
- def validate_response?(status)
40
- Committee::Middleware::ResponseValidation.validate?(status, committee_options.fetch(:validate_success_only, false))
41
- end
38
+ def response_data
39
+ raise "please set response data like 'last_response.status, last_response.headers, last_response.body'"
40
+ end
42
41
 
43
- def schema
44
- @schema ||= Committee::Middleware::Base.get_schema(committee_options)
45
- end
42
+ def validate_response?(status)
43
+ Committee::Middleware::ResponseValidation.validate?(status, committee_options.fetch(:validate_success_only, false))
44
+ end
46
45
 
47
- def router
48
- @router ||= schema.build_router(committee_options)
49
- end
46
+ def schema
47
+ @schema ||= Committee::Middleware::Base.get_schema(committee_options)
48
+ end
50
49
 
51
- def schema_validator
52
- @schema_validator ||= router.build_schema_validator(request_object)
53
- end
50
+ def router
51
+ @router ||= schema.build_router(committee_options)
52
+ end
53
+
54
+ def schema_validator
55
+ @schema_validator ||= router.build_schema_validator(request_object)
56
+ end
54
57
 
55
- def old_behavior
56
- old_assert_behavior = committee_options.fetch(:old_assert_behavior, nil)
57
- if old_assert_behavior.nil?
58
- warn <<-MSG
59
- [DEPRECATION] now assert_schema_confirm check response schema only.
60
- but we will change check request and response in future major version.
61
- so if you want to conform response only, please use assert_response_schema_confirm,
62
- or you can suppress this message and keep old behavior by setting old_assert_behavior=true.
63
- MSG
64
- old_assert_behavior = true
58
+ def old_behavior
59
+ old_assert_behavior = committee_options.fetch(:old_assert_behavior, nil)
60
+ if old_assert_behavior.nil?
61
+ warn <<-MSG
62
+ [DEPRECATION] now assert_schema_conform check response schema only.
63
+ but we will change check request and response in future major version.
64
+ so if you want to conform response only, please use assert_response_schema_confirm,
65
+ or you can suppress this message and keep old behavior by setting old_assert_behavior=true.
66
+ MSG
67
+ old_assert_behavior = true
68
+ end
69
+ old_assert_behavior
65
70
  end
66
- old_assert_behavior
67
71
  end
68
72
  end
69
73
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Committee
2
4
  class ValidationError
3
5
  attr_reader :id, :message, :status
@@ -1,4 +1,6 @@
1
- require_relative "../test_helper"
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
2
4
 
3
5
  describe Committee::Bin::CommitteeStub do
4
6
  before do
data/test/bin_test.rb CHANGED
@@ -1,4 +1,6 @@
1
- require_relative "test_helper"
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
2
4
 
3
5
  #
4
6
  # The purpose of this sets of tests is just to include our Ruby executables
@@ -1,4 +1,6 @@
1
- require_relative "test_helper"
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
2
4
 
3
5
  describe Committee do
4
6
  it "debugs based off env" do
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+
5
+ describe Committee::Drivers::HyperSchema::Driver do
6
+ before do
7
+ @driver = Committee::Drivers::HyperSchema::Driver.new
8
+ end
9
+
10
+ it "has a name" do
11
+ assert_equal :hyper_schema, @driver.name
12
+ end
13
+
14
+ it "has a schema class" do
15
+ assert_equal Committee::Drivers::HyperSchema::Schema, @driver.schema_class
16
+ end
17
+
18
+ it "parses a hyper-schema and builds routes" do
19
+ schema = @driver.parse(hyper_schema_data)
20
+ assert_kind_of Committee::Drivers::HyperSchema::Schema, schema
21
+ assert_equal @driver, schema.driver
22
+
23
+ assert_kind_of Hash, schema.routes
24
+ refute schema.routes.empty?
25
+ assert(schema.routes.keys.all? { |m|
26
+ ["DELETE", "GET", "PATCH", "POST", "PUT"].include?(m)
27
+ })
28
+
29
+ schema.routes.each do |(_, method_routes)|
30
+ method_routes.each do |regex, link|
31
+ assert_kind_of Regexp, regex
32
+ assert_kind_of Committee::Drivers::HyperSchema::Link, link
33
+ end
34
+ end
35
+ end
36
+
37
+ it "defaults to not coercing form parameters" do
38
+ assert_equal false, @driver.default_coerce_form_params
39
+ end
40
+
41
+ it "defaults to no path parameters" do
42
+ assert_equal false, @driver.default_path_params
43
+ end
44
+
45
+ it "defaults to no query parameters" do
46
+ assert_equal false, @driver.default_query_params
47
+ end
48
+ end
49
+