committee 2.0.0.pre → 2.0.0.pre2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5911eb64b8a07bb45eaf264399bebeb95ea2395b
4
- data.tar.gz: 35d800d2dd5cd0c3d402b26813d7b156f0809006
3
+ metadata.gz: c27dbbfbcb3d316bd61c7056fe0a8f7fec175ab6
4
+ data.tar.gz: c3ad5a80a63987ae2f94988ed12b1285e71ee760
5
5
  SHA512:
6
- metadata.gz: 86c361cc0bd1f4d0e340335402ab452b99a0c0d0eae814aa3296794ed0a076177f9dc3ebc772ae95a66afbe45efcbeccc77e2851ef3a0e385171fc549e31092c
7
- data.tar.gz: 306a67c72463d3879dd7fb4e9aff88a17d34e54d83c209a439cabc47b912027178c5d23fc9b5270cc6b0f9d65d4957f152ec630c7e3484931bba1bda46ed4bd0
6
+ metadata.gz: 86f1c3e718e6dee210e3c42ba2d1a5ba0b029137adc1be572d5dac9d6048dc7c84cf4274a652360473b9e263662912f5a7a94fc27b2666daf054530f0b44c40f
7
+ data.tar.gz: 6dd6d2dc9165ea38e3df05a0d35915809a82447a5708728c192d22ee632692448f6e4996733c165c8f0d6f4895dff7bfa18b952c070b2a8bb1e01d21073ad7c7
@@ -6,13 +6,15 @@ module Committee
6
6
  class CommitteeStub
7
7
  # Gets a Rack app suitable for use as a stub.
8
8
  def get_app(schema, options)
9
+ cache = {}
10
+
9
11
  Rack::Builder.new {
10
12
  unless options[:tolerant]
11
13
  use Committee::Middleware::RequestValidation, schema: schema
12
14
  use Committee::Middleware::ResponseValidation, schema: schema
13
15
  end
14
16
 
15
- use Committee::Middleware::Stub, schema: schema
17
+ use Committee::Middleware::Stub, cache: cache, schema: schema
16
18
 
17
19
  run lambda { |_|
18
20
  [404, {}, ["Not found"]]
@@ -53,9 +55,6 @@ module Committee
53
55
  end
54
56
  [options, parser]
55
57
  end
56
-
57
- def get_schema(driver_name, data)
58
- end
59
58
  end
60
59
  end
61
60
  end
@@ -89,43 +89,54 @@ module Committee::Drivers
89
89
  self.link_data = link_data
90
90
  end
91
91
 
92
+ # Returns a tuple of (schema, schema_data) where only one of the two
93
+ # values is present. This is either a full schema that's ready to go _or_
94
+ # a hash of unparsed schema data.
92
95
  def call
93
- link_schema = JsonSchema::Schema.new
94
- link_schema.properties = {}
95
- link_schema.required = []
96
-
97
96
  if link_data["parameters"]
98
- link_data["parameters"].each do |param_data|
99
- LINK_REQUIRED_FIELDS.each do |field|
100
- if !param_data[field]
101
- raise ArgumentError,
102
- "Committee: no #{field} section in link data."
103
- end
104
- end
97
+ body_param = link_data["parameters"].detect { |p| p["in"] == "body" }
98
+ if body_param
99
+ check_required_fields!(body_param)
105
100
 
106
- param_schema = JsonSchema::Schema.new
101
+ if link_data["parameters"].detect { |p| p["in"] == "form" } != nil
102
+ raise ArgumentError, "Committee: can't mix body parameter " \
103
+ "with form parameters."
104
+ end
107
105
 
108
- # We could probably use more validation here, but the formats of
109
- # OpenAPI 2 are based off of what's available in JSON schema, and
110
- # therefore this should map over quite well.
111
- param_schema.type = [param_data["type"]]
106
+ schema_data = body_param["schema"]
107
+ [nil, schema_data]
108
+ else
109
+ link_schema = JsonSchema::Schema.new
110
+ link_schema.properties = {}
111
+ link_schema.required = []
112
+
113
+ link_data["parameters"].each do |param_data|
114
+ check_required_fields!(param_data)
115
+
116
+ param_schema = JsonSchema::Schema.new
117
+
118
+ # We could probably use more validation here, but the formats of
119
+ # OpenAPI 2 are based off of what's available in JSON schema, and
120
+ # therefore this should map over quite well.
121
+ param_schema.type = [param_data["type"]]
122
+
123
+ # And same idea: despite parameters not being schemas, the items
124
+ # key (if preset) is actually a schema that defines each item of an
125
+ # array type, so we can just reflect that directly onto our
126
+ # artifical schema.
127
+ if param_data["type"] == "array" && param_data["items"]
128
+ param_schema.items = param_data["items"]
129
+ end
112
130
 
113
- # And same idea: despite parameters not being schemas, the items
114
- # key (if preset) is actually a schema that defines each item of an
115
- # array type, so we can just reflect that directly onto our
116
- # artifical schema.
117
- if param_data["type"] == "array" && param_data["items"]
118
- param_schema.items = param_data["items"]
131
+ link_schema.properties[param_data["name"]] = param_schema
132
+ if param_data["required"] == true
133
+ link_schema.required << param_data["name"]
134
+ end
119
135
  end
120
136
 
121
- link_schema.properties[param_data["name"]] = param_schema
122
- if param_data["required"] == true
123
- link_schema.required << param_data["name"]
124
- end
137
+ [link_schema, nil]
125
138
  end
126
139
  end
127
-
128
- link_schema
129
140
  end
130
141
 
131
142
  private
@@ -135,6 +146,15 @@ module Committee::Drivers
135
146
  ].map(&:to_s).freeze
136
147
 
137
148
  attr_accessor :link_data
149
+
150
+ def check_required_fields!(param_data)
151
+ LINK_REQUIRED_FIELDS.each do |field|
152
+ if !param_data[field]
153
+ raise ArgumentError,
154
+ "Committee: no #{field} section in link data."
155
+ end
156
+ end
157
+ end
138
158
  end
139
159
 
140
160
  class Schema < Committee::Drivers::Schema
@@ -219,10 +239,14 @@ module Committee::Drivers
219
239
  # all schemas into one big hash and then parse it all at the end. After
220
240
  # we parse it, go through each link and assign a proper schema object. In
221
241
  # practice this comes out to somewhere on the order of 50x faster.
242
+ schemas_data = { "properties" => {} }
243
+
244
+ # Exactly the same idea, but for response schemas.
222
245
  target_schemas_data = { "properties" => {} }
223
246
 
224
247
  data['paths'].each do |path, methods|
225
248
  href = schema.base_path + path
249
+ schemas_data["properties"][href] = { "properties" => {} }
226
250
  target_schemas_data["properties"][href] = { "properties" => {} }
227
251
 
228
252
  methods.each do |method, link_data|
@@ -236,7 +260,14 @@ module Committee::Drivers
236
260
 
237
261
  # Convert the spec's parameter pseudo-schemas into JSON schemas that
238
262
  # we can use for some basic request validation.
239
- link.schema = ParameterSchemaBuilder.new(link_data).call
263
+ link.schema, schema_data = ParameterSchemaBuilder.new(link_data).call
264
+
265
+ # If data came back instead of a schema (this occurs when a route has
266
+ # a single `body` parameter instead of a collection of URL/query/form
267
+ # parameters), store it for later parsing.
268
+ if schema_data
269
+ schemas_data["properties"][href]["properties"][method] = schema_data
270
+ end
240
271
 
241
272
  # Arbitrarily pick one response for the time being. Prefers in order:
242
273
  # a 200, 201, any 3-digit numerical response, then anything at all.
@@ -263,15 +294,25 @@ module Committee::Drivers
263
294
  # #parse_definitions!, but what we're doing here is prefixing references
264
295
  # with a specialized internal URI so that they can reference definitions
265
296
  # from another document in the store.
266
- target_schemas = rewrite_references(target_schemas_data)
267
-
268
- target_schemas = JsonSchema.parse!(target_schemas)
269
- target_schemas.expand_references!(store: store)
297
+ schemas =
298
+ rewrite_references_and_parse(schemas_data, store)
299
+ target_schemas =
300
+ rewrite_references_and_parse(target_schemas_data, store)
270
301
 
271
302
  # As noted above, now that we've parsed our aggregate response schema, go
272
303
  # back through each link and them their response schema.
273
304
  routes.each do |method, method_routes|
274
305
  method_routes.each do |(_, link)|
306
+ # request
307
+ #
308
+ # Differs slightly from responses in that the schema may already have
309
+ # been set for endpoints with non-body parameters, so check for nil
310
+ # before we set it.
311
+ if schema = schemas.properties[link.href].properties[method]
312
+ link.schema = schema
313
+ end
314
+
315
+ # response
275
316
  link.target_schema =
276
317
  target_schemas.properties[link.href].properties[method]
277
318
  end
@@ -280,6 +321,13 @@ module Committee::Drivers
280
321
  routes
281
322
  end
282
323
 
324
+ def rewrite_references_and_parse(schemas_data, store)
325
+ schemas = rewrite_references(schemas_data)
326
+ schemas = JsonSchema.parse!(schemas_data)
327
+ schemas.expand_references!(:store => store)
328
+ schemas
329
+ end
330
+
283
331
  def rewrite_references(schema)
284
332
  if schema.is_a?(Hash)
285
333
  ref = schema["$ref"]
@@ -197,8 +197,9 @@ describe Committee::Drivers::OpenAPI2::ParameterSchemaBuilder do
197
197
  }
198
198
  ]
199
199
  }
200
- schema = call(data)
200
+ schema, schema_data = call(data)
201
201
 
202
+ assert_equal nil, schema_data
202
203
  assert_equal ["limit"], schema.properties.keys
203
204
  assert_equal [], schema.required
204
205
  assert_equal ["integer"], schema.properties["limit"].type
@@ -213,8 +214,9 @@ describe Committee::Drivers::OpenAPI2::ParameterSchemaBuilder do
213
214
  }
214
215
  ]
215
216
  }
216
- schema = call(data)
217
+ schema, schema_data = call(data)
217
218
 
219
+ assert_equal nil, schema_data
218
220
  assert_equal ["limit"], schema.required
219
221
  end
220
222
 
@@ -230,12 +232,31 @@ describe Committee::Drivers::OpenAPI2::ParameterSchemaBuilder do
230
232
  }
231
233
  ]
232
234
  }
233
- schema = call(data)
235
+ schema, schema_data = call(data)
234
236
 
237
+ assert_equal nil, schema_data
235
238
  assert_equal ["array"], schema.properties["tags"].type
236
239
  assert_equal({ "type" => "string" }, schema.properties["tags"].items)
237
240
  end
238
241
 
242
+ it "returns schema data for a body parameter" do
243
+ data = {
244
+ "parameters" => [
245
+ {
246
+ "name" => "payload",
247
+ "in" => "body",
248
+ "schema" => {
249
+ "$ref" => "#/definitions/foo",
250
+ }
251
+ }
252
+ ]
253
+ }
254
+ schema, schema_data = call(data)
255
+
256
+ assert_equal nil, schema
257
+ assert_equal({ "$ref" => "#/definitions/foo" }, schema_data)
258
+ end
259
+
239
260
  it "requires that certain fields are present" do
240
261
  data = {
241
262
  "parameters" => [
@@ -249,6 +270,26 @@ describe Committee::Drivers::OpenAPI2::ParameterSchemaBuilder do
249
270
  assert_equal "Committee: no name section in link data.", e.message
250
271
  end
251
272
 
273
+ it "requires that body parameters not be mixed with form parameters" do
274
+ data = {
275
+ "parameters" => [
276
+ {
277
+ "name" => "payload",
278
+ "in" => "body",
279
+ },
280
+ {
281
+ "name" => "limit",
282
+ "in" => "form",
283
+ },
284
+ ]
285
+ }
286
+ e = assert_raises ArgumentError do
287
+ call(data)
288
+ end
289
+ assert_equal "Committee: can't mix body parameter with form parameters.",
290
+ e.message
291
+ end
292
+
252
293
  def call(data)
253
294
  Committee::Drivers::OpenAPI2::ParameterSchemaBuilder.new(data).call
254
295
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: committee
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.pre
4
+ version: 2.0.0.pre2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brandur
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-10-10 00:00:00.000000000 Z
12
+ date: 2016-10-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: json_schema