api-auth 1.5.0 → 2.0.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 (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