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