committee 0.4.14 → 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.
- data/bin/committee-stub +1 -1
- data/lib/committee/errors.rb +1 -10
- data/lib/committee/middleware/base.rb +9 -1
- data/lib/committee/middleware/request_validation.rb +5 -9
- data/lib/committee/middleware/response_validation.rb +3 -19
- data/lib/committee/middleware/stub.rb +4 -5
- data/lib/committee/request_validator.rb +28 -0
- data/lib/committee/response_generator.rb +19 -13
- data/lib/committee/response_validator.rb +21 -88
- data/lib/committee/router.rb +10 -9
- data/lib/committee/test/methods.rb +15 -17
- data/lib/committee.rb +10 -3
- data/test/middleware/request_validation_test.rb +23 -43
- data/test/middleware/response_validation_test.rb +9 -27
- data/test/middleware/stub_test.rb +10 -1
- data/test/request_validator_test.rb +34 -0
- data/test/response_generator_test.rb +15 -15
- data/test/response_validator_test.rb +19 -110
- data/test/router_test.rb +6 -6
- data/test/test/methods_test.rb +7 -20
- data/test/test_helper.rb +4 -40
- metadata +14 -17
- data/lib/committee/param_validator.rb +0 -106
- data/lib/committee/schema.rb +0 -56
- data/lib/committee/validation.rb +0 -83
- data/test/param_validator_test.rb +0 -127
- data/test/performance/request_validation.rb +0 -55
- data/test/schema_test.rb +0 -36
@@ -0,0 +1,34 @@
|
|
1
|
+
require_relative "test_helper"
|
2
|
+
|
3
|
+
describe Committee::RequestValidator do
|
4
|
+
before do
|
5
|
+
@schema =
|
6
|
+
JsonSchema.parse!(MultiJson.decode(File.read("./test/data/schema.json")))
|
7
|
+
# POST /apps/:id
|
8
|
+
@link = @link = @schema.properties["app"].links[0]
|
9
|
+
end
|
10
|
+
|
11
|
+
it "passes through a valid request" do
|
12
|
+
params = {
|
13
|
+
"name" => "heroku-api",
|
14
|
+
}
|
15
|
+
call(params)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "detects a parameter of the wrong pattern" do
|
19
|
+
params = {
|
20
|
+
"name" => "%@!"
|
21
|
+
}
|
22
|
+
e = assert_raises(Committee::InvalidRequest) do
|
23
|
+
call(params)
|
24
|
+
end
|
25
|
+
message = %{Invalid request.\n\nAt "/schema/app": Expected string to match pattern "/^[a-z][a-z0-9-]{3,30}$/", value was: %@!.}
|
26
|
+
assert_equal message, e.message
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def call(params)
|
32
|
+
Committee::RequestValidator.new.call(@link, params)
|
33
|
+
end
|
34
|
+
end
|
@@ -2,31 +2,31 @@ require_relative "test_helper"
|
|
2
2
|
|
3
3
|
describe Committee::ResponseGenerator do
|
4
4
|
before do
|
5
|
-
@schema =
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
5
|
+
@schema =
|
6
|
+
JsonSchema.parse!(MultiJson.decode(File.read("./test/data/schema.json")))
|
7
|
+
# GET /apps/:id
|
8
|
+
@get_link = @link = @schema.properties["app"].links[2]
|
9
|
+
# GET /apps
|
10
|
+
@list_link = @schema.properties["app"].links[3]
|
11
11
|
end
|
12
12
|
|
13
13
|
it "generates string properties" do
|
14
|
-
data =
|
14
|
+
data = call
|
15
15
|
assert data["name"].is_a?(String)
|
16
16
|
end
|
17
17
|
|
18
18
|
it "generates non-string properties" do
|
19
|
-
data =
|
20
|
-
|
19
|
+
data = call
|
20
|
+
assert_includes [FalseClass, TrueClass], data["maintenance"].class
|
21
21
|
end
|
22
22
|
|
23
23
|
it "wraps list data in an array" do
|
24
|
-
@
|
25
|
-
|
26
|
-
@schema["app"],
|
27
|
-
@schema["app"]["links"][3]
|
28
|
-
)
|
29
|
-
data = @generator.call
|
24
|
+
@link = @list_link
|
25
|
+
data = call
|
30
26
|
assert data.is_a?(Array)
|
31
27
|
end
|
28
|
+
|
29
|
+
def call
|
30
|
+
Committee::ResponseGenerator.new.call(@link)
|
31
|
+
end
|
32
32
|
end
|
@@ -3,10 +3,16 @@ require_relative "test_helper"
|
|
3
3
|
describe Committee::ResponseValidator do
|
4
4
|
before do
|
5
5
|
@data = ValidApp.dup
|
6
|
-
@
|
6
|
+
@headers = {
|
7
|
+
"Content-Type" => "application/json"
|
8
|
+
}
|
9
|
+
@schema =
|
10
|
+
JsonSchema.parse!(MultiJson.decode(File.read("./test/data/schema.json")))
|
7
11
|
# GET /apps/:id
|
8
|
-
@
|
9
|
-
|
12
|
+
@get_link = @link = @schema.properties["app"].links[2]
|
13
|
+
# GET /apps
|
14
|
+
@list_link = @schema.properties["app"].links[3]
|
15
|
+
@type_schema = @schema.properties["app"]
|
10
16
|
end
|
11
17
|
|
12
18
|
it "passes through a valid response" do
|
@@ -15,132 +21,35 @@ describe Committee::ResponseValidator do
|
|
15
21
|
|
16
22
|
it "passes through a valid list response" do
|
17
23
|
@data = [@data]
|
18
|
-
|
19
|
-
@link_schema = @schema["app"]["links"][3]
|
20
|
-
call
|
21
|
-
end
|
22
|
-
|
23
|
-
it "passes through a valid list response with non-default title" do
|
24
|
-
@data = [@data]
|
25
|
-
@link_schema = @schema["app"]["links"][4]
|
24
|
+
@link = @list_link
|
26
25
|
call
|
27
26
|
end
|
28
27
|
|
29
28
|
it "detects an improperly formatted list response" do
|
30
|
-
|
31
|
-
@link_schema = @schema["app"]["links"][3]
|
29
|
+
@link = @list_link
|
32
30
|
e = assert_raises(Committee::InvalidResponse) { call }
|
33
31
|
message = "List endpoints must return an array of objects."
|
34
32
|
assert_equal message, e.message
|
35
33
|
end
|
36
34
|
|
37
|
-
it "detects
|
38
|
-
@
|
39
|
-
e = assert_raises(Committee::InvalidResponse) { call }
|
40
|
-
message = %r{Missing keys in response: name.}
|
41
|
-
assert_match message, e.message
|
42
|
-
end
|
43
|
-
|
44
|
-
it "detects extra keys in response" do
|
45
|
-
@data.merge!("tier" => "important")
|
35
|
+
it "detects an invalid response Content-Type" do
|
36
|
+
@headers = {}
|
46
37
|
e = assert_raises(Committee::InvalidResponse) { call }
|
47
|
-
message =
|
48
|
-
|
49
|
-
end
|
50
|
-
|
51
|
-
it "detects mismatched types" do
|
52
|
-
@data.merge!("maintenance" => "not-bool")
|
53
|
-
e = assert_raises(Committee::InvalidType) { call }
|
54
|
-
message = %{Invalid type at "maintenance": expected "not-bool" to be ["boolean"].}
|
55
|
-
assert_equal message, e.message
|
56
|
-
end
|
57
|
-
|
58
|
-
it "detects bad formats" do
|
59
|
-
@data.merge!("id" => "123")
|
60
|
-
e = assert_raises(Committee::InvalidFormat) { call }
|
61
|
-
message = %{Invalid format at "id": expected "123" to be "uuid".}
|
38
|
+
message =
|
39
|
+
%{"Content-Type" response header must be set to "application/json".}
|
62
40
|
assert_equal message, e.message
|
63
41
|
end
|
64
42
|
|
65
|
-
it "
|
43
|
+
it "raises errors generated by json_schema" do
|
66
44
|
@data.merge!("name" => "%@!")
|
67
|
-
e = assert_raises(Committee::
|
68
|
-
message = %{Invalid
|
69
|
-
assert_equal message, e.message
|
70
|
-
end
|
71
|
-
|
72
|
-
it "accepts date-time format without milliseconds" do
|
73
|
-
validator = Committee::ResponseValidator.new(
|
74
|
-
@data,
|
75
|
-
@schema,
|
76
|
-
@link_schema,
|
77
|
-
@schema["app"])
|
78
|
-
|
79
|
-
value = "2014-03-10T00:00:00Z"
|
80
|
-
assert_nil validator.check_format!("date-time", value, ["example"])
|
81
|
-
end
|
82
|
-
|
83
|
-
it "accepts date-time format with milliseconds" do
|
84
|
-
validator = Committee::ResponseValidator.new(
|
85
|
-
@data,
|
86
|
-
@schema,
|
87
|
-
@link_schema,
|
88
|
-
@schema["app"])
|
89
|
-
|
90
|
-
value = "2014-03-10T00:00:00.123Z"
|
91
|
-
assert_nil validator.check_format!("date-time", value, ["example"])
|
92
|
-
end
|
93
|
-
|
94
|
-
it "accepts a simple array" do
|
95
|
-
@data = ValidAccount.dup
|
96
|
-
@data["flags"] = @data["flags"].dup
|
97
|
-
@link_schema = @schema["account"]["links"][1]
|
98
|
-
@type_schema = @schema["account"]
|
99
|
-
|
100
|
-
call
|
101
|
-
end
|
102
|
-
|
103
|
-
it "validates an array of objects" do
|
104
|
-
@data = ValidAccount.dup
|
105
|
-
@data["credit_cards"] = @data["credit_cards"].dup
|
106
|
-
@link_schema = @schema["account"]["links"][0]
|
107
|
-
@type_schema = @schema["account"]
|
108
|
-
|
109
|
-
call
|
110
|
-
end
|
111
|
-
|
112
|
-
it "detects a simple array with an item of the wrong type" do
|
113
|
-
@data = ValidAccount.dup
|
114
|
-
@data["flags"] = @data["flags"].dup
|
115
|
-
@data["flags"] << false
|
116
|
-
@link_schema = @schema["account"]["links"][1]
|
117
|
-
@type_schema = @schema["account"]
|
118
|
-
|
119
|
-
e = assert_raises(Committee::InvalidType) { call }
|
120
|
-
message = %{Invalid type at "flags": expected false to be ["string"].}
|
121
|
-
assert_equal message, e.message
|
122
|
-
end
|
123
|
-
|
124
|
-
it "rejects an invalid pattern match" do
|
125
|
-
@data = ValidAccount.dup
|
126
|
-
@data["credit_cards"] = @data["credit_cards"].dup
|
127
|
-
@data["credit_cards"] << {"account_number" => "1234-1234-1234-HUGZ", "name" => "Rodney Mullen", "security_code" => 123}
|
128
|
-
@link_schema = @schema["account"]["links"][0]
|
129
|
-
@type_schema = @schema["account"]
|
130
|
-
|
131
|
-
e = assert_raises(Committee::InvalidPattern) { call }
|
132
|
-
message = %{Invalid pattern at "credit_cards:account_number": expected 1234-1234-1234-HUGZ to match "(?-mix:[0-9]{4}\\-[0-9]{4}\\-[0-9]{4}\\-[0-9]{4}$)".}
|
45
|
+
e = assert_raises(Committee::InvalidResponse) { call }
|
46
|
+
message = %{Invalid response.\n\nAt "/schema/app": Expected string to match pattern "/^[a-z][a-z0-9-]{3,30}$/", value was: %@!.}
|
133
47
|
assert_equal message, e.message
|
134
48
|
end
|
135
49
|
|
136
50
|
private
|
137
51
|
|
138
52
|
def call
|
139
|
-
Committee::ResponseValidator.new(
|
140
|
-
@data,
|
141
|
-
@schema,
|
142
|
-
@link_schema,
|
143
|
-
@type_schema
|
144
|
-
).call
|
53
|
+
Committee::ResponseValidator.new(@link).call(@headers, @data)
|
145
54
|
end
|
146
55
|
end
|
data/test/router_test.rb
CHANGED
@@ -2,25 +2,25 @@ require_relative "test_helper"
|
|
2
2
|
|
3
3
|
describe Committee::Router do
|
4
4
|
before do
|
5
|
-
data = File.read("./test/data/schema.json")
|
6
|
-
schema =
|
5
|
+
data = MultiJson.decode(File.read("./test/data/schema.json"))
|
6
|
+
schema = JsonSchema.parse!(data)
|
7
7
|
@router = Committee::Router.new(schema)
|
8
8
|
end
|
9
9
|
|
10
10
|
it "builds routes without parameters" do
|
11
|
-
refute_nil @router.routes?("GET", "/apps")
|
11
|
+
refute_nil @router.routes?("GET", "/apps")
|
12
12
|
end
|
13
13
|
|
14
14
|
it "builds routes with parameters" do
|
15
|
-
refute_nil @router.routes?("GET", "/apps/123")
|
15
|
+
refute_nil @router.routes?("GET", "/apps/123")
|
16
16
|
end
|
17
17
|
|
18
18
|
it "doesn't match anything on a /" do
|
19
|
-
assert_nil @router.routes?("GET", "/")
|
19
|
+
assert_nil @router.routes?("GET", "/")
|
20
20
|
end
|
21
21
|
|
22
22
|
it "takes a prefix" do
|
23
23
|
# this is a sociopathic example
|
24
|
-
refute_nil @router.routes?("GET", "/kpi/apps/123", prefix: "/kpi")
|
24
|
+
refute_nil @router.routes?("GET", "/kpi/apps/123", prefix: "/kpi")
|
25
25
|
end
|
26
26
|
end
|
data/test/test/methods_test.rb
CHANGED
@@ -13,20 +13,10 @@ describe Committee::Middleware::Stub do
|
|
13
13
|
end
|
14
14
|
|
15
15
|
describe "#assert_schema_content_type" do
|
16
|
-
it "
|
17
|
-
|
18
|
-
get "/apps"
|
16
|
+
it "warns about deprecation" do
|
17
|
+
mock(Committee).warn_deprecated.with_any_args
|
19
18
|
assert_schema_content_type
|
20
19
|
end
|
21
|
-
|
22
|
-
it "detects an invalid response Content-Type" do
|
23
|
-
@app = new_rack_app(MultiJson.encode([ValidApp]), {})
|
24
|
-
get "/apps"
|
25
|
-
e = assert_raises(Committee::InvalidResponse) do
|
26
|
-
assert_schema_content_type
|
27
|
-
end
|
28
|
-
assert_match /response header must be set to/i, e.message
|
29
|
-
end
|
30
20
|
end
|
31
21
|
|
32
22
|
describe "#assert_schema_conform" do
|
@@ -45,15 +35,12 @@ describe Committee::Middleware::Stub do
|
|
45
35
|
assert_match /response header must be set to/i, e.message
|
46
36
|
end
|
47
37
|
|
48
|
-
it "
|
49
|
-
|
50
|
-
|
51
|
-
@app = new_rack_app(MultiJson.encode([
|
38
|
+
it "warns when sending a deprecated string" do
|
39
|
+
stub(self).schema_contents { File.read(schema_path) }
|
40
|
+
mock(Committee).warn_deprecated.with_any_args
|
41
|
+
@app = new_rack_app(MultiJson.encode([ValidApp]))
|
52
42
|
get "/apps"
|
53
|
-
|
54
|
-
assert_schema_conform
|
55
|
-
end
|
56
|
-
assert_match /missing keys/i, e.message
|
43
|
+
assert_schema_conform
|
57
44
|
end
|
58
45
|
end
|
59
46
|
|
data/test/test_helper.rb
CHANGED
@@ -1,48 +1,12 @@
|
|
1
1
|
require "minitest"
|
2
2
|
require "minitest/spec"
|
3
3
|
require "minitest/autorun"
|
4
|
-
|
5
|
-
require "
|
6
|
-
Bundler.require(:development)
|
4
|
+
require "rack/test"
|
5
|
+
require "rr"
|
7
6
|
|
8
7
|
require_relative "../lib/committee"
|
9
8
|
|
10
9
|
ValidApp = {
|
11
|
-
"
|
12
|
-
"
|
13
|
-
"created_at" => "2012-01-01T12:00:00Z",
|
14
|
-
"git_url" => "git@heroku.com/example.git",
|
15
|
-
"id" => "01234567-89ab-cdef-0123-456789abcdef",
|
16
|
-
"maintenance" => false,
|
17
|
-
"name" => "example",
|
18
|
-
"owner" => {
|
19
|
-
"email" => "username@example.com",
|
20
|
-
"id" => "01234567-89ab-cdef-0123-456789abcdef"
|
21
|
-
},
|
22
|
-
"region" => {
|
23
|
-
"id" => "01234567-89ab-cdef-0123-456789abcdef",
|
24
|
-
"name" => "us"
|
25
|
-
},
|
26
|
-
"released_at" => "2012-01-01T12:00:00Z",
|
27
|
-
"repo_size" => 0,
|
28
|
-
"slug_size" => 0,
|
29
|
-
"stack" => {
|
30
|
-
"id" => "01234567-89ab-cdef-0123-456789abcdef",
|
31
|
-
"name" => "cedar"
|
32
|
-
},
|
33
|
-
"updated_at" => "2012-01-01T12:00:00Z",
|
34
|
-
"web_url" => "http://example.herokuapp.com"
|
35
|
-
}.freeze
|
36
|
-
|
37
|
-
ValidAccount = {
|
38
|
-
"allow_tracking" => true,
|
39
|
-
"beta" => true,
|
40
|
-
"created_at" => "2012-01-01T12:00:00Z",
|
41
|
-
"email" => "username@example.com",
|
42
|
-
"id" => "01234567-89ab-cdef-0123-456789abcdef",
|
43
|
-
"last_login" => "2012-01-01T12:00:00Z",
|
44
|
-
"updated_at" => "2012-01-01T12:00:00Z",
|
45
|
-
"verified" => true,
|
46
|
-
"flags" => ["foo", "bar"],
|
47
|
-
"credit_cards" => [{"account_number" => "1234-1234-1234-1234", "name" => "Rodney Mullen", "security_code" => 123}]
|
10
|
+
"maintenance" => false,
|
11
|
+
"name" => "example",
|
48
12
|
}.freeze
|
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: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,10 +10,10 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2014-05-
|
13
|
+
date: 2014-05-21 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
|
-
name:
|
16
|
+
name: json_schema
|
17
17
|
requirement: !ruby/object:Gem::Requirement
|
18
18
|
none: false
|
19
19
|
requirements:
|
@@ -29,7 +29,7 @@ dependencies:
|
|
29
29
|
- !ruby/object:Gem::Version
|
30
30
|
version: '0.0'
|
31
31
|
- !ruby/object:Gem::Dependency
|
32
|
-
name:
|
32
|
+
name: multi_json
|
33
33
|
requirement: !ruby/object:Gem::Requirement
|
34
34
|
none: false
|
35
35
|
requirements:
|
@@ -45,21 +45,21 @@ dependencies:
|
|
45
45
|
- !ruby/object:Gem::Version
|
46
46
|
version: '0.0'
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
|
-
name:
|
48
|
+
name: rack
|
49
49
|
requirement: !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
|
-
- - ! '
|
52
|
+
- - ! '>'
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '0'
|
55
|
-
type: :
|
54
|
+
version: '0.0'
|
55
|
+
type: :runtime
|
56
56
|
prerelease: false
|
57
57
|
version_requirements: !ruby/object:Gem::Requirement
|
58
58
|
none: false
|
59
59
|
requirements:
|
60
|
-
- - ! '
|
60
|
+
- - ! '>'
|
61
61
|
- !ruby/object:Gem::Version
|
62
|
-
version: '0'
|
62
|
+
version: '0.0'
|
63
63
|
- !ruby/object:Gem::Dependency
|
64
64
|
name: rack-test
|
65
65
|
requirement: !ruby/object:Gem::Requirement
|
@@ -77,7 +77,7 @@ dependencies:
|
|
77
77
|
- !ruby/object:Gem::Version
|
78
78
|
version: '0'
|
79
79
|
- !ruby/object:Gem::Dependency
|
80
|
-
name:
|
80
|
+
name: rr
|
81
81
|
requirement: !ruby/object:Gem::Requirement
|
82
82
|
none: false
|
83
83
|
requirements:
|
@@ -106,25 +106,21 @@ files:
|
|
106
106
|
- lib/committee/middleware/request_validation.rb
|
107
107
|
- lib/committee/middleware/response_validation.rb
|
108
108
|
- lib/committee/middleware/stub.rb
|
109
|
-
- lib/committee/param_validator.rb
|
110
109
|
- lib/committee/request_unpacker.rb
|
110
|
+
- lib/committee/request_validator.rb
|
111
111
|
- lib/committee/response_generator.rb
|
112
112
|
- lib/committee/response_validator.rb
|
113
113
|
- lib/committee/router.rb
|
114
|
-
- lib/committee/schema.rb
|
115
114
|
- lib/committee/test/methods.rb
|
116
|
-
- lib/committee/validation.rb
|
117
115
|
- lib/committee.rb
|
118
116
|
- test/middleware/request_validation_test.rb
|
119
117
|
- test/middleware/response_validation_test.rb
|
120
118
|
- test/middleware/stub_test.rb
|
121
|
-
- test/param_validator_test.rb
|
122
|
-
- test/performance/request_validation.rb
|
123
119
|
- test/request_unpacker_test.rb
|
120
|
+
- test/request_validator_test.rb
|
124
121
|
- test/response_generator_test.rb
|
125
122
|
- test/response_validator_test.rb
|
126
123
|
- test/router_test.rb
|
127
|
-
- test/schema_test.rb
|
128
124
|
- test/test/methods_test.rb
|
129
125
|
- test/test_helper.rb
|
130
126
|
- bin/committee-stub
|
@@ -154,3 +150,4 @@ signing_key:
|
|
154
150
|
specification_version: 3
|
155
151
|
summary: A collection of Rack middleware to support JSON Schema.
|
156
152
|
test_files: []
|
153
|
+
has_rdoc:
|
@@ -1,106 +0,0 @@
|
|
1
|
-
module Committee
|
2
|
-
class ParamValidator
|
3
|
-
include Validation
|
4
|
-
|
5
|
-
def initialize(params, schema, link_schema, options = {})
|
6
|
-
@params = params
|
7
|
-
@schema = schema
|
8
|
-
@link_schema = link_schema
|
9
|
-
@allow_extra = options[:allow_extra]
|
10
|
-
end
|
11
|
-
|
12
|
-
def call
|
13
|
-
detect_missing!
|
14
|
-
detect_extra! if !@allow_extra
|
15
|
-
check_data!
|
16
|
-
end
|
17
|
-
|
18
|
-
private
|
19
|
-
|
20
|
-
def all_keys
|
21
|
-
properties = @link_schema["schema"] && @link_schema["schema"]["properties"]
|
22
|
-
properties && properties.keys || []
|
23
|
-
end
|
24
|
-
|
25
|
-
def check_data!
|
26
|
-
return if !@link_schema["schema"] || !@link_schema["schema"]["properties"]
|
27
|
-
|
28
|
-
@link_schema["schema"]["properties"].each do |key, value|
|
29
|
-
# don't try to check this unless it was actually specificed
|
30
|
-
next unless @params.key?(key)
|
31
|
-
|
32
|
-
if value["type"] != ["array"]
|
33
|
-
definitions = find_definitions(value["$ref"])
|
34
|
-
try_match(key, @params[key], definitions)
|
35
|
-
else
|
36
|
-
# only assume one possible array definition for now
|
37
|
-
definitions = find_definitions(value["items"]["$ref"])
|
38
|
-
array_definition = definitions[0]
|
39
|
-
@params[key].each do |item|
|
40
|
-
# separate logic for a complex object that includes properties
|
41
|
-
if array_definition.key?("properties")
|
42
|
-
array_definition["properties"].each do |array_key, array_value|
|
43
|
-
return unless item.key?(array_key)
|
44
|
-
|
45
|
-
# @todo: this should really be recursive; only one array level is
|
46
|
-
# supported for now
|
47
|
-
item_definitions = find_definitions(array_value["$ref"])
|
48
|
-
try_match(array_key, item[array_key], item_definitions)
|
49
|
-
end
|
50
|
-
else
|
51
|
-
try_match(key, item, definitions)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
def detect_extra!
|
59
|
-
extra = @params.keys - all_keys
|
60
|
-
if extra.count > 0
|
61
|
-
raise InvalidParams.new("Unknown params: #{extra.join(', ')}.")
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
def detect_missing!
|
66
|
-
missing = required_keys - @params.keys
|
67
|
-
if missing.count > 0
|
68
|
-
raise InvalidParams.new("Require params: #{missing.join(', ')}.")
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
def find_definitions(ref)
|
73
|
-
definition = @schema.find(ref)
|
74
|
-
if definition["anyOf"]
|
75
|
-
definition["anyOf"].map { |r| @schema.find(r["$ref"]) }
|
76
|
-
else
|
77
|
-
[definition]
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
def required_keys
|
82
|
-
(@link_schema["schema"] && @link_schema["schema"]["required"]) || []
|
83
|
-
end
|
84
|
-
|
85
|
-
def try_match(key, value, definitions)
|
86
|
-
match = false
|
87
|
-
|
88
|
-
# try to match data against any possible definition
|
89
|
-
definitions.each do |definition|
|
90
|
-
if check_type(definition["type"], value, key) &&
|
91
|
-
check_format(definition["format"], value, key) &&
|
92
|
-
check_pattern(definition["pattern"], value, key)
|
93
|
-
match = true
|
94
|
-
next
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
# if nothing was matched, throw error according to first definition
|
99
|
-
if !match && definition = definitions.first
|
100
|
-
check_type!(definition["type"], value, key)
|
101
|
-
check_format!(definition["format"], value, key)
|
102
|
-
check_pattern!(definition["pattern"], value, key)
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
data/lib/committee/schema.rb
DELETED
@@ -1,56 +0,0 @@
|
|
1
|
-
module Committee
|
2
|
-
class Schema
|
3
|
-
include Enumerable
|
4
|
-
|
5
|
-
def initialize(data)
|
6
|
-
@cache = {}
|
7
|
-
@schema = MultiJson.decode(data)
|
8
|
-
manifest_regex(@schema)
|
9
|
-
end
|
10
|
-
|
11
|
-
def [](type)
|
12
|
-
find(@schema["properties"][type]['$ref'])
|
13
|
-
end
|
14
|
-
|
15
|
-
def each
|
16
|
-
@schema["properties"].each do |type, ref|
|
17
|
-
yield(type, find(ref['$ref']))
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def find(ref)
|
22
|
-
cache(ref) do
|
23
|
-
parts = ref.split("/")
|
24
|
-
parts.shift if parts.first == "#"
|
25
|
-
pointer = @schema
|
26
|
-
parts.each do |p|
|
27
|
-
next unless pointer
|
28
|
-
pointer = pointer[p]
|
29
|
-
end
|
30
|
-
raise ReferenceNotFound, "Reference not found: #{ref}." if !pointer
|
31
|
-
pointer
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
private
|
36
|
-
|
37
|
-
def cache(key)
|
38
|
-
if @cache[key]
|
39
|
-
@cache[key]
|
40
|
-
else
|
41
|
-
@cache[key] = yield
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
def manifest_regex(schema_part)
|
46
|
-
schema_part["definitions"].each do |_, type_schema|
|
47
|
-
if type_schema.has_key?("definitions")
|
48
|
-
manifest_regex(type_schema)
|
49
|
-
end
|
50
|
-
if pattern = type_schema["pattern"]
|
51
|
-
type_schema["pattern"] = Regexp.new(pattern)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|