songkick-oauth2-provider 0.10.2 → 0.10.3

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 (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