api-auth 1.5.0 → 2.6.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.
- checksums.yaml +5 -5
- data/.github/workflows/main.yml +71 -0
- data/.gitignore +13 -44
- data/.rubocop.yml +39 -0
- data/.rubocop_todo.yml +83 -0
- data/Appraisals +12 -36
- data/CHANGELOG.md +75 -1
- data/README.md +155 -52
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/api_auth.gemspec +35 -23
- data/gemfiles/rails_60.gemfile +9 -0
- data/gemfiles/rails_61.gemfile +9 -0
- data/gemfiles/rails_70.gemfile +9 -0
- data/lib/api-auth.rb +1 -1
- data/lib/api_auth/base.rb +41 -35
- data/lib/api_auth/errors.rb +4 -3
- data/lib/api_auth/headers.rb +38 -42
- data/lib/api_auth/helpers.rb +7 -16
- data/lib/api_auth/railtie.rb +34 -74
- data/lib/api_auth/request_drivers/action_controller.rb +27 -27
- data/lib/api_auth/request_drivers/action_dispatch.rb +0 -6
- data/lib/api_auth/request_drivers/curb.rb +16 -21
- data/lib/api_auth/request_drivers/faraday.rb +25 -34
- data/lib/api_auth/request_drivers/faraday_env.rb +102 -0
- data/lib/api_auth/request_drivers/grape_request.rb +87 -0
- data/lib/api_auth/request_drivers/http.rb +96 -0
- data/lib/api_auth/request_drivers/httpi.rb +22 -27
- data/lib/api_auth/request_drivers/net_http.rb +21 -26
- data/lib/api_auth/request_drivers/rack.rb +23 -28
- data/lib/api_auth/request_drivers/rest_client.rb +24 -29
- data/lib/api_auth.rb +4 -0
- data/lib/faraday/api_auth/middleware.rb +35 -0
- data/lib/faraday/api_auth.rb +8 -0
- data/spec/api_auth_spec.rb +135 -96
- data/spec/faraday_middleware_spec.rb +17 -0
- data/spec/headers_spec.rb +148 -108
- data/spec/helpers_spec.rb +8 -10
- data/spec/railtie_spec.rb +80 -99
- data/spec/request_drivers/action_controller_spec.rb +122 -79
- data/spec/request_drivers/action_dispatch_spec.rb +212 -85
- data/spec/request_drivers/curb_spec.rb +36 -33
- data/spec/request_drivers/faraday_env_spec.rb +188 -0
- data/spec/request_drivers/faraday_spec.rb +87 -83
- data/spec/request_drivers/grape_request_spec.rb +280 -0
- data/spec/request_drivers/http_spec.rb +190 -0
- data/spec/request_drivers/httpi_spec.rb +59 -59
- data/spec/request_drivers/net_http_spec.rb +70 -66
- data/spec/request_drivers/rack_spec.rb +101 -97
- data/spec/request_drivers/rest_client_spec.rb +218 -144
- data/spec/spec_helper.rb +15 -12
- metadata +144 -83
- data/.travis.yml +0 -40
- data/Gemfile.lock +0 -115
- data/gemfiles/rails_23.gemfile +0 -9
- data/gemfiles/rails_23.gemfile.lock +0 -70
- data/gemfiles/rails_30.gemfile +0 -9
- data/gemfiles/rails_30.gemfile.lock +0 -92
- data/gemfiles/rails_31.gemfile +0 -9
- data/gemfiles/rails_31.gemfile.lock +0 -98
- data/gemfiles/rails_32.gemfile +0 -9
- data/gemfiles/rails_32.gemfile.lock +0 -97
- data/gemfiles/rails_4.gemfile +0 -9
- data/gemfiles/rails_4.gemfile.lock +0 -94
- data/gemfiles/rails_41.gemfile +0 -9
- data/gemfiles/rails_41.gemfile.lock +0 -98
- data/gemfiles/rails_42.gemfile +0 -9
- data/gemfiles/rails_42.gemfile.lock +0 -115
|
@@ -3,234 +3,361 @@ require 'spec_helper'
|
|
|
3
3
|
if defined?(ActionDispatch::Request)
|
|
4
4
|
|
|
5
5
|
describe ApiAuth::RequestDrivers::ActionDispatchRequest do
|
|
6
|
-
|
|
7
|
-
let(:
|
|
6
|
+
let(:timestamp) { Time.now.utc.httpdate }
|
|
7
|
+
let(:content_sha256) { '47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=' }
|
|
8
|
+
let(:content_md5) { '+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=' }
|
|
8
9
|
|
|
9
10
|
let(:request) do
|
|
10
11
|
ActionDispatch::Request.new(
|
|
11
|
-
'AUTHORIZATION'
|
|
12
|
-
'PATH_INFO'
|
|
13
|
-
'QUERY_STRING'
|
|
12
|
+
'AUTHORIZATION' => 'APIAuth 1044:12345',
|
|
13
|
+
'PATH_INFO' => '/resource.xml',
|
|
14
|
+
'QUERY_STRING' => 'foo=bar&bar=foo',
|
|
14
15
|
'REQUEST_METHOD' => 'PUT',
|
|
15
|
-
'
|
|
16
|
-
'CONTENT_TYPE'
|
|
16
|
+
'HTTP_X_AUTHORIZATION_CONTENT_SHA256' => content_sha256,
|
|
17
|
+
'CONTENT_TYPE' => 'text/plain',
|
|
17
18
|
'CONTENT_LENGTH' => '11',
|
|
18
|
-
'HTTP_DATE'
|
|
19
|
-
'rack.input'
|
|
19
|
+
'HTTP_DATE' => timestamp,
|
|
20
|
+
'rack.input' => StringIO.new("hello\nworld")
|
|
20
21
|
)
|
|
21
22
|
end
|
|
22
23
|
|
|
23
|
-
|
|
24
|
+
let(:request2) do
|
|
25
|
+
ActionDispatch::Request.new(
|
|
26
|
+
'AUTHORIZATION' => 'APIAuth 1044:12345',
|
|
27
|
+
'PATH_INFO' => '/resource.xml',
|
|
28
|
+
'QUERY_STRING' => 'foo=bar&bar=foo',
|
|
29
|
+
'REQUEST_METHOD' => 'PUT',
|
|
30
|
+
'X_AUTHORIZATION_CONTENT_SHA256' => content_sha256,
|
|
31
|
+
'CONTENT_TYPE' => 'text/plain',
|
|
32
|
+
'CONTENT_LENGTH' => '11',
|
|
33
|
+
'HTTP_DATE' => timestamp,
|
|
34
|
+
'rack.input' => StringIO.new("hello\nworld")
|
|
35
|
+
)
|
|
36
|
+
end
|
|
24
37
|
|
|
25
|
-
|
|
26
|
-
|
|
38
|
+
let(:request3) do
|
|
39
|
+
ActionDispatch::Request.new(
|
|
40
|
+
'AUTHORIZATION' => 'APIAuth 1044:12345',
|
|
41
|
+
'PATH_INFO' => '/resource.xml',
|
|
42
|
+
'QUERY_STRING' => 'foo=bar&bar=foo',
|
|
43
|
+
'REQUEST_METHOD' => 'PUT',
|
|
44
|
+
'X-AUTHORIZATION-CONTENT-SHA256' => content_sha256,
|
|
45
|
+
'CONTENT_TYPE' => 'text/plain',
|
|
46
|
+
'CONTENT_LENGTH' => '11',
|
|
47
|
+
'HTTP_DATE' => timestamp,
|
|
48
|
+
'rack.input' => StringIO.new("hello\nworld")
|
|
49
|
+
)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
let(:request_md5) do
|
|
53
|
+
ActionDispatch::Request.new(
|
|
54
|
+
'AUTHORIZATION' => 'APIAuth 1044:12345',
|
|
55
|
+
'PATH_INFO' => '/resource.xml',
|
|
56
|
+
'QUERY_STRING' => 'foo=bar&bar=foo',
|
|
57
|
+
'REQUEST_METHOD' => 'PUT',
|
|
58
|
+
'CONTENT_MD5' => content_md5,
|
|
59
|
+
'CONTENT_TYPE' => 'text/plain',
|
|
60
|
+
'CONTENT_LENGTH' => '11',
|
|
61
|
+
'HTTP_DATE' => timestamp,
|
|
62
|
+
'rack.input' => StringIO.new("hello\nworld")
|
|
63
|
+
)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
subject(:driven_request) { ApiAuth::RequestDrivers::ActionDispatchRequest.new(request) }
|
|
67
|
+
subject(:driven_request_md5) do
|
|
68
|
+
ApiAuth::RequestDrivers::ActionDispatchRequest.new(request_md5,
|
|
69
|
+
authorize_md5: true)
|
|
70
|
+
end
|
|
71
|
+
subject(:driven_request_sha2_with_md5) { ApiAuth::RequestDrivers::ActionDispatchRequest.new(request, authorize_md5: true) }
|
|
72
|
+
|
|
73
|
+
describe 'getting headers correctly' do
|
|
74
|
+
it 'gets the content_type' do
|
|
27
75
|
expect(driven_request.content_type).to eq('text/plain')
|
|
28
76
|
end
|
|
29
77
|
|
|
30
|
-
it
|
|
31
|
-
expect(driven_request.
|
|
78
|
+
it 'gets the content_hash' do
|
|
79
|
+
expect(driven_request.content_hash).to eq(content_sha256)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
it 'gets the content_hash for request 2' do
|
|
83
|
+
example_request = ApiAuth::RequestDrivers::ActionDispatchRequest.new(request2)
|
|
84
|
+
expect(example_request.content_hash).to eq(content_sha256)
|
|
32
85
|
end
|
|
33
86
|
|
|
34
|
-
it
|
|
87
|
+
it 'gets the content_hash for request 3' do
|
|
88
|
+
example_request = ApiAuth::RequestDrivers::ActionDispatchRequest.new(request3)
|
|
89
|
+
expect(example_request.content_hash).to eq(content_sha256)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
it 'gets the content_hash for request_md5' do
|
|
93
|
+
example_request = ApiAuth::RequestDrivers::ActionDispatchRequest.new(request_md5, authorize_md5: true)
|
|
94
|
+
expect(example_request.content_hash).to eq(content_md5)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
it 'gets the request_uri' do
|
|
35
98
|
expect(driven_request.request_uri).to eq('/resource.xml?foo=bar&bar=foo')
|
|
36
99
|
end
|
|
37
100
|
|
|
38
|
-
it
|
|
101
|
+
it 'gets the timestamp' do
|
|
39
102
|
expect(driven_request.timestamp).to eq(timestamp)
|
|
40
103
|
end
|
|
41
104
|
|
|
42
|
-
it
|
|
105
|
+
it 'gets the authorization_header' do
|
|
43
106
|
expect(driven_request.authorization_header).to eq('APIAuth 1044:12345')
|
|
44
107
|
end
|
|
45
108
|
|
|
46
|
-
describe
|
|
47
|
-
it
|
|
48
|
-
expect(driven_request.
|
|
109
|
+
describe '#calculated_hash' do
|
|
110
|
+
it 'calculates hash from the body' do
|
|
111
|
+
expect(driven_request.calculated_hash).to eq(['JsYKYdAdtYNspw/v1EpqAWYgQTyO9fJZpsVhLU9507g='])
|
|
49
112
|
end
|
|
50
113
|
|
|
51
|
-
it
|
|
114
|
+
it 'calculates hashes from the body with md5 compatibility option' do
|
|
115
|
+
expect(driven_request_md5.calculated_hash).to eq(%w[JsYKYdAdtYNspw/v1EpqAWYgQTyO9fJZpsVhLU9507g= kZXQvrKoieG+Be1rsZVINw==])
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
it 'treats no body as empty string' do
|
|
52
119
|
request.env['rack.input'] = StringIO.new
|
|
53
120
|
request.env['CONTENT_LENGTH'] = 0
|
|
54
|
-
expect(driven_request.
|
|
121
|
+
expect(driven_request.calculated_hash).to eq(['47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU='])
|
|
55
122
|
end
|
|
56
123
|
end
|
|
57
124
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
context "when put request" do
|
|
125
|
+
describe 'http_method' do
|
|
126
|
+
context 'when put request' do
|
|
61
127
|
let(:request) do
|
|
62
128
|
ActionDispatch::Request.new('REQUEST_METHOD' => 'PUT')
|
|
63
129
|
end
|
|
64
130
|
|
|
65
|
-
it
|
|
131
|
+
it 'returns upcased put' do
|
|
66
132
|
expect(driven_request.http_method).to eq('PUT')
|
|
67
133
|
end
|
|
68
134
|
end
|
|
69
135
|
|
|
70
|
-
context
|
|
136
|
+
context 'when get request' do
|
|
71
137
|
let(:request) do
|
|
72
138
|
ActionDispatch::Request.new('REQUEST_METHOD' => 'GET')
|
|
73
139
|
end
|
|
74
140
|
|
|
75
|
-
it
|
|
141
|
+
it 'returns upcased get' do
|
|
76
142
|
expect(driven_request.http_method).to eq('GET')
|
|
77
143
|
end
|
|
78
144
|
end
|
|
79
145
|
end
|
|
80
146
|
end
|
|
81
147
|
|
|
82
|
-
describe
|
|
148
|
+
describe 'setting headers correctly' do
|
|
83
149
|
let(:request) do
|
|
84
150
|
ActionDispatch::Request.new(
|
|
85
|
-
'PATH_INFO'
|
|
86
|
-
'QUERY_STRING'
|
|
151
|
+
'PATH_INFO' => '/resource.xml',
|
|
152
|
+
'QUERY_STRING' => 'foo=bar&bar=foo',
|
|
87
153
|
'REQUEST_METHOD' => 'PUT',
|
|
88
|
-
'CONTENT_TYPE'
|
|
154
|
+
'CONTENT_TYPE' => 'text/plain',
|
|
89
155
|
'CONTENT_LENGTH' => '11',
|
|
90
|
-
'rack.input'
|
|
156
|
+
'rack.input' => StringIO.new("hello\nworld")
|
|
91
157
|
)
|
|
92
158
|
end
|
|
93
159
|
|
|
94
|
-
describe
|
|
95
|
-
context
|
|
96
|
-
it "doesn't populate content
|
|
160
|
+
describe '#populate_content_hash' do
|
|
161
|
+
context 'when getting' do
|
|
162
|
+
it "doesn't populate content hash" do
|
|
97
163
|
request.env['REQUEST_METHOD'] = 'GET'
|
|
98
|
-
driven_request.
|
|
99
|
-
expect(request.env[
|
|
164
|
+
driven_request.populate_content_hash
|
|
165
|
+
expect(request.env['X-AUTHORIZATION-CONTENT-SHA256']).to be_nil
|
|
100
166
|
end
|
|
101
167
|
end
|
|
102
168
|
|
|
103
|
-
context
|
|
104
|
-
it
|
|
169
|
+
context 'when posting' do
|
|
170
|
+
it 'populates content hash' do
|
|
105
171
|
request.env['REQUEST_METHOD'] = 'POST'
|
|
106
|
-
driven_request.
|
|
107
|
-
expect(request.env[
|
|
172
|
+
driven_request.populate_content_hash
|
|
173
|
+
expect(request.env['X-AUTHORIZATION-CONTENT-SHA256']).to eq(['JsYKYdAdtYNspw/v1EpqAWYgQTyO9fJZpsVhLU9507g='])
|
|
108
174
|
end
|
|
109
175
|
|
|
110
|
-
it
|
|
111
|
-
driven_request.
|
|
112
|
-
expect(driven_request.
|
|
176
|
+
it 'refreshes the cached headers' do
|
|
177
|
+
driven_request.populate_content_hash
|
|
178
|
+
expect(driven_request.content_hash).to eq(['JsYKYdAdtYNspw/v1EpqAWYgQTyO9fJZpsVhLU9507g='])
|
|
113
179
|
end
|
|
114
180
|
end
|
|
115
181
|
|
|
116
|
-
context
|
|
117
|
-
it
|
|
182
|
+
context 'when putting' do
|
|
183
|
+
it 'populates content hash' do
|
|
118
184
|
request.env['REQUEST_METHOD'] = 'PUT'
|
|
119
|
-
driven_request.
|
|
120
|
-
expect(request.env[
|
|
185
|
+
driven_request.populate_content_hash
|
|
186
|
+
expect(request.env['X-AUTHORIZATION-CONTENT-SHA256']).to eq(['JsYKYdAdtYNspw/v1EpqAWYgQTyO9fJZpsVhLU9507g='])
|
|
121
187
|
end
|
|
122
188
|
|
|
123
|
-
it
|
|
124
|
-
driven_request.
|
|
125
|
-
expect(driven_request.
|
|
189
|
+
it 'refreshes the cached headers' do
|
|
190
|
+
driven_request.populate_content_hash
|
|
191
|
+
expect(driven_request.content_hash).to eq(['JsYKYdAdtYNspw/v1EpqAWYgQTyO9fJZpsVhLU9507g='])
|
|
126
192
|
end
|
|
127
193
|
end
|
|
128
194
|
|
|
129
|
-
context
|
|
130
|
-
it "doesn't populate content
|
|
195
|
+
context 'when deleting' do
|
|
196
|
+
it "doesn't populate content hash" do
|
|
131
197
|
request.env['REQUEST_METHOD'] = 'DELETE'
|
|
132
|
-
driven_request.
|
|
133
|
-
expect(request.env[
|
|
198
|
+
driven_request.populate_content_hash
|
|
199
|
+
expect(request.env['X-AUTHORIZATION-CONTENT-SHA256']).to be_nil
|
|
134
200
|
end
|
|
135
201
|
end
|
|
136
|
-
|
|
137
202
|
end
|
|
138
203
|
|
|
139
|
-
describe
|
|
204
|
+
describe '#set_date' do
|
|
140
205
|
before do
|
|
141
206
|
allow(Time).to receive_message_chain(:now, :utc, :httpdate).and_return(timestamp)
|
|
142
207
|
end
|
|
143
208
|
|
|
144
|
-
it
|
|
209
|
+
it 'sets the date header of the request' do
|
|
145
210
|
driven_request.set_date
|
|
146
211
|
expect(request.env['HTTP_DATE']).to eq(timestamp)
|
|
147
212
|
end
|
|
148
213
|
|
|
149
|
-
it
|
|
214
|
+
it 'refreshes the cached headers' do
|
|
150
215
|
driven_request.set_date
|
|
151
216
|
expect(driven_request.timestamp).to eq(timestamp)
|
|
152
217
|
end
|
|
153
218
|
end
|
|
154
219
|
|
|
155
|
-
describe
|
|
156
|
-
it
|
|
220
|
+
describe '#set_auth_header' do
|
|
221
|
+
it 'sets the auth header' do
|
|
157
222
|
driven_request.set_auth_header('APIAuth 1044:54321')
|
|
158
223
|
expect(request.env['Authorization']).to eq('APIAuth 1044:54321')
|
|
159
224
|
end
|
|
160
225
|
end
|
|
161
226
|
end
|
|
162
227
|
|
|
163
|
-
describe
|
|
164
|
-
context
|
|
228
|
+
describe 'content_hash_mismatch?' do
|
|
229
|
+
context 'when getting' do
|
|
165
230
|
before do
|
|
166
231
|
request.env['REQUEST_METHOD'] = 'GET'
|
|
232
|
+
request_md5.env['REQUEST_METHOD'] = 'GET'
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
it 'is false' do
|
|
236
|
+
expect(driven_request.content_hash_mismatch?).to be false
|
|
167
237
|
end
|
|
168
238
|
|
|
169
|
-
it
|
|
170
|
-
expect(
|
|
239
|
+
it 'is false with md5' do
|
|
240
|
+
expect(driven_request_md5.content_hash_mismatch?).to be false
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
it 'is false with sha2 and md5 compatibility on' do
|
|
244
|
+
expect(driven_request_sha2_with_md5.content_hash_mismatch?).to be false
|
|
171
245
|
end
|
|
172
246
|
end
|
|
173
247
|
|
|
174
|
-
context
|
|
248
|
+
context 'when posting' do
|
|
175
249
|
before do
|
|
176
250
|
request.env['REQUEST_METHOD'] = 'POST'
|
|
251
|
+
request_md5.env['REQUEST_METHOD'] = 'POST'
|
|
177
252
|
end
|
|
178
253
|
|
|
179
|
-
context
|
|
254
|
+
context 'when calculated matches sent' do
|
|
180
255
|
before do
|
|
181
|
-
request.env[
|
|
256
|
+
request.env['X-AUTHORIZATION-CONTENT-SHA256'] = 'JsYKYdAdtYNspw/v1EpqAWYgQTyO9fJZpsVhLU9507g='
|
|
257
|
+
request_md5.env['CONTENT_MD5'] = 'kZXQvrKoieG+Be1rsZVINw=='
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
it 'is false' do
|
|
261
|
+
expect(driven_request.content_hash_mismatch?).to be false
|
|
182
262
|
end
|
|
183
263
|
|
|
184
|
-
it
|
|
185
|
-
expect(
|
|
264
|
+
it 'is false with md5' do
|
|
265
|
+
expect(driven_request_md5.content_hash_mismatch?).to be false
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
it 'is false with sha2 and md5 compatibility on' do
|
|
269
|
+
expect(driven_request_sha2_with_md5.content_hash_mismatch?).to be false
|
|
186
270
|
end
|
|
187
271
|
end
|
|
188
272
|
|
|
189
273
|
context "when calculated doesn't match sent" do
|
|
190
274
|
before do
|
|
191
|
-
request.env[
|
|
275
|
+
request.env['X-AUTHORIZATION-CONTENT-SHA256'] = '3'
|
|
276
|
+
request_md5.env['CONTENT_MD5'] = '3'
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
it 'is true' do
|
|
280
|
+
expect(driven_request.content_hash_mismatch?).to be true
|
|
192
281
|
end
|
|
193
282
|
|
|
194
|
-
it
|
|
195
|
-
expect(driven_request.
|
|
283
|
+
it 'is true with md5' do
|
|
284
|
+
expect(driven_request.content_hash_mismatch?).to be true
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
it 'is true with sha2 and md5 compatibility on' do
|
|
288
|
+
expect(driven_request_sha2_with_md5.content_hash_mismatch?).to be true
|
|
196
289
|
end
|
|
197
290
|
end
|
|
198
291
|
end
|
|
199
292
|
|
|
200
|
-
context
|
|
293
|
+
context 'when putting' do
|
|
201
294
|
before do
|
|
202
295
|
request.env['REQUEST_METHOD'] = 'PUT'
|
|
296
|
+
request_md5.env['REQUEST_METHOD'] = 'PUT'
|
|
203
297
|
end
|
|
204
298
|
|
|
205
|
-
context
|
|
299
|
+
context 'when calculated matches sent' do
|
|
206
300
|
before do
|
|
207
|
-
request.env[
|
|
301
|
+
request.env['X-AUTHORIZATION-CONTENT-SHA256'] = 'JsYKYdAdtYNspw/v1EpqAWYgQTyO9fJZpsVhLU9507g='
|
|
302
|
+
request_md5.env['CONTENT_MD5'] = 'kZXQvrKoieG+Be1rsZVINw=='
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
it 'is false' do
|
|
306
|
+
expect(driven_request.content_hash_mismatch?).to be false
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
it 'is false with md5' do
|
|
310
|
+
expect(driven_request_md5.content_hash_mismatch?).to be false
|
|
208
311
|
end
|
|
209
312
|
|
|
210
|
-
it
|
|
211
|
-
expect(
|
|
313
|
+
it 'is false with sha2 and md5 compatibility on' do
|
|
314
|
+
expect(driven_request_sha2_with_md5.content_hash_mismatch?).to be false
|
|
212
315
|
end
|
|
213
316
|
end
|
|
214
317
|
|
|
215
318
|
context "when calculated doesn't match sent" do
|
|
216
319
|
before do
|
|
217
|
-
request.env[
|
|
320
|
+
request.env['X-AUTHORIZATION-CONTENT-SHA256'] = '3'
|
|
321
|
+
request_md5.env['CONTENT_MD5'] = '3'
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
it 'is true' do
|
|
325
|
+
expect(driven_request.content_hash_mismatch?).to be true
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
it 'is true with md5' do
|
|
329
|
+
expect(driven_request_md5.content_hash_mismatch?).to be true
|
|
218
330
|
end
|
|
219
331
|
|
|
220
|
-
it
|
|
221
|
-
expect(
|
|
332
|
+
it 'is true with sha2 and md5 compatibility on' do
|
|
333
|
+
expect(driven_request_sha2_with_md5.content_hash_mismatch?).to be true
|
|
222
334
|
end
|
|
223
335
|
end
|
|
224
336
|
end
|
|
225
337
|
|
|
226
|
-
context
|
|
338
|
+
context 'when deleting' do
|
|
227
339
|
before do
|
|
228
340
|
request.env['REQUEST_METHOD'] = 'DELETE'
|
|
341
|
+
request_md5.env['REQUEST_METHOD'] = 'DELETE'
|
|
229
342
|
end
|
|
230
343
|
|
|
231
|
-
it
|
|
232
|
-
expect(driven_request.
|
|
344
|
+
it 'is false' do
|
|
345
|
+
expect(driven_request.content_hash_mismatch?).to be false
|
|
233
346
|
end
|
|
347
|
+
|
|
348
|
+
it 'is false with md5' do
|
|
349
|
+
expect(driven_request_md5.content_hash_mismatch?).to be false
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
it 'is false with sha2 and md5 compatibility on' do
|
|
353
|
+
expect(driven_request_sha2_with_md5.content_hash_mismatch?).to be false
|
|
354
|
+
end
|
|
355
|
+
end
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
describe 'fetch_headers' do
|
|
359
|
+
it 'returns request headers' do
|
|
360
|
+
expect(driven_request.fetch_headers).to include('CONTENT_TYPE' => 'text/plain')
|
|
234
361
|
end
|
|
235
362
|
end
|
|
236
363
|
end
|
|
@@ -1,97 +1,100 @@
|
|
|
1
1
|
require 'spec_helper'
|
|
2
2
|
|
|
3
3
|
describe ApiAuth::RequestDrivers::CurbRequest do
|
|
4
|
-
|
|
5
|
-
let(:timestamp){ Time.now.utc.httpdate }
|
|
4
|
+
let(:timestamp) { Time.now.utc.httpdate }
|
|
6
5
|
|
|
7
6
|
let(:request) do
|
|
8
7
|
headers = {
|
|
9
8
|
'Authorization' => 'APIAuth 1044:12345',
|
|
10
|
-
'Content-
|
|
11
|
-
'Content-Type'
|
|
12
|
-
'Date'
|
|
9
|
+
'X-Authorization-Content-SHA256' => '47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=',
|
|
10
|
+
'Content-Type' => 'text/plain',
|
|
11
|
+
'Date' => timestamp
|
|
13
12
|
}
|
|
14
|
-
Curl::Easy.new(
|
|
13
|
+
Curl::Easy.new('/resource.xml?foo=bar&bar=foo') do |curl|
|
|
15
14
|
curl.headers = headers
|
|
16
15
|
end
|
|
17
16
|
end
|
|
18
17
|
|
|
18
|
+
subject(:driven_request) { ApiAuth::RequestDrivers::CurbRequest.new(request) }
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
describe "getting headers correctly" do
|
|
23
|
-
it "gets the content_type" do
|
|
20
|
+
describe 'getting headers correctly' do
|
|
21
|
+
it 'gets the content_type' do
|
|
24
22
|
expect(driven_request.content_type).to eq('text/plain')
|
|
25
23
|
end
|
|
26
24
|
|
|
27
|
-
it
|
|
28
|
-
expect(driven_request.
|
|
25
|
+
it 'gets the content_hash' do
|
|
26
|
+
expect(driven_request.content_hash).to eq('47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=')
|
|
29
27
|
end
|
|
30
28
|
|
|
31
|
-
it
|
|
29
|
+
it 'gets the request_uri' do
|
|
32
30
|
expect(driven_request.request_uri).to eq('/resource.xml?foo=bar&bar=foo')
|
|
33
31
|
end
|
|
34
32
|
|
|
35
|
-
it
|
|
33
|
+
it 'gets the timestamp' do
|
|
36
34
|
expect(driven_request.timestamp).to eq(timestamp)
|
|
37
35
|
end
|
|
38
36
|
|
|
39
|
-
it
|
|
37
|
+
it 'gets the authorization_header' do
|
|
40
38
|
expect(driven_request.authorization_header).to eq('APIAuth 1044:12345')
|
|
41
39
|
end
|
|
42
40
|
|
|
43
|
-
describe
|
|
44
|
-
it
|
|
41
|
+
describe 'http_method' do
|
|
42
|
+
it 'is always nil' do
|
|
45
43
|
expect(driven_request.http_method).to be_nil
|
|
46
44
|
end
|
|
47
45
|
end
|
|
48
46
|
end
|
|
49
47
|
|
|
50
|
-
describe
|
|
48
|
+
describe 'setting headers correctly' do
|
|
51
49
|
let(:request) do
|
|
52
50
|
headers = {
|
|
53
|
-
'Content-Type'
|
|
51
|
+
'Content-Type' => 'text/plain'
|
|
54
52
|
}
|
|
55
|
-
Curl::Easy.new(
|
|
53
|
+
Curl::Easy.new('/resource.xml?foo=bar&bar=foo') do |curl|
|
|
56
54
|
curl.headers = headers
|
|
57
55
|
end
|
|
58
56
|
end
|
|
59
57
|
|
|
60
|
-
describe
|
|
61
|
-
it
|
|
62
|
-
expect(driven_request.
|
|
63
|
-
expect(request.headers['Content-
|
|
58
|
+
describe '#populate_content_hash' do
|
|
59
|
+
it 'is a no-op' do
|
|
60
|
+
expect(driven_request.populate_content_hash).to be_nil
|
|
61
|
+
expect(request.headers['X-Authorization-Content-SHA256']).to be_nil
|
|
64
62
|
end
|
|
65
|
-
|
|
66
63
|
end
|
|
67
64
|
|
|
68
|
-
describe
|
|
65
|
+
describe '#set_date' do
|
|
69
66
|
before do
|
|
70
67
|
allow(Time).to receive_message_chain(:now, :utc, :httpdate).and_return(timestamp)
|
|
71
68
|
end
|
|
72
69
|
|
|
73
|
-
it
|
|
70
|
+
it 'sets the date header of the request' do
|
|
74
71
|
driven_request.set_date
|
|
75
72
|
expect(request.headers['DATE']).to eq(timestamp)
|
|
76
73
|
end
|
|
77
74
|
|
|
78
|
-
it
|
|
75
|
+
it 'refreshes the cached headers' do
|
|
79
76
|
driven_request.set_date
|
|
80
77
|
expect(driven_request.timestamp).to eq(timestamp)
|
|
81
78
|
end
|
|
82
79
|
end
|
|
83
80
|
|
|
84
|
-
describe
|
|
85
|
-
it
|
|
81
|
+
describe '#set_auth_header' do
|
|
82
|
+
it 'sets the auth header' do
|
|
86
83
|
driven_request.set_auth_header('APIAuth 1044:54321')
|
|
87
84
|
expect(request.headers['Authorization']).to eq('APIAuth 1044:54321')
|
|
88
85
|
end
|
|
89
86
|
end
|
|
90
87
|
end
|
|
91
88
|
|
|
92
|
-
describe
|
|
93
|
-
it
|
|
94
|
-
expect(driven_request.
|
|
89
|
+
describe 'content_hash_mismatch?' do
|
|
90
|
+
it 'is always false' do
|
|
91
|
+
expect(driven_request.content_hash_mismatch?).to be false
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
describe 'fetch_headers' do
|
|
96
|
+
it 'returns request headers' do
|
|
97
|
+
expect(driven_request.fetch_headers).to include('CONTENT-TYPE' => 'text/plain')
|
|
95
98
|
end
|
|
96
99
|
end
|
|
97
100
|
end
|