sinatra-swagger-exposer 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/lib/sinatra/swagger-exposer/configuration/swagger-endpoint-parameter.rb +118 -0
  4. data/lib/sinatra/swagger-exposer/configuration/swagger-endpoint-response.rb +64 -0
  5. data/lib/sinatra/swagger-exposer/configuration/swagger-endpoint.rb +88 -0
  6. data/lib/sinatra/swagger-exposer/configuration/swagger-info.rb +72 -0
  7. data/lib/sinatra/swagger-exposer/configuration/swagger-parameter-validation-helper.rb +106 -0
  8. data/lib/sinatra/swagger-exposer/configuration/swagger-type-property.rb +82 -0
  9. data/lib/sinatra/swagger-exposer/configuration/swagger-type.rb +127 -0
  10. data/lib/sinatra/swagger-exposer/configuration/swagger-types.rb +51 -0
  11. data/lib/sinatra/swagger-exposer/processing/swagger-array-value-preprocessor.rb +46 -0
  12. data/lib/sinatra/swagger-exposer/processing/swagger-base-value-preprocessor.rb +48 -0
  13. data/lib/sinatra/swagger-exposer/processing/swagger-parameter-preprocessor.rb +47 -0
  14. data/lib/sinatra/swagger-exposer/processing/swagger-preprocessor-dispatcher.rb +45 -0
  15. data/lib/sinatra/swagger-exposer/processing/swagger-primitive-value-preprocessor.rb +165 -0
  16. data/lib/sinatra/swagger-exposer/processing/swagger-request-preprocessor.rb +64 -0
  17. data/lib/sinatra/swagger-exposer/processing/swagger-type-value-preprocessor.rb +37 -0
  18. data/lib/sinatra/swagger-exposer/swagger-content-creator.rb +3 -2
  19. data/lib/sinatra/swagger-exposer/swagger-exposer.rb +18 -20
  20. data/lib/sinatra/swagger-exposer/swagger-parameter-helper.rb +1 -1
  21. data/lib/sinatra/swagger-exposer/swagger-preprocessor-creator.rb +137 -0
  22. data/lib/sinatra/swagger-exposer/swagger-utilities.rb +1 -1
  23. data/lib/sinatra/swagger-exposer/version.rb +1 -1
  24. metadata +18 -10
  25. data/lib/sinatra/swagger-exposer/swagger-endpoint-parameter.rb +0 -197
  26. data/lib/sinatra/swagger-exposer/swagger-endpoint-response.rb +0 -63
  27. data/lib/sinatra/swagger-exposer/swagger-endpoint.rb +0 -94
  28. data/lib/sinatra/swagger-exposer/swagger-info.rb +0 -70
  29. data/lib/sinatra/swagger-exposer/swagger-parameter-preprocessor.rb +0 -187
  30. data/lib/sinatra/swagger-exposer/swagger-request-preprocessor.rb +0 -56
  31. data/lib/sinatra/swagger-exposer/swagger-type-property.rb +0 -72
  32. data/lib/sinatra/swagger-exposer/swagger-type.rb +0 -125
@@ -1,187 +0,0 @@
1
- require 'date'
2
-
3
- require_relative 'swagger-endpoint-parameter'
4
- require_relative 'swagger-parameter-helper'
5
- require_relative 'swagger-invalid-exception'
6
-
7
- module Sinatra
8
-
9
- module SwaggerExposer
10
-
11
- # Process the parameters for validation and enrichment
12
- class SwaggerParameterPreprocessor
13
-
14
- include SwaggerParameterHelper
15
-
16
- def initialize(name, how_to_pass, required, type, default, params)
17
- @name = name.to_s
18
- @how_to_pass = how_to_pass
19
- @required = required
20
- @type = type
21
- @default = default
22
- @params = params
23
-
24
- # All headers are upcased
25
- if how_to_pass == HOW_TO_PASS_HEADER
26
- @name.upcase!
27
- end
28
- end
29
-
30
- def useful?
31
- @required ||
32
- (!@default.nil?) ||
33
- [TYPE_NUMBER, TYPE_INTEGER, TYPE_BOOLEAN, TYPE_DATE_TIME].include?(@type) || # Must check type
34
- (@params.key? PARAMS_MIN_LENGTH) || (@params.key? PARAMS_MAX_LENGTH) # Must check string
35
- end
36
-
37
- def run(app, parsed_body)
38
- case @how_to_pass
39
- when HOW_TO_PASS_PATH
40
- # can't validate
41
- when HOW_TO_PASS_QUERY
42
- check_param(app.params)
43
- when HOW_TO_PASS_HEADER
44
- check_param(app.headers)
45
- when HOW_TO_PASS_BODY
46
- check_param(parsed_body || {})
47
- end
48
- end
49
-
50
- def check_param(params)
51
- if params.key?(@name)
52
- params[@name] = validate_param_value(params[@name])
53
- elsif @required
54
- raise SwaggerInvalidException.new("Mandatory parameter [#{@name}] is missing")
55
- elsif @default
56
- params[@name] = @default
57
- end
58
- params
59
- end
60
-
61
- def validate_param_value(value)
62
- case @type
63
- when TYPE_NUMBER
64
- return validate_param_value_number(value)
65
- when TYPE_INTEGER
66
- return validate_param_value_integer(value)
67
- when TYPE_BOOLEAN
68
- return validate_param_value_boolean(value)
69
- when TYPE_DATE_TIME
70
- return validate_param_value_date_time(value)
71
- else
72
- return validate_param_value_string(value)
73
- end
74
- end
75
-
76
- # Validate a boolean parameter
77
- def validate_param_value_boolean(value)
78
- if (value == 'true') || value.is_a?(TrueClass)
79
- return true
80
- elsif (value == 'false') || value.is_a?(FalseClass)
81
- return false
82
- else
83
- raise SwaggerInvalidException.new("Parameter [#{@name}] should be an boolean but is [#{value}]")
84
- end
85
- end
86
-
87
- # Validate an integer parameter
88
- def validate_param_value_integer(value)
89
- begin
90
- f = Float(value)
91
- i = Integer(value)
92
- if f == i
93
- i
94
- else
95
- raise SwaggerInvalidException.new("Parameter [#{@name}] should be an integer but is [#{value}]")
96
- end
97
- value = Integer(value)
98
- validate_numerical_value(value)
99
- value
100
- rescue ArgumentError
101
- raise SwaggerInvalidException.new("Parameter [#{@name}] should be an integer but is [#{value}]")
102
- rescue TypeError
103
- raise SwaggerInvalidException.new("Parameter [#{@name}] should be an integer but is [#{value}]")
104
- end
105
- end
106
-
107
- # Validate a number parameter
108
- def validate_param_value_number(value)
109
- begin
110
- value = Float(value)
111
- validate_numerical_value(value)
112
- return value
113
- rescue ArgumentError
114
- raise SwaggerInvalidException.new("Parameter [#{@name}] should be a float but is [#{value}]")
115
- rescue TypeError
116
- raise SwaggerInvalidException.new("Parameter [#{@name}] should be a float but is [#{value}]")
117
- end
118
- end
119
-
120
- # Validate a numerical value
121
- # @param value [Numeric] the value
122
- def validate_numerical_value(value)
123
- validate_numerical_value_internal(
124
- value,
125
- PARAMS_MINIMUM,
126
- PARAMS_EXCLUSIVE_MINIMUM,
127
- '>=',
128
- '>')
129
- validate_numerical_value_internal(
130
- value,
131
- PARAMS_MAXIMUM,
132
- PARAMS_EXCLUSIVE_MAXIMUM,
133
- '<=',
134
- '<')
135
- end
136
-
137
- # Validate a date time parameter
138
- def validate_param_value_date_time(value)
139
- begin
140
- DateTime.rfc3339(value)
141
- rescue ArgumentError
142
- raise SwaggerInvalidException.new("Parameter [#{@name}] should be a date time but is [#{value}]")
143
- end
144
- end
145
-
146
- # Validate a string parameter
147
- def validate_param_value_string(value)
148
- if value
149
- validate_param_value_string_length(value, PARAMS_MIN_LENGTH, '>=')
150
- validate_param_value_string_length(value, PARAMS_MAX_LENGTH, '<=')
151
- end
152
- value
153
- end
154
-
155
- # Validate the length of a string parameter
156
- # @param value the value to check
157
- # @param limit_param_name [Symbol] the param that contain the value to compare to
158
- # @param limit_param_method [String] the comparison method to call
159
- def validate_param_value_string_length(value, limit_param_name, limit_param_method)
160
- if @params.key? limit_param_name
161
- target_value = @params[limit_param_name]
162
- unless value.length.send(limit_param_method, target_value)
163
- raise SwaggerInvalidException.new("Parameter [#{@name}] length should be #{limit_param_method} than #{target_value} but is #{value.length} for [#{value}]")
164
- end
165
- end
166
- end
167
-
168
- # Validate the value of a number
169
- # @param value the value to check
170
- # @param limit_param_name [Symbol] the param that contain the value to compare to
171
- # @param exclusive_limit_param_name [Symbol] the param that indicates if the comparison is absolute
172
- # @param limit_param_method [String] the comparison method to call
173
- # @param exclusive_limit_param_method [String] the absolute comparison method to call
174
- def validate_numerical_value_internal(value, limit_param_name, exclusive_limit_param_name, limit_param_method, exclusive_limit_param_method)
175
- if @params.key? limit_param_name
176
- target_value = @params[limit_param_name]
177
- method_to_call = @params[exclusive_limit_param_name] ? exclusive_limit_param_method : limit_param_method
178
- unless value.send(method_to_call, target_value)
179
- raise SwaggerInvalidException.new("Parameter [#{@name}] should be #{method_to_call} than [#{target_value}] but is [#{value}]")
180
- end
181
- end
182
- end
183
-
184
- end
185
-
186
- end
187
- end
@@ -1,56 +0,0 @@
1
- require 'json'
2
-
3
- require_relative 'swagger-invalid-exception'
4
-
5
- module Sinatra
6
-
7
- module SwaggerExposer
8
-
9
- # A preprocessor for a request, apply the parameter preprocessor then execute the query code
10
- class SwaggerRequestPreprocessor
11
-
12
- attr_reader :preprocessors
13
-
14
- def initialize
15
- @preprocessors = []
16
- end
17
-
18
- def add_preprocessor(preprocessor)
19
- @preprocessors << preprocessor
20
- end
21
-
22
- # Run the preprocessor the call the route content
23
- # @param app the sinatra app being run
24
- # @params block_params [Array] the block parameters
25
- # @param block the block containing the route content
26
- def run(app, block_params, &block)
27
- parsed_body = {}
28
- if app.env['CONTENT_TYPE'] == 'application/json'
29
- body = app.request.body.read
30
- unless body.empty?
31
- parsed_body = JSON.parse(body)
32
- end
33
- end
34
- app.params['parsed_body'] = parsed_body
35
- unless @preprocessors.empty?
36
- @preprocessors.each do |preprocessor|
37
- begin
38
- preprocessor.run(app, parsed_body)
39
- rescue SwaggerInvalidException => e
40
- app.content_type :json
41
- return [400, {:code => 400, :message => e.message}.to_json]
42
- end
43
- end
44
- end
45
- if block
46
- # Execute the block in the context of the app
47
- app.instance_exec(*block_params, &block)
48
- else
49
- ''
50
- end
51
- end
52
-
53
- end
54
-
55
- end
56
- end
@@ -1,72 +0,0 @@
1
- require_relative 'swagger-utilities'
2
- require_relative 'swagger-invalid-exception'
3
-
4
- module Sinatra
5
-
6
- module SwaggerExposer
7
-
8
- # A property of a type
9
- class SwaggerTypeProperty
10
-
11
- include SwaggerUtilities
12
-
13
- OTHER_PROPERTIES = [:example, :description, :format, :minLength, :maxLength]
14
- PROPERTIES = [:type] + OTHER_PROPERTIES
15
-
16
- def initialize(type_name, property_name, property_properties, known_types)
17
- @name = property_name
18
-
19
- unless property_properties.is_a? Hash
20
- raise SwaggerInvalidException.new("Property [#{property_name}] value [#{property_properties}] of [#{type_name}] should be a hash")
21
- end
22
-
23
- if property_properties.key? :type
24
- get_type(property_properties[:type], PRIMITIVE_TYPES + known_types)
25
- end
26
-
27
- white_list_params(property_properties, PROPERTIES)
28
-
29
- @other_properties = property_properties.select do |key, value|
30
- OTHER_PROPERTIES.include? key
31
- end
32
-
33
- end
34
-
35
- def to_swagger
36
- result = @other_properties.clone
37
-
38
- if @type
39
- if @type == 'array'
40
- result[:type] = 'array'
41
- if @items
42
- if PRIMITIVE_TYPES.include? @items
43
- result[:items] = {:type => @items}
44
- else
45
- result[:items] = ref_to_type(@items)
46
- end
47
- end
48
- else
49
- if PRIMITIVE_TYPES.include? @type
50
- result[:type] = @type
51
- else
52
- result['$ref'] = "#/definitions/#{@type}"
53
- end
54
- end
55
- end
56
-
57
- result
58
- end
59
-
60
- def to_s
61
- {
62
- :name => @name,
63
- :type => @type,
64
- :items => @items,
65
- :other_properties => @other_properties,
66
- }.to_json
67
- end
68
-
69
- end
70
-
71
- end
72
- end
@@ -1,125 +0,0 @@
1
- require_relative 'swagger-invalid-exception'
2
- require_relative 'swagger-type-property'
3
- require_relative 'swagger-utilities'
4
-
5
- module Sinatra
6
-
7
- module SwaggerExposer
8
-
9
- # A type
10
- class SwaggerType
11
-
12
- include SwaggerUtilities
13
-
14
- PROPERTY_PROPERTIES = :properties
15
- PROPERTY_REQUIRED = :required
16
- PROPERTY_EXAMPLE = :example
17
- PROPERTY_EXTENDS = :extends
18
- PROPERTIES = [PROPERTY_PROPERTIES, PROPERTY_REQUIRED, PROPERTY_EXAMPLE, PROPERTY_EXTENDS]
19
-
20
- def initialize(type_name, type_properties, known_types)
21
- white_list_params(type_properties, PROPERTIES)
22
- @properties = process_properties(type_name, type_properties, known_types)
23
- @required = process_required(type_name, type_properties, @properties.keys)
24
- @example = process_example(type_name, type_properties, @properties.keys)
25
- @extends = process_extends(type_properties, known_types)
26
- end
27
-
28
- def process_properties(type_name, type_content, known_types)
29
- possible_value = check_attribute_empty_or_bad(type_name, type_content, PROPERTY_PROPERTIES, Hash)
30
- if possible_value
31
- possible_value
32
- else
33
- result = {}
34
- type_content[PROPERTY_PROPERTIES].each_pair do |property_name, property_properties|
35
- result[property_name.to_s] = SwaggerTypeProperty.new(type_name, property_name, property_properties, known_types)
36
- end
37
- result
38
- end
39
- end
40
-
41
- def process_required(type_name, type_content, properties_names)
42
- possible_value = check_attribute_empty_or_bad(type_name, type_content, PROPERTY_REQUIRED, Array)
43
- if possible_value
44
- possible_value
45
- else
46
- type_content[PROPERTY_REQUIRED].each do |property_name|
47
- property_name = property_name.to_s
48
- unless properties_names.include? property_name
49
- raise SwaggerInvalidException.new("Required property [#{property_name}] of [#{type_name}] is unknown#{list_or_none(properties_names, 'properties')}")
50
- end
51
- end
52
- type_content[PROPERTY_REQUIRED]
53
- end
54
- end
55
-
56
- def process_example(type_name, type_content, properties_names)
57
- possible_value = check_attribute_empty_or_bad(type_name, type_content, PROPERTY_EXAMPLE, Hash)
58
- if possible_value
59
- possible_value
60
- else
61
- type_content[PROPERTY_EXAMPLE].each_pair do |property_name, property_value|
62
- property_name = property_name.to_s
63
- unless properties_names.include? property_name
64
- raise SwaggerInvalidException.new("Example property [#{property_name}] with value [#{property_value}] of [#{type_name}] is unknown#{list_or_none(properties_names, 'properties')}")
65
- end
66
- end
67
- type_content[PROPERTY_EXAMPLE]
68
- end
69
- end
70
-
71
- def check_attribute_empty_or_bad(type_name, type_content, attribute_name, attribute_class)
72
- if !type_content.key?(attribute_name)
73
- attribute_class.new
74
- elsif !type_content[attribute_name].is_a? attribute_class
75
- raise SwaggerInvalidException.new("Attribute [#{attribute_name}] of #{type_name} is not an hash: #{type_content[attribute_name]}")
76
- end
77
- end
78
-
79
- def process_extends(type_properties, known_types)
80
- if type_properties.key? PROPERTY_EXTENDS
81
- check_type(type_properties[PROPERTY_EXTENDS], known_types)
82
- @extends = type_properties[PROPERTY_EXTENDS]
83
- end
84
- end
85
-
86
- def to_swagger
87
- result = {:type => 'object'}
88
-
89
- unless @properties.empty?
90
- result[PROPERTY_PROPERTIES] = hash_to_swagger(@properties)
91
- end
92
-
93
- unless @required.empty?
94
- result[PROPERTY_REQUIRED] = @required
95
- end
96
-
97
- unless @example.empty?
98
- result[PROPERTY_EXAMPLE] = @example
99
- end
100
-
101
- if @extends
102
- result = {
103
- :allOf => [
104
- ref_to_type(@extends),
105
- result
106
- ]
107
- }
108
- end
109
-
110
- result
111
- end
112
-
113
- def to_s
114
- {
115
- :properties => @properties,
116
- :required => @required,
117
- :example => @example,
118
- }.to_json
119
- end
120
-
121
-
122
- end
123
-
124
- end
125
- end