songkick-oauth2-provider 0.10.2 → 0.10.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +7 -0
  2. data/History.txt +7 -0
  3. data/README.rdoc +18 -11
  4. data/example/README.rdoc +1 -1
  5. data/example/application.rb +9 -9
  6. data/example/schema.rb +1 -1
  7. data/example/views/authorize.erb +2 -2
  8. data/example/views/layout.erb +4 -4
  9. data/example/views/login.erb +2 -2
  10. data/example/views/new_client.erb +1 -1
  11. data/example/views/new_user.erb +1 -1
  12. data/lib/songkick/oauth2/model.rb +8 -6
  13. data/lib/songkick/oauth2/model/authorization.rb +31 -31
  14. data/lib/songkick/oauth2/model/client.rb +15 -15
  15. data/lib/songkick/oauth2/model/client_owner.rb +2 -2
  16. data/lib/songkick/oauth2/model/hashing.rb +3 -3
  17. data/lib/songkick/oauth2/model/helpers.rb +16 -0
  18. data/lib/songkick/oauth2/model/resource_owner.rb +4 -4
  19. data/lib/songkick/oauth2/provider.rb +16 -16
  20. data/lib/songkick/oauth2/provider/access_token.rb +20 -15
  21. data/lib/songkick/oauth2/provider/authorization.rb +43 -42
  22. data/lib/songkick/oauth2/provider/error.rb +4 -4
  23. data/lib/songkick/oauth2/provider/exchange.rb +46 -46
  24. data/lib/songkick/oauth2/router.rb +13 -13
  25. data/lib/songkick/oauth2/schema.rb +11 -3
  26. data/lib/songkick/oauth2/schema/20120828112156_songkick_oauth2_schema_original_schema.rb +2 -2
  27. data/lib/songkick/oauth2/schema/20121024180930_songkick_oauth2_schema_add_authorization_index.rb +3 -3
  28. data/lib/songkick/oauth2/schema/20121025180447_songkick_oauth2_schema_add_unique_indexes.rb +7 -7
  29. data/spec/request_helpers.rb +25 -21
  30. data/spec/songkick/oauth2/model/authorization_spec.rb +56 -56
  31. data/spec/songkick/oauth2/model/client_spec.rb +9 -9
  32. data/spec/songkick/oauth2/model/helpers_spec.rb +26 -0
  33. data/spec/songkick/oauth2/model/resource_owner_spec.rb +13 -13
  34. data/spec/songkick/oauth2/provider/access_token_spec.rb +32 -20
  35. data/spec/songkick/oauth2/provider/authorization_spec.rb +73 -62
  36. data/spec/songkick/oauth2/provider/exchange_spec.rb +72 -72
  37. data/spec/songkick/oauth2/provider_spec.rb +101 -101
  38. data/spec/spec_helper.rb +5 -3
  39. data/spec/test_app/helper.rb +11 -7
  40. data/spec/test_app/provider/application.rb +12 -12
  41. data/spec/test_app/provider/views/authorize.erb +2 -2
  42. metadata +71 -93
@@ -1,57 +1,61 @@
1
+ require "socket"
2
+
1
3
  module RequestHelpers
2
- require 'net/http'
3
-
4
+ require "net/http"
5
+
6
+ SERVER_PORT = TCPServer.new(0).addr[1]
7
+
4
8
  def querystring(params)
5
- params.map { |k,v| "#{ CGI.escape k.to_s }=#{ CGI.escape v.to_s }" }.join('&')
9
+ params.map { |k,v| "#{ CGI.escape k.to_s }=#{ CGI.escape v.to_s }" }.join("&")
6
10
  end
7
-
11
+
8
12
  def get(query_params)
9
- uri = URI.parse('http://localhost:8000/authorize?' + querystring(query_params))
13
+ uri = URI.parse("http://localhost:#{SERVER_PORT}/authorize?" + querystring(query_params))
10
14
  Net::HTTP.get_response(uri)
11
15
  end
12
-
16
+
13
17
  def allow_or_deny(query_params)
14
- Net::HTTP.post_form(URI.parse('http://localhost:8000/allow'), query_params)
18
+ Net::HTTP.post_form(URI.parse("http://localhost:#{SERVER_PORT}/allow"), query_params)
15
19
  end
16
-
20
+
17
21
  def post_basic_auth(auth_params, query_params)
18
- url = "http://#{ auth_params['client_id'] }:#{ auth_params['client_secret'] }@localhost:8000/authorize"
22
+ url = "http://#{ auth_params["client_id"] }:#{ auth_params["client_secret"] }@localhost:#{SERVER_PORT}/authorize"
19
23
  Net::HTTP.post_form(URI.parse(url), query_params)
20
24
  end
21
-
25
+
22
26
  def post(body_params, query_params = {})
23
- uri = URI.parse('http://localhost:8000/authorize?' + querystring(query_params))
27
+ uri = URI.parse("http://localhost:#{SERVER_PORT}/authorize?" + querystring(query_params))
24
28
  Net::HTTP.start(uri.host, uri.port) do |http|
25
- http.post(uri.path + '?' + uri.query.to_s, querystring(body_params))
29
+ http.post(uri.path + "?" + uri.query.to_s, querystring(body_params))
26
30
  end
27
31
  end
28
-
32
+
29
33
  def validate_response(response, status, body)
30
34
  response.code.to_i.should == status
31
35
  response.body.should == body
32
- response['Cache-Control'].should == 'no-store'
36
+ response["Cache-Control"].should == "no-store"
33
37
  end
34
-
38
+
35
39
  def validate_json_response(response, status, body)
36
40
  response.code.to_i.should == status
37
41
  JSON.parse(response.body).should == body
38
- response['Content-Type'].should == 'application/json'
39
- response['Cache-Control'].should == 'no-store'
42
+ response["Content-Type"].should == "application/json"
43
+ response["Cache-Control"].should == "no-store"
40
44
  end
41
-
45
+
42
46
  def mock_request(request_class, stubs = {})
43
- mock_request = mock(request_class)
47
+ mock_request = double(request_class)
44
48
  method_stubs = {
45
49
  :redirect? => false,
46
50
  :response_body => nil,
47
51
  :response_headers => {},
48
52
  :response_status => 200
49
53
  }.merge(stubs)
50
-
54
+
51
55
  method_stubs.each do |method, value|
52
56
  mock_request.should_receive(method).and_return(value)
53
57
  end
54
-
58
+
55
59
  mock_request
56
60
  end
57
61
  end
@@ -6,112 +6,112 @@ describe Songkick::OAuth2::Model::Authorization do
6
6
  let(:owner) { Factory :owner }
7
7
  let(:user) { Factory :owner }
8
8
  let(:tester) { Factory(:owner) }
9
-
9
+
10
10
  let(:authorization) do
11
11
  create_authorization(:owner => tester, :client => client)
12
12
  end
13
-
14
- it "is vaid" do
13
+
14
+ it "is valid" do
15
15
  authorization.should be_valid
16
16
  end
17
-
17
+
18
18
  it "is not valid without a client" do
19
19
  authorization.client = nil
20
20
  authorization.should_not be_valid
21
21
  end
22
-
22
+
23
23
  it "is not valid without an owner" do
24
24
  authorization.owner = nil
25
25
  authorization.should_not be_valid
26
26
  end
27
-
27
+
28
28
  describe "when there are existing authorizations" do
29
29
  before do
30
30
  create_authorization(
31
31
  :owner => user,
32
32
  :client => impostor,
33
33
  :access_token => 'existing_access_token')
34
-
34
+
35
35
  create_authorization(
36
36
  :owner => user,
37
37
  :client => client,
38
38
  :code => 'existing_code')
39
-
39
+
40
40
  create_authorization(
41
41
  :owner => owner,
42
42
  :client => client,
43
43
  :refresh_token => 'existing_refresh_token')
44
44
  end
45
-
45
+
46
46
  it "is valid if its access_token is unique" do
47
47
  authorization.should be_valid
48
48
  end
49
-
49
+
50
50
  it "is valid if both access_tokens are nil" do
51
51
  Songkick::OAuth2::Model::Authorization.first.update_attribute(:access_token, nil)
52
52
  authorization.access_token = nil
53
53
  authorization.should be_valid
54
54
  end
55
-
55
+
56
56
  it "is not valid if its access_token is not unique" do
57
57
  authorization.access_token = 'existing_access_token'
58
58
  authorization.should_not be_valid
59
59
  end
60
-
60
+
61
61
  it "is valid if it has a unique code for its client" do
62
62
  authorization.client = impostor
63
63
  authorization.code = 'existing_code'
64
64
  authorization.should be_valid
65
65
  end
66
-
66
+
67
67
  it "is not valid if it does not have a unique client and code" do
68
68
  authorization.code = 'existing_code'
69
69
  authorization.should_not be_valid
70
70
  end
71
-
71
+
72
72
  it "is valid if it has a unique refresh_token for its client" do
73
73
  authorization.client = impostor
74
74
  authorization.refresh_token = 'existing_refresh_token'
75
75
  authorization.should be_valid
76
76
  end
77
-
77
+
78
78
  it "is not valid if it does not have a unique client and refresh_token" do
79
79
  authorization.refresh_token = 'existing_refresh_token'
80
80
  authorization.should_not be_valid
81
81
  end
82
-
82
+
83
83
  describe ".create_code" do
84
84
  before { Songkick::OAuth2.stub(:random_string).and_return('existing_code', 'new_code') }
85
-
85
+
86
86
  it "returns the first code the client has not used" do
87
87
  Songkick::OAuth2::Model::Authorization.create_code(client).should == 'new_code'
88
88
  end
89
-
89
+
90
90
  it "returns the first code another client has not used" do
91
91
  Songkick::OAuth2::Model::Authorization.create_code(impostor).should == 'existing_code'
92
92
  end
93
93
  end
94
-
94
+
95
95
  describe ".create_access_token" do
96
96
  before { Songkick::OAuth2.stub(:random_string).and_return('existing_access_token', 'new_access_token') }
97
-
97
+
98
98
  it "returns the first unused token it can find" do
99
99
  Songkick::OAuth2::Model::Authorization.create_access_token.should == 'new_access_token'
100
100
  end
101
101
  end
102
-
102
+
103
103
  describe ".create_refresh_token" do
104
104
  before { Songkick::OAuth2.stub(:random_string).and_return('existing_refresh_token', 'new_refresh_token') }
105
-
105
+
106
106
  it "returns the first refresh_token the client has not used" do
107
107
  Songkick::OAuth2::Model::Authorization.create_refresh_token(client).should == 'new_refresh_token'
108
108
  end
109
-
109
+
110
110
  it "returns the first refresh_token another client has not used" do
111
111
  Songkick::OAuth2::Model::Authorization.create_refresh_token(impostor).should == 'existing_refresh_token'
112
112
  end
113
113
  end
114
-
114
+
115
115
  describe "duplicate records" do
116
116
  it "raises an error if a duplicate authorization is created" do
117
117
  lambda {
@@ -121,7 +121,7 @@ describe Songkick::OAuth2::Model::Authorization do
121
121
  authorization.save
122
122
  }.should raise_error
123
123
  end
124
-
124
+
125
125
  it "finds an existing record after a race" do
126
126
  user.stub(:oauth2_authorization_for) do
127
127
  user.unstub(:oauth2_authorization_for)
@@ -133,19 +133,19 @@ describe Songkick::OAuth2::Model::Authorization do
133
133
  end
134
134
  end
135
135
  end
136
-
136
+
137
137
  describe "#exchange!" do
138
138
  it "saves the record" do
139
139
  authorization.should_receive(:save!)
140
140
  authorization.exchange!
141
141
  end
142
-
142
+
143
143
  it "uses its helpers to find unique tokens" do
144
144
  Songkick::OAuth2::Model::Authorization.should_receive(:create_access_token).and_return('access_token')
145
145
  authorization.exchange!
146
146
  authorization.access_token.should == 'access_token'
147
147
  end
148
-
148
+
149
149
  it "updates the tokens correctly" do
150
150
  authorization.exchange!
151
151
  authorization.should be_valid
@@ -153,84 +153,84 @@ describe Songkick::OAuth2::Model::Authorization do
153
153
  authorization.refresh_token.should be_nil
154
154
  end
155
155
  end
156
-
156
+
157
157
  describe "#expired?" do
158
158
  it "returns false when not expiry is set" do
159
159
  authorization.should_not be_expired
160
160
  end
161
-
161
+
162
162
  it "returns false when expiry is in the future" do
163
163
  authorization.expires_at = 2.days.from_now
164
164
  authorization.should_not be_expired
165
165
  end
166
-
166
+
167
167
  it "returns true when expiry is in the past" do
168
168
  authorization.expires_at = 2.days.ago
169
169
  authorization.should be_expired
170
170
  end
171
171
  end
172
-
172
+
173
173
  describe "#grants_access?" do
174
174
  it "returns true given the right user" do
175
- authorization.grants_access?(tester).should be_true
175
+ authorization.grants_access?(tester).should be(true)
176
176
  end
177
-
177
+
178
178
  it "returns false given the wrong user" do
179
- authorization.grants_access?(user).should be_false
179
+ authorization.grants_access?(user).should be(false)
180
180
  end
181
-
181
+
182
182
  describe "when the authorization is expired" do
183
183
  before { authorization.expires_at = 2.days.ago }
184
-
184
+
185
185
  it "returns false in all cases" do
186
- authorization.grants_access?(tester).should be_false
187
- authorization.grants_access?(user).should be_false
186
+ authorization.grants_access?(tester).should be(false)
187
+ authorization.grants_access?(user).should be(false)
188
188
  end
189
189
  end
190
190
  end
191
-
191
+
192
192
  describe "with a scope" do
193
193
  before { authorization.scope = 'foo bar' }
194
-
194
+
195
195
  describe "#in_scope?" do
196
196
  it "returns true for authorized scopes" do
197
197
  authorization.should be_in_scope('foo')
198
198
  authorization.should be_in_scope('bar')
199
199
  end
200
-
200
+
201
201
  it "returns false for unauthorized scopes" do
202
202
  authorization.should_not be_in_scope('qux')
203
203
  authorization.should_not be_in_scope('fo')
204
204
  end
205
205
  end
206
-
206
+
207
207
  describe "#grants_access?" do
208
208
  it "returns true given the right user and all authorization scopes" do
209
- authorization.grants_access?(tester, 'foo', 'bar').should be_true
209
+ authorization.grants_access?(tester, 'foo', 'bar').should be(true)
210
210
  end
211
-
211
+
212
212
  it "returns true given the right user and some authorization scopes" do
213
- authorization.grants_access?(tester, 'bar').should be_true
213
+ authorization.grants_access?(tester, 'bar').should be(true)
214
214
  end
215
-
215
+
216
216
  it "returns false given the right user and some unauthorization scopes" do
217
- authorization.grants_access?(tester, 'foo', 'bar', 'qux').should be_false
217
+ authorization.grants_access?(tester, 'foo', 'bar', 'qux').should be(false)
218
218
  end
219
-
219
+
220
220
  it "returns false given an unauthorized scope" do
221
- authorization.grants_access?(tester, 'qux').should be_false
221
+ authorization.grants_access?(tester, 'qux').should be(false)
222
222
  end
223
-
223
+
224
224
  it "returns true given the right user" do
225
- authorization.grants_access?(tester).should be_true
225
+ authorization.grants_access?(tester).should be(true)
226
226
  end
227
-
227
+
228
228
  it "returns false given the wrong user" do
229
- authorization.grants_access?(user).should be_false
229
+ authorization.grants_access?(user).should be(false)
230
230
  end
231
-
231
+
232
232
  it "returns false given the wrong user and an authorized scope" do
233
- authorization.grants_access?(user, 'foo').should be_false
233
+ authorization.grants_access?(user, 'foo').should be(false)
234
234
  end
235
235
  end
236
236
  end
@@ -6,47 +6,47 @@ describe Songkick::OAuth2::Model::Client do
6
6
  @owner = Factory(:owner)
7
7
  Songkick::OAuth2::Model::Authorization.for(@owner, @client)
8
8
  end
9
-
9
+
10
10
  it "is valid" do
11
11
  @client.should be_valid
12
12
  end
13
-
13
+
14
14
  it "is invalid without a name" do
15
15
  @client.name = nil
16
16
  @client.should_not be_valid
17
17
  end
18
-
18
+
19
19
  it "is invalid without a redirect_uri" do
20
20
  @client.redirect_uri = nil
21
21
  @client.should_not be_valid
22
22
  end
23
-
23
+
24
24
  it "is invalid with a non-URI redirect_uri" do
25
25
  @client.redirect_uri = 'foo'
26
26
  @client.should_not be_valid
27
27
  end
28
-
28
+
29
29
  # http://en.wikipedia.org/wiki/HTTP_response_splitting
30
30
  it "is invalid if the URI contains HTTP line breaks" do
31
31
  @client.redirect_uri = "http://example.com/c\r\nb"
32
32
  @client.should_not be_valid
33
33
  end
34
-
34
+
35
35
  it "cannot mass-assign client_id" do
36
36
  @client.update_attributes(:client_id => 'foo')
37
37
  @client.client_id.should_not == 'foo'
38
38
  end
39
-
39
+
40
40
  it "cannot mass-assign client_secret" do
41
41
  @client.update_attributes(:client_secret => 'foo')
42
42
  @client.client_secret.should_not == 'foo'
43
43
  end
44
-
44
+
45
45
  it "has client_id and client_secret filled in" do
46
46
  @client.client_id.should_not be_nil
47
47
  @client.client_secret.should_not be_nil
48
48
  end
49
-
49
+
50
50
  it "destroys its authorizations on destroy" do
51
51
  @client.destroy
52
52
  Songkick::OAuth2::Model::Authorization.count.should be_zero
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ describe Songkick::OAuth2::Model::Helpers do
4
+ subject { Songkick::OAuth2::Model::Helpers }
5
+
6
+ describe '.count' do
7
+ let(:owner) { Factory(:owner) }
8
+
9
+ before do
10
+ 3.times { Factory(:client, :owner => owner) }
11
+ end
12
+
13
+ context 'when conditions are not passed' do
14
+ it 'returns count of total rows' do
15
+ subject.count(owner.oauth2_clients).should == 3
16
+ end
17
+ end
18
+
19
+ context 'when conditions are passed' do
20
+ it 'returns count of rows satisfying supplied conditions' do
21
+ subject.count(Songkick::OAuth2::Model::Client, :client_id => Songkick::OAuth2::Model::Client.first.client_id).should == 1
22
+ end
23
+ end
24
+ end
25
+ end
26
+
@@ -5,29 +5,29 @@ describe Songkick::OAuth2::Model::ResourceOwner do
5
5
  @owner = Factory(:owner)
6
6
  @client = Factory(:client)
7
7
  end
8
-
8
+
9
9
  describe "#grant_access!" do
10
10
  it "raises an error when passed an invalid client argument" do
11
11
  lambda{ @owner.grant_access!('client') }.should raise_error(ArgumentError)
12
12
  end
13
-
13
+
14
14
  it "creates an authorization between the owner and the client" do
15
15
  authorization = Songkick::OAuth2::Model::Authorization.__send__(:new)
16
16
  Songkick::OAuth2::Model::Authorization.should_receive(:new).and_return(authorization)
17
17
  @owner.grant_access!(@client)
18
18
  end
19
-
20
- # This is hacky, but mocking ActiveRecord turns out to get messy
19
+
20
+ # This is hacky, but doubleing ActiveRecord turns out to get messy
21
21
  it "creates an Authorization" do
22
22
  Songkick::OAuth2::Model::Authorization.count.should == 0
23
23
  @owner.grant_access!(@client)
24
24
  Songkick::OAuth2::Model::Authorization.count.should == 1
25
25
  end
26
-
26
+
27
27
  it "returns the authorization" do
28
28
  @owner.grant_access!(@client).should be_kind_of(Songkick::OAuth2::Model::Authorization)
29
29
  end
30
-
30
+
31
31
  # This method must return the same owner object, since the assertion
32
32
  # handler may modify it -- either by changing its attributes or by extending
33
33
  # it with new methods. These changes must be returned to the app calling the
@@ -36,34 +36,34 @@ describe Songkick::OAuth2::Model::ResourceOwner do
36
36
  authorization = @owner.grant_access!(@client)
37
37
  authorization.owner.should be_equal(@owner)
38
38
  end
39
-
39
+
40
40
  it "sets the duration of the authorization" do
41
41
  authorization = @owner.grant_access!(@client, :duration => 5.hours)
42
42
  authorization.expires_at.to_i.should == (Time.now + 5.hours.to_i).to_i
43
43
  end
44
44
  end
45
-
45
+
46
46
  describe "when there is an existing authorization" do
47
47
  before do
48
48
  @authorization = create_authorization(:owner => @owner, :client => @client)
49
49
  end
50
-
50
+
51
51
  it "does not create a new one" do
52
52
  Songkick::OAuth2::Model::Authorization.should_not_receive(:new)
53
53
  @owner.grant_access!(@client)
54
54
  end
55
-
55
+
56
56
  it "updates the authorization with scopes" do
57
57
  @owner.grant_access!(@client, :scopes => ['foo', 'bar'])
58
58
  @authorization.reload
59
59
  @authorization.scopes.should == Set.new(['foo', 'bar'])
60
60
  end
61
-
61
+
62
62
  describe "with scopes" do
63
63
  before do
64
64
  @authorization.update_attribute(:scope, 'foo bar')
65
65
  end
66
-
66
+
67
67
  it "merges the new scopes with the existing ones" do
68
68
  @owner.grant_access!(@client, :scopes => ['qux'])
69
69
  @authorization.reload
@@ -78,7 +78,7 @@ describe Songkick::OAuth2::Model::ResourceOwner do
78
78
  end
79
79
  end
80
80
  end
81
-
81
+
82
82
  it "destroys its authorizations on destroy" do
83
83
  Songkick::OAuth2::Model::Authorization.for(@owner, @client)
84
84
  @owner.destroy