api-auth 1.3.2 → 1.4.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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +2 -2
  3. data/.travis.yml +4 -0
  4. data/Appraisals +6 -0
  5. data/CHANGELOG.md +36 -0
  6. data/Gemfile.lock +77 -44
  7. data/README.md +15 -8
  8. data/VERSION +1 -1
  9. data/api_auth.gemspec +4 -4
  10. data/gemfiles/rails_23.gemfile +1 -1
  11. data/gemfiles/rails_23.gemfile.lock +19 -11
  12. data/gemfiles/rails_30.gemfile +1 -1
  13. data/gemfiles/rails_30.gemfile.lock +19 -11
  14. data/gemfiles/rails_31.gemfile +1 -1
  15. data/gemfiles/rails_31.gemfile.lock +19 -11
  16. data/gemfiles/rails_32.gemfile +1 -1
  17. data/gemfiles/rails_32.gemfile.lock +19 -11
  18. data/gemfiles/rails_4.gemfile +1 -1
  19. data/gemfiles/rails_4.gemfile.lock +19 -11
  20. data/gemfiles/rails_41.gemfile +1 -1
  21. data/gemfiles/rails_41.gemfile.lock +19 -11
  22. data/gemfiles/rails_42.gemfile +9 -0
  23. data/gemfiles/rails_42.gemfile.lock +115 -0
  24. data/lib/api_auth/base.rb +37 -23
  25. data/lib/api_auth/headers.rb +23 -3
  26. data/lib/api_auth/request_drivers/action_controller.rb +4 -0
  27. data/lib/api_auth/request_drivers/curb.rb +4 -0
  28. data/lib/api_auth/request_drivers/faraday.rb +4 -0
  29. data/lib/api_auth/request_drivers/httpi.rb +5 -1
  30. data/lib/api_auth/request_drivers/net_http.rb +4 -0
  31. data/lib/api_auth/request_drivers/rack.rb +5 -1
  32. data/lib/api_auth/request_drivers/rest_client.rb +4 -0
  33. data/spec/api_auth_spec.rb +112 -628
  34. data/spec/headers_spec.rb +132 -289
  35. data/spec/helpers_spec.rb +2 -2
  36. data/spec/railtie_spec.rb +13 -8
  37. data/spec/request_drivers/action_controller_spec.rb +218 -0
  38. data/spec/request_drivers/action_dispatch_spec.rb +219 -0
  39. data/spec/request_drivers/curb_spec.rb +89 -0
  40. data/spec/request_drivers/faraday_spec.rb +243 -0
  41. data/spec/request_drivers/httpi_spec.rb +147 -0
  42. data/spec/request_drivers/net_http_spec.rb +185 -0
  43. data/spec/request_drivers/rack_spec.rb +288 -0
  44. data/spec/request_drivers/rest_client_spec.rb +311 -0
  45. metadata +44 -19
  46. data/spec/application_helper.rb +0 -2
  47. data/spec/test_helper.rb +0 -2
@@ -0,0 +1,185 @@
1
+ require 'spec_helper'
2
+
3
+ describe ApiAuth::RequestDrivers::NetHttpRequest do
4
+
5
+ let(:timestamp){ Time.now.utc.httpdate }
6
+
7
+ let(:request_path){ "/resource.xml?foo=bar&bar=foo" }
8
+
9
+ let(:request_headers){
10
+ {
11
+ 'Authorization' => 'APIAuth 1044:12345',
12
+ 'content-md5' => '1B2M2Y8AsgTpgAmY7PhCfg==',
13
+ 'content-type' => 'text/plain',
14
+ 'date' => timestamp
15
+ }
16
+ }
17
+
18
+ let(:request) do
19
+ net_http_request = Net::HTTP::Put.new(request_path, request_headers)
20
+ net_http_request.body = "hello\nworld"
21
+ net_http_request
22
+ end
23
+
24
+ subject(:driven_request){ ApiAuth::RequestDrivers::NetHttpRequest.new(request) }
25
+
26
+ describe "getting headers correctly" do
27
+ describe "#content_type" do
28
+ it "gets the content_type" do
29
+ expect(driven_request.content_type).to eq('text/plain')
30
+ end
31
+
32
+ it "gets multipart content_type" do
33
+ request = Net::HTTP::Put::Multipart.new("/resource.xml?foo=bar&bar=foo",
34
+ 'file' => UploadIO.new(File.new('spec/fixtures/upload.png'), 'image/png', 'upload.png'))
35
+ driven_request = ApiAuth::RequestDrivers::NetHttpRequest.new(request)
36
+ expect(driven_request.content_type).to match 'multipart/form-data; boundary='
37
+ end
38
+ end
39
+
40
+ it "gets the content_md5" do
41
+ expect(driven_request.content_md5).to eq('1B2M2Y8AsgTpgAmY7PhCfg==')
42
+ end
43
+
44
+ it "gets the request_uri" do
45
+ expect(driven_request.request_uri).to eq('/resource.xml?foo=bar&bar=foo')
46
+ end
47
+
48
+ it "gets the timestamp" do
49
+ expect(driven_request.timestamp).to eq(timestamp)
50
+ end
51
+
52
+ it "gets the authorization_header" do
53
+ expect(driven_request.authorization_header).to eq('APIAuth 1044:12345')
54
+ end
55
+
56
+ describe "#calculated_md5" do
57
+ it "calculates md5 from the body" do
58
+ expect(driven_request.calculated_md5).to eq('kZXQvrKoieG+Be1rsZVINw==')
59
+ end
60
+
61
+ it "treats no body as empty string" do
62
+ request.body = nil
63
+ expect(driven_request.calculated_md5).to eq('1B2M2Y8AsgTpgAmY7PhCfg==')
64
+ end
65
+
66
+ it "calculates correctly for multipart content" do
67
+ request.body = nil
68
+ request.body_stream = File.new('spec/fixtures/upload.png')
69
+ expect(driven_request.calculated_md5).to eq('k4U8MTA3RHDcewBzymVNEQ==')
70
+ end
71
+ end
72
+
73
+ describe "http_method" do
74
+ context "when put request" do
75
+ let(:request){ Net::HTTP::Put.new(request_path, request_headers) }
76
+
77
+ it "returns upcased put" do
78
+ expect(driven_request.http_method).to eq('PUT')
79
+ end
80
+ end
81
+
82
+ context "when get request" do
83
+ let(:request){ Net::HTTP::Get.new(request_path, request_headers) }
84
+
85
+ it "returns upcased get" do
86
+ expect(driven_request.http_method).to eq('GET')
87
+ end
88
+ end
89
+ end
90
+ end
91
+
92
+ describe "setting headers correctly" do
93
+ let(:request_headers){
94
+ {
95
+ 'content-type' => 'text/plain'
96
+ }
97
+ }
98
+
99
+ let(:request) do
100
+ Net::HTTP::Put.new(request_path, request_headers)
101
+ end
102
+
103
+ describe "#populate_content_md5" do
104
+ context "when request type has no body" do
105
+ let(:request) do
106
+ Net::HTTP::Get.new(request_path, request_headers)
107
+ end
108
+
109
+ it "doesn't populate content-md5" do
110
+ driven_request.populate_content_md5
111
+ expect(request["Content-MD5"]).to be_nil
112
+ end
113
+ end
114
+
115
+ context "when request type has a body" do
116
+ let(:request) do
117
+ net_http_request = Net::HTTP::Put.new(request_path, request_headers)
118
+ net_http_request.body = "hello\nworld"
119
+ net_http_request
120
+ end
121
+
122
+ it "populates content-md5" do
123
+ driven_request.populate_content_md5
124
+ expect(request["Content-MD5"]).to eq('kZXQvrKoieG+Be1rsZVINw==')
125
+ end
126
+ end
127
+ end
128
+
129
+ describe "#set_date" do
130
+ it "sets the date" do
131
+ allow(Time).to receive_message_chain(:now, :utc, :httpdate).and_return(timestamp)
132
+ driven_request.set_date
133
+ expect(request['DATE']).to eq(timestamp)
134
+ end
135
+ end
136
+
137
+ describe "#set_auth_header" do
138
+ it "sets the auth header" do
139
+ driven_request.set_auth_header('APIAuth 1044:54321')
140
+ expect(request['Authorization']).to eq('APIAuth 1044:54321')
141
+ end
142
+ end
143
+ end
144
+
145
+ describe "md5_mismatch?" do
146
+ context "when request type has no body" do
147
+ let(:request) do
148
+ Net::HTTP::Get.new(request_path, request_headers)
149
+ end
150
+
151
+
152
+ it "is false" do
153
+ expect(driven_request.md5_mismatch?).to be false
154
+ end
155
+ end
156
+
157
+ context "when request type has a body" do
158
+ let(:request) do
159
+ net_http_request = Net::HTTP::Put.new(request_path, request_headers)
160
+ net_http_request.body = "hello\nworld"
161
+ net_http_request
162
+ end
163
+
164
+ context "when calculated matches sent" do
165
+ before do
166
+ request["Content-MD5"] = 'kZXQvrKoieG+Be1rsZVINw=='
167
+ end
168
+
169
+ it "is false" do
170
+ expect(driven_request.md5_mismatch?).to be false
171
+ end
172
+ end
173
+
174
+ context "when calculated doesn't match sent" do
175
+ before do
176
+ request["Content-MD5"] = "3"
177
+ end
178
+
179
+ it "is true" do
180
+ expect(driven_request.md5_mismatch?).to be true
181
+ end
182
+ end
183
+ end
184
+ end
185
+ end
@@ -0,0 +1,288 @@
1
+ require 'spec_helper'
2
+
3
+ describe ApiAuth::RequestDrivers::RackRequest do
4
+
5
+ let(:timestamp){ Time.now.utc.httpdate }
6
+
7
+ let(:request_path){ "/resource.xml?foo=bar&bar=foo" }
8
+
9
+ let(:request_headers){
10
+ {
11
+ 'Authorization' => 'APIAuth 1044:12345',
12
+ 'Content-MD5' => '1B2M2Y8AsgTpgAmY7PhCfg==',
13
+ 'Content-Type' => 'text/plain',
14
+ 'Date' => timestamp
15
+ }
16
+ }
17
+
18
+ let(:request) do
19
+ Rack::Request.new(
20
+ Rack::MockRequest.env_for(
21
+ request_path,
22
+ :method => :put,
23
+ :input => "hello\nworld"
24
+ ).merge!(request_headers)
25
+ )
26
+ end
27
+
28
+ subject(:driven_request){ ApiAuth::RequestDrivers::RackRequest.new(request) }
29
+
30
+ describe "getting headers correctly" do
31
+ it "gets the content_type" do
32
+ expect(driven_request.content_type).to eq('text/plain')
33
+ end
34
+
35
+ it "gets the content_md5" do
36
+ expect(driven_request.content_md5).to eq('1B2M2Y8AsgTpgAmY7PhCfg==')
37
+ end
38
+
39
+ it "gets the request_uri" do
40
+ expect(driven_request.request_uri).to eq('/resource.xml?foo=bar&bar=foo')
41
+ end
42
+
43
+ it "gets the timestamp" do
44
+ expect(driven_request.timestamp).to eq(timestamp)
45
+ end
46
+
47
+ it "gets the authorization_header" do
48
+ expect(driven_request.authorization_header).to eq('APIAuth 1044:12345')
49
+ end
50
+
51
+ describe "#calculated_md5" do
52
+ it "calculates md5 from the body" do
53
+ expect(driven_request.calculated_md5).to eq('kZXQvrKoieG+Be1rsZVINw==')
54
+ end
55
+
56
+ it "treats no body as empty string" do
57
+ request = Rack::Request.new(
58
+ Rack::MockRequest.env_for(
59
+ request_path,
60
+ :method => :put
61
+ ).merge!(request_headers)
62
+ )
63
+ driven_request = ApiAuth::RequestDrivers::RackRequest.new(request)
64
+ expect(driven_request.calculated_md5).to eq('1B2M2Y8AsgTpgAmY7PhCfg==')
65
+ end
66
+ end
67
+
68
+ describe "http_method" do
69
+ context "when put request" do
70
+ let(:request) do
71
+ Rack::Request.new(
72
+ Rack::MockRequest.env_for(
73
+ request_path,
74
+ :method => :put
75
+ ).merge!(request_headers)
76
+ )
77
+ end
78
+
79
+ it "returns upcased put" do
80
+ expect(driven_request.http_method).to eq('PUT')
81
+ end
82
+ end
83
+
84
+ context "when get request" do
85
+ let(:request) do
86
+ Rack::Request.new(
87
+ Rack::MockRequest.env_for(
88
+ request_path,
89
+ :method => :get
90
+ ).merge!(request_headers)
91
+ )
92
+ end
93
+
94
+ it "returns upcased get" do
95
+ expect(driven_request.http_method).to eq('GET')
96
+ end
97
+ end
98
+ end
99
+ end
100
+
101
+ describe "setting headers correctly" do
102
+ let(:request_headers){
103
+ {
104
+ 'content-type' => 'text/plain'
105
+ }
106
+ }
107
+
108
+ describe "#populate_content_md5" do
109
+ context "when getting" do
110
+ let(:request) do
111
+ Rack::Request.new(
112
+ Rack::MockRequest.env_for(
113
+ request_path,
114
+ :method => :get
115
+ ).merge!(request_headers)
116
+ )
117
+ end
118
+
119
+ it "doesn't populate content-md5" do
120
+ driven_request.populate_content_md5
121
+ expect(request.env["Content-MD5"]).to be_nil
122
+ end
123
+ end
124
+
125
+ context "when posting" do
126
+ let(:request) do
127
+ Rack::Request.new(
128
+ Rack::MockRequest.env_for(
129
+ request_path,
130
+ :method => :post,
131
+ :input => "hello\nworld"
132
+ ).merge!(request_headers)
133
+ )
134
+ end
135
+
136
+ it "populates content-md5" do
137
+ driven_request.populate_content_md5
138
+ expect(request.env["Content-MD5"]).to eq('kZXQvrKoieG+Be1rsZVINw==')
139
+ end
140
+ end
141
+
142
+ context "when putting" do
143
+ let(:request) do
144
+ Rack::Request.new(
145
+ Rack::MockRequest.env_for(
146
+ request_path,
147
+ :method => :put,
148
+ :input => "hello\nworld"
149
+ ).merge!(request_headers)
150
+ )
151
+ end
152
+
153
+ it "populates content-md5" do
154
+ driven_request.populate_content_md5
155
+ expect(request.env["Content-MD5"]).to eq('kZXQvrKoieG+Be1rsZVINw==')
156
+ end
157
+ end
158
+
159
+ context "when deleting" do
160
+ let(:request) do
161
+ Rack::Request.new(
162
+ Rack::MockRequest.env_for(
163
+ request_path,
164
+ :method => :delete
165
+ ).merge!(request_headers)
166
+ )
167
+ end
168
+
169
+ it "doesn't populate content-md5" do
170
+ driven_request.populate_content_md5
171
+ expect(request.env["Content-MD5"]).to be_nil
172
+ end
173
+ end
174
+
175
+ end
176
+
177
+ describe "#set_date" do
178
+ it "sets the date" do
179
+ allow(Time).to receive_message_chain(:now, :utc, :httpdate).and_return(timestamp)
180
+ driven_request.set_date
181
+ expect(request.env['DATE']).to eq(timestamp)
182
+ end
183
+ end
184
+
185
+ describe "#set_auth_header" do
186
+ it "sets the auth header" do
187
+ driven_request.set_auth_header('APIAuth 1044:54321')
188
+ expect(request.env['Authorization']).to eq('APIAuth 1044:54321')
189
+ end
190
+ end
191
+ end
192
+
193
+ describe "md5_mismatch?" do
194
+ context "when getting" do
195
+ let(:request) do
196
+ Rack::Request.new(
197
+ Rack::MockRequest.env_for(
198
+ request_path,
199
+ :method => :get
200
+ ).merge!(request_headers)
201
+ )
202
+ end
203
+
204
+ it "is false" do
205
+ expect(driven_request.md5_mismatch?).to be false
206
+ end
207
+ end
208
+
209
+ context "when posting" do
210
+ let(:request) do
211
+ Rack::Request.new(
212
+ Rack::MockRequest.env_for(
213
+ request_path,
214
+ :method => :post,
215
+ :input => "hello\nworld"
216
+ ).merge!(request_headers)
217
+ )
218
+ end
219
+
220
+ context "when calculated matches sent" do
221
+ before do
222
+ request.env["Content-MD5"] = 'kZXQvrKoieG+Be1rsZVINw=='
223
+ end
224
+
225
+ it "is false" do
226
+ expect(driven_request.md5_mismatch?).to be false
227
+ end
228
+ end
229
+
230
+ context "when calculated doesn't match sent" do
231
+ before do
232
+ request.env["Content-MD5"] = "3"
233
+ end
234
+
235
+ it "is true" do
236
+ expect(driven_request.md5_mismatch?).to be true
237
+ end
238
+ end
239
+ end
240
+
241
+ context "when putting" do
242
+ let(:request) do
243
+ Rack::Request.new(
244
+ Rack::MockRequest.env_for(
245
+ request_path,
246
+ :method => :put,
247
+ :input => "hello\nworld"
248
+ ).merge!(request_headers)
249
+ )
250
+ end
251
+
252
+ context "when calculated matches sent" do
253
+ before do
254
+ request.env["Content-MD5"] = 'kZXQvrKoieG+Be1rsZVINw=='
255
+ end
256
+
257
+ it "is false" do
258
+ expect(driven_request.md5_mismatch?).to be false
259
+ end
260
+ end
261
+
262
+ context "when calculated doesn't match sent" do
263
+ before do
264
+ request.env["Content-MD5"] = "3"
265
+ end
266
+
267
+ it "is true" do
268
+ expect(driven_request.md5_mismatch?).to be true
269
+ end
270
+ end
271
+ end
272
+
273
+ context "when deleting" do
274
+ let(:request) do
275
+ Rack::Request.new(
276
+ Rack::MockRequest.env_for(
277
+ request_path,
278
+ :method => :delete
279
+ ).merge!(request_headers)
280
+ )
281
+ end
282
+
283
+ it "is false" do
284
+ expect(driven_request.md5_mismatch?).to be false
285
+ end
286
+ end
287
+ end
288
+ end