bixby-auth 0.1.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 +7 -0
- data/.document +5 -0
- data/Gemfile +28 -0
- data/Gemfile.lock +245 -0
- data/LICENSE.txt +20 -0
- data/README.md +19 -0
- data/Rakefile +52 -0
- data/VERSION +1 -0
- data/bixby-auth.gemspec +129 -0
- data/lib/api-auth.rb +2 -0
- data/lib/api_auth/base.rb +105 -0
- data/lib/api_auth/errors.rb +12 -0
- data/lib/api_auth/headers.rb +82 -0
- data/lib/api_auth/helpers.rb +39 -0
- data/lib/api_auth/railtie.rb +129 -0
- data/lib/api_auth/request_drivers/action_controller.rb +84 -0
- data/lib/api_auth/request_drivers/action_dispatch.rb +17 -0
- data/lib/api_auth/request_drivers/bixby_request.rb +65 -0
- data/lib/api_auth/request_drivers/curb.rb +72 -0
- data/lib/api_auth/request_drivers/httpi.rb +82 -0
- data/lib/api_auth/request_drivers/net_http.rb +98 -0
- data/lib/api_auth/request_drivers/rack.rb +88 -0
- data/lib/api_auth/request_drivers/rest_client.rb +98 -0
- data/lib/api_auth/request_drivers.rb +21 -0
- data/lib/api_auth.rb +10 -0
- data/lib/bixby-auth.rb +3 -0
- data/spec/api_auth_spec.rb +660 -0
- data/spec/application_helper.rb +2 -0
- data/spec/fixtures/upload.png +0 -0
- data/spec/headers_spec.rb +356 -0
- data/spec/helpers_spec.rb +14 -0
- data/spec/railtie_spec.rb +134 -0
- data/spec/spec_helper.rb +27 -0
- data/spec/test_helper.rb +2 -0
- data/test/helper.rb +35 -0
- data/test/test_bixby-auth.rb +7 -0
- metadata +346 -0
@@ -0,0 +1,356 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe "ApiAuth::Headers" do
|
4
|
+
|
5
|
+
CANONICAL_STRING = "text/plain,e59ff97941044f85df5297e1c302d260,/resource.xml?foo=bar&bar=foo,Mon, 23 Jan 1984 03:29:56 GMT"
|
6
|
+
|
7
|
+
describe "with Net::HTTP::Put::Multipart" do
|
8
|
+
|
9
|
+
before(:each) do
|
10
|
+
request = Net::HTTP::Put::Multipart.new("/resource.xml?foo=bar&bar=foo",
|
11
|
+
'file' => UploadIO.new(File.new('spec/fixtures/upload.png'), 'image/png', 'upload.png'))
|
12
|
+
ApiAuth.sign!(request, "some access id", "some secret key")
|
13
|
+
@headers = ApiAuth::Headers.new(request)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should set the content-type" do
|
17
|
+
@headers.canonical_string.split(',')[0].should match 'multipart/form-data; boundary='
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should generate the proper content-md5" do
|
21
|
+
@headers.canonical_string.split(',')[1].should match 'zap0d6zuh6wRBSrsvO2bcw=='
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "with Net::HTTP" do
|
27
|
+
|
28
|
+
before(:each) do
|
29
|
+
@request = Net::HTTP::Put.new("/resource.xml?foo=bar&bar=foo",
|
30
|
+
'content-type' => 'text/plain',
|
31
|
+
'content-md5' => 'e59ff97941044f85df5297e1c302d260',
|
32
|
+
'date' => "Mon, 23 Jan 1984 03:29:56 GMT")
|
33
|
+
@headers = ApiAuth::Headers.new(@request)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should generate the proper canonical string" do
|
37
|
+
@headers.canonical_string.should == CANONICAL_STRING
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should set the authorization header" do
|
41
|
+
@headers.sign_header("alpha")
|
42
|
+
@headers.authorization_header.should == "alpha"
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should set the DATE header if one is not already present" do
|
46
|
+
@request = Net::HTTP::Put.new("/resource.xml?foo=bar&bar=foo",
|
47
|
+
'content-type' => 'text/plain',
|
48
|
+
'content-md5' => 'e59ff97941044f85df5297e1c302d260')
|
49
|
+
ApiAuth.sign!(@request, "some access id", "some secret key")
|
50
|
+
@request['DATE'].should_not be_nil
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should not set the DATE header just by asking for the canonical_string" do
|
54
|
+
request = Net::HTTP::Put.new("/resource.xml?foo=bar&bar=foo",
|
55
|
+
'content-type' => 'text/plain',
|
56
|
+
'content-md5' => 'e59ff97941044f85df5297e1c302d260')
|
57
|
+
headers = ApiAuth::Headers.new(request)
|
58
|
+
headers.canonical_string
|
59
|
+
request['DATE'].should be_nil
|
60
|
+
end
|
61
|
+
|
62
|
+
context "md5_mismatch?" do
|
63
|
+
it "is false if no md5 header is present" do
|
64
|
+
request = Net::HTTP::Put.new("/resource.xml?foo=bar&bar=foo",
|
65
|
+
'content-type' => 'text/plain')
|
66
|
+
headers = ApiAuth::Headers.new(request)
|
67
|
+
headers.md5_mismatch?.should be_false
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe "with RestClient" do
|
73
|
+
|
74
|
+
before(:each) do
|
75
|
+
headers = { 'Content-MD5' => "e59ff97941044f85df5297e1c302d260",
|
76
|
+
'Content-Type' => "text/plain",
|
77
|
+
'Date' => "Mon, 23 Jan 1984 03:29:56 GMT" }
|
78
|
+
@request = RestClient::Request.new(:url => "/resource.xml?foo=bar&bar=foo",
|
79
|
+
:headers => headers,
|
80
|
+
:method => :put)
|
81
|
+
@headers = ApiAuth::Headers.new(@request)
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should generate the proper canonical string" do
|
85
|
+
@headers.canonical_string.should == CANONICAL_STRING
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should set the authorization header" do
|
89
|
+
@headers.sign_header("alpha")
|
90
|
+
@headers.authorization_header.should == "alpha"
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should set the DATE header if one is not already present" do
|
94
|
+
headers = { 'Content-MD5' => "e59ff97941044f85df5297e1c302d260",
|
95
|
+
'Content-Type' => "text/plain" }
|
96
|
+
@request = RestClient::Request.new(:url => "/resource.xml?foo=bar&bar=foo",
|
97
|
+
:headers => headers,
|
98
|
+
:method => :put)
|
99
|
+
ApiAuth.sign!(@request, "some access id", "some secret key")
|
100
|
+
@request.headers['DATE'].should_not be_nil
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should not set the DATE header just by asking for the canonical_string" do
|
104
|
+
headers = { 'Content-MD5' => "e59ff97941044f85df5297e1c302d260",
|
105
|
+
'Content-Type' => "text/plain" }
|
106
|
+
request = RestClient::Request.new(:url => "/resource.xml?foo=bar&bar=foo",
|
107
|
+
:headers => headers,
|
108
|
+
:method => :put)
|
109
|
+
headers = ApiAuth::Headers.new(request)
|
110
|
+
headers.canonical_string
|
111
|
+
request.headers['DATE'].should be_nil
|
112
|
+
end
|
113
|
+
|
114
|
+
it "doesn't mess up symbol based headers" do
|
115
|
+
headers = { 'Content-MD5' => "e59ff97941044f85df5297e1c302d260",
|
116
|
+
:content_type => "text/plain",
|
117
|
+
'Date' => "Mon, 23 Jan 1984 03:29:56 GMT" }
|
118
|
+
@request = RestClient::Request.new(:url => "/resource.xml?foo=bar&bar=foo",
|
119
|
+
:headers => headers,
|
120
|
+
:method => :put)
|
121
|
+
@headers = ApiAuth::Headers.new(@request)
|
122
|
+
ApiAuth.sign!(@request, "some access id", "some secret key")
|
123
|
+
@request.processed_headers.should have_key('Content-Type')
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
describe "with Curb" do
|
128
|
+
|
129
|
+
before(:each) do
|
130
|
+
headers = { 'Content-MD5' => "e59ff97941044f85df5297e1c302d260",
|
131
|
+
'Content-Type' => "text/plain",
|
132
|
+
'Date' => "Mon, 23 Jan 1984 03:29:56 GMT" }
|
133
|
+
@request = Curl::Easy.new("/resource.xml?foo=bar&bar=foo") do |curl|
|
134
|
+
curl.headers = headers
|
135
|
+
end
|
136
|
+
@headers = ApiAuth::Headers.new(@request)
|
137
|
+
end
|
138
|
+
|
139
|
+
it "should generate the proper canonical string" do
|
140
|
+
@headers.canonical_string.should == CANONICAL_STRING
|
141
|
+
end
|
142
|
+
|
143
|
+
it "should set the authorization header" do
|
144
|
+
@headers.sign_header("alpha")
|
145
|
+
@headers.authorization_header.should == "alpha"
|
146
|
+
end
|
147
|
+
|
148
|
+
it "should set the DATE header if one is not already present" do
|
149
|
+
headers = { 'Content-MD5' => "e59ff97941044f85df5297e1c302d260",
|
150
|
+
'Content-Type' => "text/plain" }
|
151
|
+
@request = Curl::Easy.new("/resource.xml?foo=bar&bar=foo") do |curl|
|
152
|
+
curl.headers = headers
|
153
|
+
end
|
154
|
+
ApiAuth.sign!(@request, "some access id", "some secret key")
|
155
|
+
@request.headers['DATE'].should_not be_nil
|
156
|
+
end
|
157
|
+
|
158
|
+
it "should not set the DATE header just by asking for the canonical_string" do
|
159
|
+
headers = { 'Content-MD5' => "e59ff97941044f85df5297e1c302d260",
|
160
|
+
'Content-Type' => "text/plain" }
|
161
|
+
request = Curl::Easy.new("/resource.xml?foo=bar&bar=foo") do |curl|
|
162
|
+
curl.headers = headers
|
163
|
+
end
|
164
|
+
headers = ApiAuth::Headers.new(request)
|
165
|
+
headers.canonical_string
|
166
|
+
request.headers['DATE'].should be_nil
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
describe "with ActionController" do
|
171
|
+
|
172
|
+
let(:request_klass){ ActionDispatch::Request rescue ActionController::Request }
|
173
|
+
|
174
|
+
before(:each) do
|
175
|
+
@request = request_klass.new(
|
176
|
+
'PATH_INFO' => '/resource.xml',
|
177
|
+
'QUERY_STRING' => 'foo=bar&bar=foo',
|
178
|
+
'REQUEST_METHOD' => 'PUT',
|
179
|
+
'CONTENT_MD5' => 'e59ff97941044f85df5297e1c302d260',
|
180
|
+
'CONTENT_TYPE' => 'text/plain',
|
181
|
+
'HTTP_DATE' => 'Mon, 23 Jan 1984 03:29:56 GMT')
|
182
|
+
@headers = ApiAuth::Headers.new(@request)
|
183
|
+
end
|
184
|
+
|
185
|
+
it "should generate the proper canonical string" do
|
186
|
+
@headers.canonical_string.should == CANONICAL_STRING
|
187
|
+
end
|
188
|
+
|
189
|
+
it "should set the authorization header" do
|
190
|
+
@headers.sign_header("alpha")
|
191
|
+
@headers.authorization_header.should == "alpha"
|
192
|
+
end
|
193
|
+
|
194
|
+
it "should set the DATE header if one is not already present" do
|
195
|
+
@request = request_klass.new(
|
196
|
+
'PATH_INFO' => '/resource.xml',
|
197
|
+
'QUERY_STRING' => 'foo=bar&bar=foo',
|
198
|
+
'REQUEST_METHOD' => 'PUT',
|
199
|
+
'CONTENT_MD5' => 'e59ff97941044f85df5297e1c302d260',
|
200
|
+
'CONTENT_TYPE' => 'text/plain')
|
201
|
+
ApiAuth.sign!(@request, "some access id", "some secret key")
|
202
|
+
@request.headers['DATE'].should_not be_nil
|
203
|
+
end
|
204
|
+
|
205
|
+
it "should not set the DATE header just by asking for the canonical_string" do
|
206
|
+
request = request_klass.new(
|
207
|
+
'PATH_INFO' => '/resource.xml',
|
208
|
+
'QUERY_STRING' => 'foo=bar&bar=foo',
|
209
|
+
'REQUEST_METHOD' => 'PUT',
|
210
|
+
'CONTENT_MD5' => 'e59ff97941044f85df5297e1c302d260',
|
211
|
+
'CONTENT_TYPE' => 'text/plain')
|
212
|
+
headers = ApiAuth::Headers.new(request)
|
213
|
+
headers.canonical_string
|
214
|
+
request.headers['DATE'].should be_nil
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
describe "with Rack::Request" do
|
219
|
+
|
220
|
+
before(:each) do
|
221
|
+
headers = { 'Content-MD5' => "e59ff97941044f85df5297e1c302d260",
|
222
|
+
'Content-Type' => "text/plain",
|
223
|
+
'Date' => "Mon, 23 Jan 1984 03:29:56 GMT"
|
224
|
+
}
|
225
|
+
@request = Rack::Request.new(Rack::MockRequest.env_for("/resource.xml?foo=bar&bar=foo", :method => :put).merge!(headers))
|
226
|
+
@headers = ApiAuth::Headers.new(@request)
|
227
|
+
end
|
228
|
+
|
229
|
+
it "should generate the proper canonical string" do
|
230
|
+
@headers.canonical_string.should == CANONICAL_STRING
|
231
|
+
end
|
232
|
+
|
233
|
+
it "should set the authorization header" do
|
234
|
+
@headers.sign_header("alpha")
|
235
|
+
@headers.authorization_header.should == "alpha"
|
236
|
+
end
|
237
|
+
|
238
|
+
it "should set the DATE header if one is not already present" do
|
239
|
+
headers = { 'Content-MD5' => "e59ff97941044f85df5297e1c302d260",
|
240
|
+
'Content-Type' => "text/plain" }
|
241
|
+
@request = Rack::Request.new(Rack::MockRequest.env_for("/resource.xml?foo=bar&bar=foo", :method => :put).merge!(headers))
|
242
|
+
ApiAuth.sign!(@request, "some access id", "some secret key")
|
243
|
+
@request.env['DATE'].should_not be_nil
|
244
|
+
end
|
245
|
+
|
246
|
+
it "should not set the DATE header just by asking for the canonical_string" do
|
247
|
+
headers = { 'Content-MD5' => "e59ff97941044f85df5297e1c302d260",
|
248
|
+
'Content-Type' => "text/plain" }
|
249
|
+
request = Rack::Request.new(Rack::MockRequest.env_for("/resource.xml?foo=bar&bar=foo", :method => :put).merge!(headers))
|
250
|
+
headers = ApiAuth::Headers.new(request)
|
251
|
+
headers.canonical_string
|
252
|
+
request.env['DATE'].should be_nil
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
describe "with HTTPI" do
|
257
|
+
before(:each) do
|
258
|
+
@request = HTTPI::Request.new("http://localhost/resource.xml?foo=bar&bar=foo")
|
259
|
+
@request.headers.merge!({
|
260
|
+
'content-type' => 'text/plain',
|
261
|
+
'content-md5' => 'e59ff97941044f85df5297e1c302d260',
|
262
|
+
'date' => "Mon, 23 Jan 1984 03:29:56 GMT"
|
263
|
+
})
|
264
|
+
@headers = ApiAuth::Headers.new(@request)
|
265
|
+
end
|
266
|
+
|
267
|
+
it "should generate the proper canonical string" do
|
268
|
+
@headers.canonical_string.should == CANONICAL_STRING
|
269
|
+
end
|
270
|
+
|
271
|
+
it "should set the authorization header" do
|
272
|
+
@headers.sign_header("alpha")
|
273
|
+
@headers.authorization_header.should == "alpha"
|
274
|
+
end
|
275
|
+
|
276
|
+
it "should set the DATE header if one is not already present" do
|
277
|
+
@request = Net::HTTP::Put.new("/resource.xml?foo=bar&bar=foo",
|
278
|
+
'content-type' => 'text/plain',
|
279
|
+
'content-md5' => 'e59ff97941044f85df5297e1c302d260')
|
280
|
+
ApiAuth.sign!(@request, "some access id", "some secret key")
|
281
|
+
@request['DATE'].should_not be_nil
|
282
|
+
end
|
283
|
+
|
284
|
+
it "should not set the DATE header just by asking for the canonical_string" do
|
285
|
+
request = Net::HTTP::Put.new("/resource.xml?foo=bar&bar=foo",
|
286
|
+
'content-type' => 'text/plain',
|
287
|
+
'content-md5' => 'e59ff97941044f85df5297e1c302d260')
|
288
|
+
headers = ApiAuth::Headers.new(request)
|
289
|
+
headers.canonical_string
|
290
|
+
request['DATE'].should be_nil
|
291
|
+
end
|
292
|
+
|
293
|
+
context "md5_mismatch?" do
|
294
|
+
it "is false if no md5 header is present" do
|
295
|
+
request = Net::HTTP::Put.new("/resource.xml?foo=bar&bar=foo",
|
296
|
+
'content-type' => 'text/plain')
|
297
|
+
headers = ApiAuth::Headers.new(request)
|
298
|
+
headers.md5_mismatch?.should be_false
|
299
|
+
end
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
describe "with Bixby::SignedJsonRequest" do
|
304
|
+
|
305
|
+
before(:each) do
|
306
|
+
@json_req = Bixby::JsonRequest.new("foo", "bar")
|
307
|
+
@request = Bixby::SignedJsonRequest.new(@json_req)
|
308
|
+
@request.headers.merge!({
|
309
|
+
'Content-Type' => 'text/plain',
|
310
|
+
'Content-MD5' => 'e59ff97941044f85df5297e1c302d260',
|
311
|
+
'Date' => "Mon, 23 Jan 1984 03:29:56 GMT"
|
312
|
+
})
|
313
|
+
@headers = ApiAuth::Headers.new(@request)
|
314
|
+
end
|
315
|
+
|
316
|
+
it "should generate the proper canonical string" do
|
317
|
+
@headers.canonical_string.should == CANONICAL_STRING.gsub("/resource.xml?foo=bar&bar=foo", "/api")
|
318
|
+
end
|
319
|
+
|
320
|
+
it "should set the authorization header" do
|
321
|
+
@headers.sign_header("alpha")
|
322
|
+
@headers.authorization_header.should == "alpha"
|
323
|
+
end
|
324
|
+
|
325
|
+
it "should set the DATE header if one is not already present" do
|
326
|
+
@request = Bixby::SignedJsonRequest.new(@json_req)
|
327
|
+
@request.headers.merge!({
|
328
|
+
'Content-Type' => 'text/plain',
|
329
|
+
'Content-MD5' => 'e59ff97941044f85df5297e1c302d260'
|
330
|
+
})
|
331
|
+
ApiAuth.sign!(@request, "some access id", "some secret key")
|
332
|
+
@request.headers['Date'].should_not be_nil
|
333
|
+
end
|
334
|
+
|
335
|
+
it "should not set the DATE header just by asking for the canonical_string" do
|
336
|
+
request = Bixby::SignedJsonRequest.new(@json_req)
|
337
|
+
@request.headers.merge!({
|
338
|
+
'Content-Type' => 'text/plain',
|
339
|
+
'Content-MD5' => 'e59ff97941044f85df5297e1c302d260'
|
340
|
+
})
|
341
|
+
headers = ApiAuth::Headers.new(request)
|
342
|
+
headers.canonical_string
|
343
|
+
request.headers['date'].should be_nil
|
344
|
+
end
|
345
|
+
|
346
|
+
context "md5_mismatch?" do
|
347
|
+
it "is false if no md5 header is present" do
|
348
|
+
request = Bixby::SignedJsonRequest.new(@json_req)
|
349
|
+
request.headers.merge!({'Content-Type' => 'text/plain'})
|
350
|
+
headers = ApiAuth::Headers.new(request)
|
351
|
+
headers.md5_mismatch?.should be_false
|
352
|
+
end
|
353
|
+
end
|
354
|
+
end
|
355
|
+
|
356
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe "ApiAuth::Helpers" do
|
4
|
+
|
5
|
+
it "should strip the new line character on a Base64 encoding" do
|
6
|
+
ApiAuth.b64_encode("some string").should_not match(/\n/)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should properly upcase a hash's keys" do
|
10
|
+
hsh = { "JoE" => "rOOLz" }
|
11
|
+
ApiAuth.capitalize_keys(hsh)["JOE"].should == "rOOLz"
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe "Rails integration" do
|
4
|
+
|
5
|
+
API_KEY_STORE = { "1044" => "l16imAXie1sRMcJODpOG7UwC1VyoqvO13jejkfpKWX4Z09W8DC9IrU23DvCwMry7pgSFW6c5S1GIfV0OY6F/vUA==" }
|
6
|
+
|
7
|
+
describe "Rails controller integration" do
|
8
|
+
|
9
|
+
class ApplicationController < ActionController::Base
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def require_api_auth
|
14
|
+
if (access_id = get_api_access_id_from_request)
|
15
|
+
begin
|
16
|
+
if api_authenticated?(API_KEY_STORE[access_id]) then
|
17
|
+
return true
|
18
|
+
end
|
19
|
+
rescue ApiAuth::RequestTooOld
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
respond_to do |format|
|
24
|
+
format.xml { render :xml => "You are unauthorized to perform this action.", :status => 401 }
|
25
|
+
format.json { render :json => "You are unauthorized to perform this action.", :status => 401 }
|
26
|
+
format.html { render :text => "You are unauthorized to perform this action", :status => 401 }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
class TestController < ApplicationController
|
33
|
+
before_filter :require_api_auth, :only => [:index]
|
34
|
+
|
35
|
+
if defined?(ActionDispatch)
|
36
|
+
def self._routes
|
37
|
+
ActionDispatch::Routing::RouteSet.new
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def index
|
42
|
+
render :text => "OK"
|
43
|
+
end
|
44
|
+
|
45
|
+
def public
|
46
|
+
render :text => "OK"
|
47
|
+
end
|
48
|
+
|
49
|
+
def rescue_action(e); raise(e); end
|
50
|
+
end
|
51
|
+
|
52
|
+
unless defined?(ActionDispatch)
|
53
|
+
ActionController::Routing::Routes.draw {|map| map.resources :test }
|
54
|
+
end
|
55
|
+
|
56
|
+
def generated_response(request, action = :index)
|
57
|
+
if defined?(ActionDispatch)
|
58
|
+
TestController.action(action).call(request.env).last
|
59
|
+
else
|
60
|
+
request.action = action.to_s
|
61
|
+
request.path = "/#{action.to_s}"
|
62
|
+
TestController.new.process(request, ActionController::TestResponse.new)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should permit a request with properly signed headers" do
|
67
|
+
request = ActionController::TestRequest.new
|
68
|
+
request.env['DATE'] = Time.now.utc.httpdate
|
69
|
+
ApiAuth.sign!(request, "1044", API_KEY_STORE["1044"])
|
70
|
+
response = generated_response(request, :index)
|
71
|
+
response.code.should == "200"
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should forbid a request with properly signed headers but timestamp > 15 minutes" do
|
75
|
+
request = ActionController::TestRequest.new
|
76
|
+
request.env['DATE'] = "Mon, 23 Jan 1984 03:29:56 GMT"
|
77
|
+
ApiAuth.sign!(request, "1044", API_KEY_STORE["1044"])
|
78
|
+
response = generated_response(request, :index)
|
79
|
+
response.code.should == "401"
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should insert a DATE header in the request when one hasn't been specified" do
|
83
|
+
request = ActionController::TestRequest.new
|
84
|
+
ApiAuth.sign!(request, "1044", API_KEY_STORE["1044"])
|
85
|
+
request.headers['DATE'].should_not be_nil
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should forbid an unsigned request to a protected controller action" do
|
89
|
+
request = ActionController::TestRequest.new
|
90
|
+
response = generated_response(request, :index)
|
91
|
+
response.code.should == "401"
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should forbid a request with a bogus signature" do
|
95
|
+
request = ActionController::TestRequest.new
|
96
|
+
request.env['Authorization'] = "APIAuth bogus:bogus"
|
97
|
+
response = generated_response(request, :index)
|
98
|
+
response.code.should == "401"
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should allow non-protected controller actions to function as before" do
|
102
|
+
request = ActionController::TestRequest.new
|
103
|
+
response = generated_response(request, :public)
|
104
|
+
response.code.should == "200"
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
describe "Rails ActiveResource integration" do
|
110
|
+
|
111
|
+
class TestResource < ActiveResource::Base
|
112
|
+
with_api_auth "1044", API_KEY_STORE["1044"]
|
113
|
+
self.site = "http://localhost/"
|
114
|
+
self.format = :xml
|
115
|
+
end
|
116
|
+
|
117
|
+
it "should send signed requests automagically" do
|
118
|
+
timestamp = Time.parse("Mon, 23 Jan 1984 03:29:56 GMT")
|
119
|
+
Time.should_receive(:now).at_least(1).times.and_return(timestamp)
|
120
|
+
ActiveResource::HttpMock.respond_to do |mock|
|
121
|
+
mock.get "/test_resources/1.xml",
|
122
|
+
{
|
123
|
+
'Authorization' => 'APIAuth 1044:IbTx7VzSOGU55HNbV4y2jZDnVis=',
|
124
|
+
'Accept' => 'application/xml',
|
125
|
+
'DATE' => "Mon, 23 Jan 1984 03:29:56 GMT"
|
126
|
+
},
|
127
|
+
{ :id => "1" }.to_xml(:root => 'test_resource')
|
128
|
+
end
|
129
|
+
TestResource.find(1)
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
3
|
+
require 'rspec'
|
4
|
+
require 'api_auth'
|
5
|
+
require 'amatch'
|
6
|
+
require 'rest_client'
|
7
|
+
require 'curb'
|
8
|
+
require 'httpi'
|
9
|
+
require 'net/http/post/multipart'
|
10
|
+
|
11
|
+
require 'active_support'
|
12
|
+
require 'active_support/test_case'
|
13
|
+
require 'action_controller'
|
14
|
+
require 'action_controller/test_case'
|
15
|
+
require 'active_resource'
|
16
|
+
require 'active_resource/http_mock'
|
17
|
+
|
18
|
+
require 'bixby-auth'
|
19
|
+
require 'bixby-common'
|
20
|
+
|
21
|
+
# Requires supporting files with custom matchers and macros, etc,
|
22
|
+
# in ./support/ and its subdirectories.
|
23
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
24
|
+
|
25
|
+
RSpec.configure do |config|
|
26
|
+
|
27
|
+
end
|
data/spec/test_helper.rb
ADDED
data/test/helper.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
|
3
|
+
module SimpleCov::Configuration
|
4
|
+
def clean_filters
|
5
|
+
@filters = []
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
SimpleCov.configure do
|
10
|
+
clean_filters
|
11
|
+
load_adapter 'test_frameworks'
|
12
|
+
end
|
13
|
+
|
14
|
+
ENV["COVERAGE"] && SimpleCov.start do
|
15
|
+
add_filter "/.rvm/"
|
16
|
+
end
|
17
|
+
require 'rubygems'
|
18
|
+
require 'bundler'
|
19
|
+
begin
|
20
|
+
Bundler.setup(:default, :development)
|
21
|
+
rescue Bundler::BundlerError => e
|
22
|
+
$stderr.puts e.message
|
23
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
24
|
+
exit e.status_code
|
25
|
+
end
|
26
|
+
require 'minitest/unit'
|
27
|
+
|
28
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
29
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
30
|
+
require 'bixby-auth'
|
31
|
+
|
32
|
+
class MiniTest::Unit::TestCase
|
33
|
+
end
|
34
|
+
|
35
|
+
MiniTest::Unit.autorun
|