api-auth 1.5.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +10 -44
  3. data/.rubocop.yml +102 -0
  4. data/.travis.yml +1 -0
  5. data/Appraisals +8 -0
  6. data/CHANGELOG.md +8 -1
  7. data/Gemfile +3 -0
  8. data/README.md +33 -5
  9. data/VERSION +1 -1
  10. data/api_auth.gemspec +17 -17
  11. data/gemfiles/rails_23.gemfile +3 -0
  12. data/gemfiles/rails_30.gemfile +3 -0
  13. data/gemfiles/rails_31.gemfile +5 -0
  14. data/gemfiles/rails_32.gemfile +5 -0
  15. data/gemfiles/rails_4.gemfile +2 -0
  16. data/gemfiles/rails_41.gemfile +2 -0
  17. data/gemfiles/rails_42.gemfile +2 -0
  18. data/lib/api-auth.rb +1 -1
  19. data/lib/api_auth/base.rb +21 -25
  20. data/lib/api_auth/errors.rb +4 -3
  21. data/lib/api_auth/headers.rb +11 -27
  22. data/lib/api_auth/helpers.rb +2 -6
  23. data/lib/api_auth/railtie.rb +5 -50
  24. data/lib/api_auth/request_drivers/action_controller.rb +7 -13
  25. data/lib/api_auth/request_drivers/action_dispatch.rb +0 -6
  26. data/lib/api_auth/request_drivers/curb.rb +8 -14
  27. data/lib/api_auth/request_drivers/faraday.rb +11 -21
  28. data/lib/api_auth/request_drivers/httpi.rb +8 -14
  29. data/lib/api_auth/request_drivers/net_http.rb +8 -14
  30. data/lib/api_auth/request_drivers/rack.rb +10 -16
  31. data/lib/api_auth/request_drivers/rest_client.rb +9 -15
  32. data/spec/api_auth_spec.rb +90 -88
  33. data/spec/headers_spec.rb +69 -84
  34. data/spec/helpers_spec.rb +7 -9
  35. data/spec/railtie_spec.rb +42 -72
  36. data/spec/request_drivers/action_controller_spec.rb +53 -55
  37. data/spec/request_drivers/action_dispatch_spec.rb +52 -55
  38. data/spec/request_drivers/curb_spec.rb +25 -28
  39. data/spec/request_drivers/faraday_spec.rb +54 -56
  40. data/spec/request_drivers/httpi_spec.rb +42 -48
  41. data/spec/request_drivers/net_http_spec.rb +51 -53
  42. data/spec/request_drivers/rack_spec.rb +58 -60
  43. data/spec/request_drivers/rest_client_spec.rb +86 -89
  44. data/spec/spec_helper.rb +9 -9
  45. metadata +4 -11
  46. data/Gemfile.lock +0 -115
  47. data/gemfiles/rails_23.gemfile.lock +0 -70
  48. data/gemfiles/rails_30.gemfile.lock +0 -92
  49. data/gemfiles/rails_31.gemfile.lock +0 -98
  50. data/gemfiles/rails_32.gemfile.lock +0 -97
  51. data/gemfiles/rails_4.gemfile.lock +0 -94
  52. data/gemfiles/rails_41.gemfile.lock +0 -98
  53. data/gemfiles/rails_42.gemfile.lock +0 -115
@@ -1,9 +1,8 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
 
3
3
  describe ApiAuth::Headers do
4
-
5
4
  describe '#canonical_string' do
6
- context "uri edge cases" do
5
+ context 'uri edge cases' do
7
6
  let(:request) { RestClient::Request.new(:url => uri, :method => :get) }
8
7
  subject(:headers) { described_class.new(request) }
9
8
  let(:uri) { '' }
@@ -12,7 +11,7 @@ describe ApiAuth::Headers do
12
11
  let(:uri) { ''.freeze }
13
12
 
14
13
  it 'adds / to canonical string' do
15
- expect(subject.canonical_string).to eq(',,/,')
14
+ expect(subject.canonical_string).to eq('GET,,,/,')
16
15
  end
17
16
  end
18
17
 
@@ -20,7 +19,7 @@ describe ApiAuth::Headers do
20
19
  let(:uri) { 'http://google.com'.freeze }
21
20
 
22
21
  it 'return / as canonical string path' do
23
- expect(subject.canonical_string).to eq(',,/,')
22
+ expect(subject.canonical_string).to eq('GET,,,/,')
24
23
  end
25
24
 
26
25
  it 'does not change request url (by removing host)' do
@@ -32,7 +31,7 @@ describe ApiAuth::Headers do
32
31
  let(:uri) { 'http://google.com/'.freeze }
33
32
 
34
33
  it 'return / as canonical string path' do
35
- expect(subject.canonical_string).to eq(',,/,')
34
+ expect(subject.canonical_string).to eq('GET,,,/,')
36
35
  end
37
36
 
38
37
  it 'does not change request url (by removing host)' do
@@ -41,107 +40,93 @@ describe ApiAuth::Headers do
41
40
  end
42
41
  end
43
42
 
44
- context "string construction" do
45
- let(:request){ RestClient::Request.new(:url => "http://google.com", :method => :get) }
46
- subject(:headers) { described_class.new(request) }
47
- let(:driver){ headers.instance_variable_get("@request")}
48
-
49
- it "puts the canonical string together correctly" do
50
- allow(driver).to receive(:content_type).and_return "text/html"
51
- allow(driver).to receive(:content_md5).and_return "12345"
52
- allow(driver).to receive(:request_uri).and_return "/foo"
53
- allow(driver).to receive(:timestamp).and_return "Mon, 23 Jan 1984 03:29:56 GMT"
54
- expect(headers.canonical_string).to eq "text/html,12345,/foo,Mon, 23 Jan 1984 03:29:56 GMT"
55
- end
56
- end
57
- end
58
-
59
- describe "#canonical_string_with_http_method" do
60
- context "with a driver that supplies http_method" do
61
- let(:request){ RestClient::Request.new(:url => "http://google.com", :method => :get) }
62
- subject(:headers) { described_class.new(request) }
63
- let(:driver){ headers.instance_variable_get("@request")}
64
-
65
- before do
66
- allow(driver).to receive(:http_method).and_return "GET"
67
- allow(driver).to receive(:content_type).and_return "text/html"
68
- allow(driver).to receive(:content_md5).and_return "12345"
69
- allow(driver).to receive(:request_uri).and_return "/foo"
70
- allow(driver).to receive(:timestamp).and_return "Mon, 23 Jan 1984 03:29:56 GMT"
71
- end
43
+ context 'string construction' do
44
+ context 'with a driver that supplies http_method' do
45
+ let(:request) { RestClient::Request.new(:url => 'http://google.com', :method => :get) }
46
+ subject(:headers) { described_class.new(request) }
47
+ let(:driver) { headers.instance_variable_get('@request') }
48
+
49
+ before do
50
+ allow(driver).to receive(:http_method).and_return 'GET'
51
+ allow(driver).to receive(:content_type).and_return 'text/html'
52
+ allow(driver).to receive(:content_md5).and_return '12345'
53
+ allow(driver).to receive(:request_uri).and_return '/foo'
54
+ allow(driver).to receive(:timestamp).and_return 'Mon, 23 Jan 1984 03:29:56 GMT'
55
+ end
72
56
 
73
- context "when not passed an override" do
74
- it "constructs the canonical_string with the driver's http method" do
75
- expect(headers.canonical_string_with_http_method).to eq "GET,text/html,12345,/foo,Mon, 23 Jan 1984 03:29:56 GMT"
57
+ context 'when not passed an override' do
58
+ it "constructs the canonical_string with the driver's http method" do
59
+ expect(headers.canonical_string).to eq 'GET,text/html,12345,/foo,Mon, 23 Jan 1984 03:29:56 GMT'
60
+ end
76
61
  end
77
- end
78
62
 
79
- context "when passed an override" do
80
- it "constructs the canonical_string with the overridden http method" do
81
- expect(headers.canonical_string_with_http_method("put")).to eq "PUT,text/html,12345,/foo,Mon, 23 Jan 1984 03:29:56 GMT"
63
+ context 'when passed an override' do
64
+ it 'constructs the canonical_string with the overridden http method' do
65
+ expect(headers.canonical_string('put')).to eq 'PUT,text/html,12345,/foo,Mon, 23 Jan 1984 03:29:56 GMT'
66
+ end
82
67
  end
83
68
  end
84
- end
85
69
 
86
- context "when a driver that doesn't supply http_method" do
87
- let(:request) do
88
- Curl::Easy.new("/resource.xml?foo=bar&bar=foo") do |curl|
89
- curl.headers = { 'Content-Type' => "text/plain" }
70
+ context "when a driver that doesn't supply http_method" do
71
+ let(:request) do
72
+ Curl::Easy.new('/resource.xml?foo=bar&bar=foo') do |curl|
73
+ curl.headers = { 'Content-Type' => 'text/plain' }
74
+ end
75
+ end
76
+ subject(:headers) { described_class.new(request) }
77
+ let(:driver) { headers.instance_variable_get('@request') }
78
+
79
+ before do
80
+ allow(driver).to receive(:http_method).and_return nil
81
+ allow(driver).to receive(:content_type).and_return 'text/html'
82
+ allow(driver).to receive(:content_md5).and_return '12345'
83
+ allow(driver).to receive(:request_uri).and_return '/foo'
84
+ allow(driver).to receive(:timestamp).and_return 'Mon, 23 Jan 1984 03:29:56 GMT'
90
85
  end
91
- end
92
- subject(:headers) { described_class.new(request) }
93
- let(:driver){ headers.instance_variable_get("@request")}
94
-
95
- before do
96
- allow(driver).to receive(:http_method).and_return nil
97
- allow(driver).to receive(:content_type).and_return "text/html"
98
- allow(driver).to receive(:content_md5).and_return "12345"
99
- allow(driver).to receive(:request_uri).and_return "/foo"
100
- allow(driver).to receive(:timestamp).and_return "Mon, 23 Jan 1984 03:29:56 GMT"
101
- end
102
86
 
103
- context "when not passed an override" do
104
- it "raises an error" do
105
- expect{ headers.canonical_string_with_http_method }.to raise_error(ArgumentError)
87
+ context 'when not passed an override' do
88
+ it 'raises an error' do
89
+ expect { headers.canonical_string }.to raise_error(ArgumentError)
90
+ end
106
91
  end
107
- end
108
92
 
109
- context "when passed an override" do
110
- it "constructs the canonical_string with the overridden http method" do
111
- expect(headers.canonical_string_with_http_method("put")).to eq "PUT,text/html,12345,/foo,Mon, 23 Jan 1984 03:29:56 GMT"
93
+ context 'when passed an override' do
94
+ it 'constructs the canonical_string with the overridden http method' do
95
+ expect(headers.canonical_string('put')).to eq 'PUT,text/html,12345,/foo,Mon, 23 Jan 1984 03:29:56 GMT'
96
+ end
112
97
  end
113
98
  end
114
99
  end
115
100
  end
116
101
 
117
102
  describe '#calculate_md5' do
118
- subject(:headers){ described_class.new(request) }
119
- let(:driver){ headers.instance_variable_get("@request")}
103
+ subject(:headers) { described_class.new(request) }
104
+ let(:driver) { headers.instance_variable_get('@request') }
120
105
 
121
- context "no md5 already calculated" do
122
- let(:request) {
106
+ context 'no md5 already calculated' do
107
+ let(:request) do
123
108
  RestClient::Request.new(
124
109
  :url => 'http://google.com',
125
110
  :method => :post,
126
111
  :payload => "hello\nworld"
127
112
  )
128
- }
113
+ end
129
114
 
130
- it "populates the md5 header" do
115
+ it 'populates the md5 header' do
131
116
  expect(driver).to receive(:populate_content_md5)
132
117
  headers.calculate_md5
133
118
  end
134
119
  end
135
120
 
136
- context "md5 already calculated" do
137
- let(:request) {
121
+ context 'md5 already calculated' do
122
+ let(:request) do
138
123
  RestClient::Request.new(
139
124
  :url => 'http://google.com',
140
125
  :method => :post,
141
126
  :payload => "hello\nworld",
142
- :headers => {:content_md5 => "abcd"}
127
+ :headers => { :content_md5 => 'abcd' }
143
128
  )
144
- }
129
+ end
145
130
 
146
131
  it "doesn't populate the md5 header" do
147
132
  expect(driver).not_to receive(:populate_content_md5)
@@ -150,30 +135,30 @@ describe ApiAuth::Headers do
150
135
  end
151
136
  end
152
137
 
153
- describe "#md5_mismatch?" do
154
- let(:request){ RestClient::Request.new(:url => "http://google.com", :method => :get) }
155
- subject(:headers){ described_class.new(request) }
156
- let(:driver){ headers.instance_variable_get("@request") }
138
+ describe '#md5_mismatch?' do
139
+ let(:request) { RestClient::Request.new(:url => 'http://google.com', :method => :get) }
140
+ subject(:headers) { described_class.new(request) }
141
+ let(:driver) { headers.instance_variable_get('@request') }
157
142
 
158
- context "when request has md5 header" do
159
- it "asks the driver" do
160
- allow(driver).to receive(:content_md5).and_return "1234"
143
+ context 'when request has md5 header' do
144
+ it 'asks the driver' do
145
+ allow(driver).to receive(:content_md5).and_return '1234'
161
146
 
162
147
  expect(driver).to receive(:md5_mismatch?).and_call_original
163
148
  headers.md5_mismatch?
164
149
  end
165
150
  end
166
151
 
167
- context "when request has no md5" do
152
+ context 'when request has no md5' do
168
153
  it "doesn't ask the driver" do
169
- allow(driver).to receive(:content_md5).and_return ""
154
+ allow(driver).to receive(:content_md5).and_return ''
170
155
 
171
156
  expect(driver).not_to receive(:md5_mismatch?).and_call_original
172
157
  headers.md5_mismatch?
173
158
  end
174
159
 
175
- it "returns false" do
176
- allow(driver).to receive(:content_md5).and_return ""
160
+ it 'returns false' do
161
+ allow(driver).to receive(:content_md5).and_return ''
177
162
 
178
163
  expect(headers.md5_mismatch?).to be false
179
164
  end
@@ -1,14 +1,12 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
 
3
- describe "ApiAuth::Helpers" do
4
-
5
- it "should strip the new line character on a Base64 encoding" do
6
- expect(ApiAuth.b64_encode("some string")).not_to match(/\n/)
3
+ describe 'ApiAuth::Helpers' do
4
+ it 'should strip the new line character on a Base64 encoding' do
5
+ expect(ApiAuth.b64_encode('some string')).not_to match(/\n/)
7
6
  end
8
-
7
+
9
8
  it "should properly upcase a hash's keys" do
10
- hsh = { "JoE" => "rOOLz" }
11
- expect(ApiAuth.capitalize_keys(hsh)["JOE"]).to eq("rOOLz")
9
+ hsh = { 'JoE' => 'rOOLz' }
10
+ expect(ApiAuth.capitalize_keys(hsh)['JOE']).to eq('rOOLz')
12
11
  end
13
-
14
- end
12
+ end
@@ -1,14 +1,11 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
 
3
- describe "Rails integration" do
4
-
5
- API_KEY_STORE = { "1044" => "l16imAXie1sRMcJODpOG7UwC1VyoqvO13jejkfpKWX4Z09W8DC9IrU23DvCwMry7pgSFW6c5S1GIfV0OY6F/vUA==" }
6
-
7
- describe "Rails controller integration" do
3
+ describe 'Rails integration' do
4
+ API_KEY_STORE = { '1044' => 'l16imAXie1sRMcJODpOG7UwC1VyoqvO13jejkfpKWX4Z09W8DC9IrU23DvCwMry7pgSFW6c5S1GIfV0OY6F/vUA==' }.freeze
8
5
 
6
+ describe 'Rails controller integration' do
9
7
  class ApplicationController < ActionController::Base
10
-
11
- private
8
+ private
12
9
 
13
10
  def require_api_auth
14
11
  if (access_id = get_api_access_id_from_request)
@@ -16,12 +13,11 @@ describe "Rails integration" do
16
13
  end
17
14
 
18
15
  respond_to do |format|
19
- format.xml { render :xml => "You are unauthorized to perform this action.", :status => 401 }
20
- format.json { render :json => "You are unauthorized to perform this action.", :status => 401 }
21
- format.html { render :text => "You are unauthorized to perform this action", :status => 401 }
16
+ format.xml { render :xml => 'You are unauthorized to perform this action.', :status => 401 }
17
+ format.json { render :json => 'You are unauthorized to perform this action.', :status => 401 }
18
+ format.html { render :text => 'You are unauthorized to perform this action', :status => 401 }
22
19
  end
23
20
  end
24
-
25
21
  end
26
22
 
27
23
  class TestController < ApplicationController
@@ -34,18 +30,20 @@ describe "Rails integration" do
34
30
  end
35
31
 
36
32
  def index
37
- render :text => "OK"
33
+ render :text => 'OK'
38
34
  end
39
35
 
40
36
  def public
41
- render :text => "OK"
37
+ render :text => 'OK'
42
38
  end
43
39
 
44
- def rescue_action(e); raise(e); end
40
+ def rescue_action(e)
41
+ raise(e)
42
+ end
45
43
  end
46
44
 
47
45
  unless defined?(ActionDispatch)
48
- ActionController::Routing::Routes.draw {|map| map.resources :test }
46
+ ActionController::Routing::Routes.draw { |map| map.resources :test }
49
47
  end
50
48
 
51
49
  def generated_response(request, action = :index)
@@ -58,102 +56,74 @@ describe "Rails integration" do
58
56
  response
59
57
  else
60
58
  request.action = action.to_s
61
- request.path = "/#{action.to_s}"
59
+ request.path = "/#{action}"
62
60
  TestController.new.process(request, ActionController::TestResponse.new)
63
61
  end
64
62
  end
65
63
 
66
- it "should permit a request with properly signed headers" do
64
+ it 'should permit a request with properly signed headers' do
67
65
  request = ActionController::TestRequest.new
68
66
  request.env['DATE'] = Time.now.utc.httpdate
69
- ApiAuth.sign!(request, "1044", API_KEY_STORE["1044"])
67
+ ApiAuth.sign!(request, '1044', API_KEY_STORE['1044'])
70
68
  response = generated_response(request, :index)
71
- expect(response.code).to eq("200")
69
+ expect(response.code).to eq('200')
72
70
  end
73
71
 
74
- it "should forbid a request with properly signed headers but timestamp > 15 minutes" do
72
+ it 'should forbid a request with properly signed headers but timestamp > 15 minutes' do
75
73
  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"])
74
+ request.env['DATE'] = 'Mon, 23 Jan 1984 03:29:56 GMT'
75
+ ApiAuth.sign!(request, '1044', API_KEY_STORE['1044'])
78
76
  response = generated_response(request, :index)
79
- expect(response.code).to eq("401")
77
+ expect(response.code).to eq('401')
80
78
  end
81
79
 
82
80
  it "should insert a DATE header in the request when one hasn't been specified" do
83
81
  request = ActionController::TestRequest.new
84
- ApiAuth.sign!(request, "1044", API_KEY_STORE["1044"])
82
+ ApiAuth.sign!(request, '1044', API_KEY_STORE['1044'])
85
83
  expect(request.headers['DATE']).not_to be_nil
86
84
  end
87
85
 
88
- it "should forbid an unsigned request to a protected controller action" do
86
+ it 'should forbid an unsigned request to a protected controller action' do
89
87
  request = ActionController::TestRequest.new
90
88
  response = generated_response(request, :index)
91
- expect(response.code).to eq("401")
89
+ expect(response.code).to eq('401')
92
90
  end
93
91
 
94
- it "should forbid a request with a bogus signature" do
92
+ it 'should forbid a request with a bogus signature' do
95
93
  request = ActionController::TestRequest.new
96
- request.env['Authorization'] = "APIAuth bogus:bogus"
94
+ request.env['Authorization'] = 'APIAuth bogus:bogus'
97
95
  response = generated_response(request, :index)
98
- expect(response.code).to eq("401")
96
+ expect(response.code).to eq('401')
99
97
  end
100
98
 
101
- it "should allow non-protected controller actions to function as before" do
99
+ it 'should allow non-protected controller actions to function as before' do
102
100
  request = ActionController::TestRequest.new
103
101
  response = generated_response(request, :public)
104
- expect(response.code).to eq("200")
102
+ expect(response.code).to eq('200')
105
103
  end
106
-
107
104
  end
108
105
 
109
- describe "Rails ActiveResource integration" do
110
-
106
+ describe 'Rails ActiveResource integration' do
111
107
  class TestResource < ActiveResource::Base
112
- with_api_auth "1044", API_KEY_STORE["1044"]
113
- self.site = "http://localhost/"
108
+ with_api_auth '1044', API_KEY_STORE['1044']
109
+ self.site = 'http://localhost/'
114
110
  self.format = :xml
115
111
  end
116
112
 
117
- it "should send signed requests automagically" do
118
- timestamp = Time.parse("Mon, 23 Jan 1984 03:29:56 GMT")
113
+ it 'should send signed requests automagically' do
114
+ timestamp = Time.parse('Mon, 23 Jan 1984 03:29:56 GMT')
119
115
  allow(Time).to receive(:now).at_least(1).times.and_return(timestamp)
120
116
  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')
117
+ mock.get '/test_resources/1.xml',
118
+ {
119
+ 'Authorization' => 'APIAuth 1044:LZ1jujf3x1nnGR70/208WPXdUHw=',
120
+ 'Accept' => 'application/xml',
121
+ 'DATE' => 'Mon, 23 Jan 1984 03:29:56 GMT'
122
+ },
123
+ { :id => '1' }.to_xml(:root => 'test_resource')
128
124
  end
129
- expect(ApiAuth).to receive(:sign!).with(anything, "1044", API_KEY_STORE["1044"], { :with_http_method => false }).and_call_original
125
+ expect(ApiAuth).to receive(:sign!).with(anything, '1044', API_KEY_STORE['1044']).and_call_original
130
126
  TestResource.find(1)
131
127
  end
132
-
133
- context "when telling it to include the http method in the signature" do
134
- class TestResourceForHttpMethod < ActiveResource::Base
135
- with_api_auth "1044", API_KEY_STORE["1044"], :sign_with_http_method => true
136
- self.site = "http://localhost/"
137
- self.format = :xml
138
- end
139
-
140
- it "signs with the http method" do
141
- timestamp = Time.parse("Mon, 23 Jan 1984 03:29:56 GMT")
142
- allow(Time).to receive(:now).at_least(1).times.and_return(timestamp)
143
- ActiveResource::HttpMock.respond_to do |mock|
144
- mock.get "/test_resource_for_http_methods/1.xml",
145
- {
146
- 'Authorization' => 'APIAuth 1044:Gq190cxgKm7oWH1fc+y8+wmD9ts=',
147
- 'Accept' => 'application/xml',
148
- 'DATE' => "Mon, 23 Jan 1984 03:29:56 GMT"
149
- },
150
- { :id => "1" }.to_xml(:root => 'test_resource')
151
- end
152
- expect(ApiAuth).to receive(:sign!).with(anything, "1044", API_KEY_STORE["1044"], { :with_http_method => true }).and_call_original
153
- TestResourceForHttpMethod.find(1)
154
- end
155
- end
156
-
157
128
  end
158
-
159
129
  end