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.
@@ -1,83 +0,0 @@
1
- module Committee
2
- module Validation
3
- def check_format!(format, value, identifier)
4
- return if !format
5
- return if check_format(format, value, identifier)
6
-
7
- description = case identifier
8
- when String
9
- %{Invalid format for key "#{identifier}": expected "#{value}" to be "#{format}".}
10
- when Array
11
- %{Invalid format at "#{identifier.join(":")}": expected "#{value}" to be "#{format}".}
12
- end
13
-
14
- raise InvalidFormat, description
15
- end
16
-
17
- def check_format(format, value, identifier)
18
- case format
19
- when "date-time"
20
- value =~ /^(\d{4})-(\d{2})-(\d{2})T(\d{2})\:(\d{2})\:(\d{2})(\.\d{1,})?(Z|[+-](\d{2})\:(\d{2}))$/
21
- when "email"
22
- value =~ /^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$/i
23
- when "uuid"
24
- value =~ /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/
25
- else
26
- true
27
- end
28
- end
29
-
30
- def check_type!(allowed_types, value, identifier)
31
- return if check_type(allowed_types, value, identifier)
32
-
33
- description = case identifier
34
- when String
35
- %{Invalid type for key "#{identifier}": expected #{value.inspect} to be #{allowed_types}.}
36
- when Array
37
- %{Invalid type at "#{identifier.join(":")}": expected #{value.inspect} to be #{allowed_types}.}
38
- end
39
-
40
- raise InvalidType, description
41
- end
42
-
43
- def check_type(allowed_types, value, identifier)
44
- types = case value
45
- when NilClass
46
- ["null"]
47
- when TrueClass, FalseClass
48
- ["boolean"]
49
- when Bignum, Fixnum
50
- ["integer", "number"]
51
- when Float
52
- ["number"]
53
- when Hash
54
- ["object"]
55
- when String
56
- ["string"]
57
- when Array
58
- ["array"]
59
- else
60
- ["unknown"]
61
- end
62
-
63
- !(allowed_types & types).empty?
64
- end
65
-
66
- def check_pattern!(pattern, value, identifier)
67
- return if check_pattern(pattern, value, identifier)
68
-
69
- description = case identifier
70
- when String
71
- %{Invalid pattern for key "#{identifier}": expected #{value} to match "#{pattern}".}
72
- when Array
73
- %{Invalid pattern at "#{identifier.join(":")}": expected #{value} to match "#{pattern}".}
74
- end
75
-
76
- raise InvalidPattern, description
77
- end
78
-
79
- def check_pattern(pattern, value, identifier)
80
- !pattern || value =~ Regexp.new(pattern)
81
- end
82
- end
83
- end
@@ -1,127 +0,0 @@
1
- require_relative "test_helper"
2
-
3
- describe Committee::ParamValidator do
4
- before do
5
- @schema = Committee::Schema.new(File.read("./test/data/schema.json"))
6
- # POST /account/app-transfers
7
- @link_schema = @schema["app-transfer"]["links"][0]
8
- end
9
-
10
- it "passes through a valid request" do
11
- params = {
12
- "app" => "heroku-api",
13
- "recipient" => "owner@heroku.com",
14
- }
15
- validate(params, @schema, @link_schema)
16
- end
17
-
18
- it "detects a missing parameter" do
19
- e = assert_raises(Committee::InvalidParams) do
20
- validate({}, @schema, @link_schema)
21
- end
22
- message = "Require params: app, recipient."
23
- assert_equal message, e.message
24
- end
25
-
26
- it "doesn't error on an extraneous parameter with allow_extra" do
27
- params = {
28
- "app" => "heroku-api",
29
- "cloud" => "production",
30
- "recipient" => "owner@heroku.com",
31
- }
32
- validate(params, @schema, @link_schema, allow_extra: true)
33
- end
34
-
35
- it "detects a parameter of the wrong type" do
36
- params = {
37
- "app" => "heroku-api",
38
- "recipient" => 123,
39
- }
40
- e = assert_raises(Committee::InvalidType) do
41
- validate(params, @schema, @link_schema)
42
- end
43
- message = %{Invalid type for key "recipient": expected 123 to be ["string"].}
44
- assert_equal message, e.message
45
- end
46
-
47
- it "detects a parameter of the wrong format" do
48
- params = {
49
- "app" => "heroku-api",
50
- "recipient" => "not-email",
51
- }
52
- e = assert_raises(Committee::InvalidFormat) do
53
- validate(params, @schema, @link_schema)
54
- end
55
- message = %{Invalid format for key "recipient": expected "not-email" to be "email".}
56
- assert_equal message, e.message
57
- end
58
-
59
- it "detects a parameter of the wrong pattern" do
60
- params = {
61
- "name" => "%@!"
62
- }
63
- link_schema = @schema["app"]["links"][0]
64
- e = assert_raises(Committee::InvalidPattern) do
65
- validate(params, @schema, link_schema)
66
- end
67
- message = %{Invalid pattern for key "name": expected %@! to match "(?-mix:^[a-z][a-z0-9-]{3,30}$)".}
68
- assert_equal message, e.message
69
- end
70
-
71
- describe "complex arrays" do
72
- it "passes an array parameter" do
73
- params = {
74
- "updates" => [
75
- { "name" => "bamboo", "state" => "private" },
76
- { "name" => "cedar", "state" => "public" },
77
- ]
78
- }
79
- link_schema = @schema["stack"]["links"][2]
80
- validate(params, @schema, link_schema)
81
- end
82
-
83
- it "detects an array item with a parameter of the wrong type" do
84
- params = {
85
- "updates" => [
86
- { "name" => "bamboo", "state" => 123 },
87
- ]
88
- }
89
- link_schema = @schema["stack"]["links"][2]
90
- e = assert_raises(Committee::InvalidType) do
91
- validate(params, @schema, link_schema)
92
- end
93
- message = %{Invalid type for key "state": expected 123 to be ["string"].}
94
- assert_equal message, e.message
95
- end
96
- end
97
-
98
- describe "simple arrays" do
99
- it "passes an array parameter" do
100
- params = {
101
- "password" => "1234",
102
- "flags" => [ "vip", "customer" ]
103
- }
104
- link_schema = @schema["account"]["links"][1]
105
- validate(params, @schema, link_schema)
106
- end
107
-
108
- it "detects an array item with a parameter of the wrong type" do
109
- params = {
110
- "password" => "1234",
111
- "flags" => [ "vip", "customer", 999 ]
112
- }
113
- link_schema = @schema["account"]["links"][1]
114
- e = assert_raises(Committee::InvalidType) do
115
- validate(params, @schema, link_schema)
116
- end
117
- message = %{Invalid type for key "flags": expected 999 to be ["string"].}
118
- assert_equal message, e.message
119
- end
120
- end
121
-
122
- private
123
-
124
- def validate(params, schema, link_schema, options = {})
125
- Committee::ParamValidator.new(params, schema, link_schema, options).call
126
- end
127
- end
@@ -1,55 +0,0 @@
1
- require "benchmark"
2
- require_relative "../test_helper"
3
-
4
- describe Committee::Middleware::RequestValidation do
5
- include Rack::Test::Methods
6
-
7
- def app
8
- @app
9
- end
10
-
11
- N = 50000
12
-
13
- it "is reasonably quick" do
14
- params = MultiJson.encode({
15
- "app" => "heroku-api",
16
- "recipient" => "owner@heroku.com",
17
- })
18
-
19
- Benchmark.benchmark(Benchmark::CAPTION, 7, Benchmark::FORMAT, ">overhead:") do |x|
20
- raw = x.report("raw") do
21
- N.times do
22
- @app = new_rack_app(raw: true)
23
- header "Content-Type", "application/json"
24
- post "/account/app-transfers", params
25
- end
26
- end
27
-
28
- rich = x.report("rich") do
29
- N.times do
30
- @app = new_rack_app
31
- header "Content-Type", "application/json"
32
- post "/account/app-transfers", params
33
- end
34
- end
35
-
36
- puts "average overhead = #{(rich.real - raw.real) / N}"
37
- end
38
- end
39
-
40
- private
41
-
42
- def new_rack_app(options = {})
43
- Rack::Builder.new {
44
- unless options.delete(:raw)
45
- options = {
46
- schema: File.read("./test/data/schema.json")
47
- }.merge(options)
48
- use Committee::Middleware::RequestValidation, options
49
- end
50
- run lambda { |_|
51
- [200, {}, []]
52
- }
53
- }
54
- end
55
- end
data/test/schema_test.rb DELETED
@@ -1,36 +0,0 @@
1
- require_relative "test_helper"
2
-
3
- describe Committee::Schema do
4
- before do
5
- data = File.read("./test/data/schema.json")
6
- @schema = Committee::Schema.new(data)
7
- end
8
-
9
- it "is enumerable" do
10
- arr = @schema.to_a
11
- assert_equal "account", arr[0][0]
12
- assert arr[0][1].is_a?(Hash)
13
- end
14
-
15
- it "can lookup definitions" do
16
- expected = {
17
- "default" => nil,
18
- "description" => "slug size in bytes of app",
19
- "example" => 0,
20
- "readOnly" => true,
21
- "type" => ["number", "null"]
22
- }
23
- assert_equal expected, @schema.find("#/definitions/app/definitions/slug_size")
24
- end
25
-
26
- it "raises error on a non-existent definition" do
27
- assert_raises(Committee::ReferenceNotFound) do
28
- @schema.find("/schema/app#/definitions/bad_field")
29
- end
30
- end
31
-
32
- it "materializes regexes" do
33
- definition = @schema.find("#/definitions/app/definitions/git_url")
34
- assert definition["pattern"].is_a?(Regexp)
35
- end
36
- end