oauth2-provider 0.0.16

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. data/.gitignore +8 -0
  2. data/Gemfile +3 -0
  3. data/README.md +49 -0
  4. data/Rakefile +24 -0
  5. data/examples/client/Gemfile +6 -0
  6. data/examples/client/Gemfile.lock +20 -0
  7. data/examples/client/README +8 -0
  8. data/examples/client/app.rb +59 -0
  9. data/examples/client/config.ru +3 -0
  10. data/examples/client/views/home.haml +3 -0
  11. data/examples/client/views/response.haml +11 -0
  12. data/examples/rails3-example/.gitignore +4 -0
  13. data/examples/rails3-example/Gemfile +10 -0
  14. data/examples/rails3-example/Gemfile.lock +82 -0
  15. data/examples/rails3-example/README +9 -0
  16. data/examples/rails3-example/Rakefile +7 -0
  17. data/examples/rails3-example/app/controllers/account_controller.rb +14 -0
  18. data/examples/rails3-example/app/controllers/application_controller.rb +18 -0
  19. data/examples/rails3-example/app/controllers/authorization_controller.rb +18 -0
  20. data/examples/rails3-example/app/controllers/home_controller.rb +4 -0
  21. data/examples/rails3-example/app/controllers/session_controller.rb +24 -0
  22. data/examples/rails3-example/app/helpers/application_helper.rb +2 -0
  23. data/examples/rails3-example/app/models/account.rb +6 -0
  24. data/examples/rails3-example/app/views/authorization/new.html.erb +5 -0
  25. data/examples/rails3-example/app/views/home/show.html.erb +1 -0
  26. data/examples/rails3-example/app/views/layouts/application.html.erb +16 -0
  27. data/examples/rails3-example/app/views/session/new.html.erb +7 -0
  28. data/examples/rails3-example/config.ru +4 -0
  29. data/examples/rails3-example/config/application.rb +42 -0
  30. data/examples/rails3-example/config/boot.rb +6 -0
  31. data/examples/rails3-example/config/database.yml +22 -0
  32. data/examples/rails3-example/config/environment.rb +5 -0
  33. data/examples/rails3-example/config/environments/development.rb +26 -0
  34. data/examples/rails3-example/config/environments/production.rb +49 -0
  35. data/examples/rails3-example/config/environments/test.rb +35 -0
  36. data/examples/rails3-example/config/initializers/backtrace_silencers.rb +7 -0
  37. data/examples/rails3-example/config/initializers/inflections.rb +10 -0
  38. data/examples/rails3-example/config/initializers/mime_types.rb +5 -0
  39. data/examples/rails3-example/config/initializers/secret_token.rb +7 -0
  40. data/examples/rails3-example/config/initializers/session_store.rb +8 -0
  41. data/examples/rails3-example/config/locales/en.yml +5 -0
  42. data/examples/rails3-example/config/routes.rb +9 -0
  43. data/examples/rails3-example/db/migrate/20110508151935_add_account_table.rb +12 -0
  44. data/examples/rails3-example/db/migrate/20110508151948_add_oauth2_tables.rb +43 -0
  45. data/examples/rails3-example/db/schema.rb +52 -0
  46. data/examples/rails3-example/db/seeds.rb +11 -0
  47. data/examples/rails3-example/doc/README_FOR_APP +2 -0
  48. data/examples/rails3-example/lib/tasks/.gitkeep +0 -0
  49. data/examples/rails3-example/public/404.html +26 -0
  50. data/examples/rails3-example/public/422.html +26 -0
  51. data/examples/rails3-example/public/500.html +26 -0
  52. data/examples/rails3-example/public/favicon.ico +0 -0
  53. data/examples/rails3-example/public/images/rails.png +0 -0
  54. data/examples/rails3-example/public/robots.txt +5 -0
  55. data/examples/rails3-example/public/stylesheets/.gitkeep +0 -0
  56. data/examples/rails3-example/script/rails +6 -0
  57. data/lib/oauth2-provider.rb +3 -0
  58. data/lib/oauth2/provider.rb +39 -0
  59. data/lib/oauth2/provider/models.rb +40 -0
  60. data/lib/oauth2/provider/models/access_token.rb +54 -0
  61. data/lib/oauth2/provider/models/active_record.rb +30 -0
  62. data/lib/oauth2/provider/models/active_record/access_token.rb +13 -0
  63. data/lib/oauth2/provider/models/active_record/authorization.rb +16 -0
  64. data/lib/oauth2/provider/models/active_record/authorization_code.rb +13 -0
  65. data/lib/oauth2/provider/models/active_record/client.rb +15 -0
  66. data/lib/oauth2/provider/models/authorization.rb +40 -0
  67. data/lib/oauth2/provider/models/authorization_code.rb +27 -0
  68. data/lib/oauth2/provider/models/client.rb +28 -0
  69. data/lib/oauth2/provider/models/mongoid.rb +30 -0
  70. data/lib/oauth2/provider/models/mongoid/access_token.rb +40 -0
  71. data/lib/oauth2/provider/models/mongoid/authorization.rb +32 -0
  72. data/lib/oauth2/provider/models/mongoid/authorization_code.rb +43 -0
  73. data/lib/oauth2/provider/models/mongoid/client.rb +40 -0
  74. data/lib/oauth2/provider/rack.rb +11 -0
  75. data/lib/oauth2/provider/rack/access_token_handler.rb +103 -0
  76. data/lib/oauth2/provider/rack/authorization_code_request.rb +74 -0
  77. data/lib/oauth2/provider/rack/authorization_codes_support.rb +25 -0
  78. data/lib/oauth2/provider/rack/middleware.rb +28 -0
  79. data/lib/oauth2/provider/rack/resource_request.rb +91 -0
  80. data/lib/oauth2/provider/rack/responses.rb +34 -0
  81. data/lib/oauth2/provider/rails.rb +37 -0
  82. data/lib/oauth2/provider/rails/controller_authentication.rb +21 -0
  83. data/lib/oauth2/provider/random.rb +30 -0
  84. data/lib/oauth2/provider/version.rb +5 -0
  85. data/oauth2-provider.gemspec +35 -0
  86. data/spec/models/access_token_spec.rb +123 -0
  87. data/spec/models/authorization_code_spec.rb +115 -0
  88. data/spec/models/authorization_spec.rb +110 -0
  89. data/spec/models/client_spec.rb +75 -0
  90. data/spec/requests/access_tokens_controller_spec.rb +360 -0
  91. data/spec/requests/authentication_spec.rb +150 -0
  92. data/spec/requests/authorization_codes_support_spec.rb +157 -0
  93. data/spec/schema.rb +38 -0
  94. data/spec/set_backend_env_to_mongoid.rb +1 -0
  95. data/spec/spec_helper.rb +27 -0
  96. data/spec/support/activerecord_backend.rb +18 -0
  97. data/spec/support/factories.rb +56 -0
  98. data/spec/support/macros.rb +46 -0
  99. data/spec/support/mongoid_backend.rb +34 -0
  100. data/spec/support/rack.rb +32 -0
  101. metadata +373 -0
@@ -0,0 +1,34 @@
1
+ require 'addressable/uri'
2
+
3
+ module OAuth2::Provider::Rack::Responses
4
+ def self.unauthorized(error = nil)
5
+ challenge = "OAuth2"
6
+ challenge << %{ error="#{error}"} if error
7
+ [401, {'Content-Type' => 'text/plain', 'Content-Length' => '0', 'WWW-Authenticate' => challenge}, []]
8
+ end
9
+
10
+ def self.only_supported(supported)
11
+ [405, {'Allow' => supported}, ["Only #{supported} requests allowed"]]
12
+ end
13
+
14
+ def self.json_error(error, options = {})
15
+ description = %{, "error_description": "#{options[:description]}"} if options[:description]
16
+ [options[:status] || 400, {'Content-Type' => 'application/json'}, [%{{"error": "#{error}"#{description}}}]]
17
+ end
18
+
19
+ def self.redirect_with_error(error, uri)
20
+ [302, {'Location' => append_to_uri(uri, :error => error)}, []]
21
+ end
22
+
23
+ def self.redirect_with_code(code, uri)
24
+ [302, {'Location' => append_to_uri(uri, :code => code)}, []]
25
+ end
26
+
27
+ private
28
+
29
+ def self.append_to_uri(uri, parameters = {})
30
+ u = Addressable::URI.parse(uri)
31
+ u.query_values = (u.query_values || {}).merge(parameters)
32
+ u.to_s
33
+ end
34
+ end
@@ -0,0 +1,37 @@
1
+ require 'oauth2/provider'
2
+
3
+ module OAuth2::Provider::Rails
4
+ autoload :ControllerAuthentication, 'oauth2/provider/rails/controller_authentication'
5
+
6
+ class Railtie < Rails::Railtie
7
+ config.oauth2_provider = ActiveSupport::OrderedOptions.new
8
+ config.oauth2_provider.activerecord = ActiveSupport::OrderedOptions.new
9
+ config.oauth2_provider.mongoid = ActiveSupport::OrderedOptions.new
10
+
11
+ initializer "oauth2_provider.config" do |app|
12
+ app.config.oauth2_provider.except(:activerecord, :mongoid).each do |k,v|
13
+ OAuth2::Provider.send "#{k}=", v
14
+ end
15
+
16
+ app.config.oauth2_provider.activerecord.each do |k, v|
17
+ OAuth2::Provider::Models::ActiveRecord.send "#{k}=", v
18
+ end
19
+
20
+ app.config.oauth2_provider.mongoid.each do |k, v|
21
+ OAuth2::Provider::Models::Mongoid.send "#{k}=", v
22
+ end
23
+
24
+ OAuth2::Provider.activate
25
+ end
26
+
27
+ initializer "oauth2_provider.initialize_controller" do |app|
28
+ ActionController::Base.module_eval do
29
+ include OAuth2::Provider::Rails::ControllerAuthentication
30
+ end
31
+ end
32
+
33
+ initializer "oauth2_provider.initialize_middleware" do |app|
34
+ app.middleware.use ::OAuth2::Provider::Rack::Middleware
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,21 @@
1
+ require 'oauth2/provider'
2
+
3
+ module OAuth2::Provider::Rails::ControllerAuthentication
4
+ extend ActiveSupport::Concern
5
+
6
+ module ClassMethods
7
+ def authenticate_with_oauth(options = {})
8
+ around_filter AuthenticationFilter.new(options.delete(:scope)), options
9
+ end
10
+
11
+ class AuthenticationFilter
12
+ def initialize(scope = nil)
13
+ @scope = scope
14
+ end
15
+
16
+ def filter(controller, &block)
17
+ controller.request.env['oauth2'].authenticate_request! :scope => @scope, &block
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,30 @@
1
+ require 'oauth2/provider'
2
+
3
+ module OAuth2::Provider::Random
4
+ module Base62
5
+ CHARS = ('0'..'9').to_a + ('a'..'z').to_a + ('A'..'Z').to_a
6
+
7
+ # Adapted from http://refactormycode.com/codes/125-base-62-encoding
8
+ def self.encode(i)
9
+ return '0' if i == 0
10
+ s = ''
11
+ while i > 0
12
+ s << CHARS[i.modulo(62)]
13
+ i /= 62
14
+ end
15
+ s.reverse!
16
+ s
17
+ end
18
+ end
19
+
20
+ def base62(length = 8)
21
+ number = ActiveSupport::SecureRandom.random_number(62 ** length)
22
+ Base62.encode(number).rjust(length, '0')
23
+ end
24
+
25
+ def base36(length = 8)
26
+ ActiveSupport::SecureRandom.random_number(36 ** length).to_s(36).rjust(length, '0')
27
+ end
28
+
29
+ module_function :base62, :base36
30
+ end
@@ -0,0 +1,5 @@
1
+ module OAuth2
2
+ module Provider
3
+ VERSION = "0.0.16"
4
+ end
5
+ end
@@ -0,0 +1,35 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "oauth2/provider/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "oauth2-provider"
7
+ s.version = OAuth2::Provider::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Tom Ward"]
10
+ s.email = ["tom@popdog.net"]
11
+ s.homepage = "http://tomafro.net"
12
+ s.summary = %q{OAuth2 Provider, extracted from api.hashblue.com}
13
+ s.description = %q{OAuth2 Provider, extracted from api.hashblue.com}
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+ s.require_paths = ["lib"]
19
+
20
+ # Main dependencies
21
+ s.add_dependency 'activesupport', '~>3.0.1'
22
+ s.add_dependency 'addressable', '~>2.2'
23
+
24
+ # Development only dependencies
25
+ s.add_development_dependency 'rails', '~>3.0.1'
26
+ s.add_development_dependency 'rspec-rails', '~>2.1.0'
27
+ s.add_development_dependency 'rake', '~>0.8.7'
28
+ s.add_development_dependency 'sqlite3-ruby', '~>1.3.1'
29
+ s.add_development_dependency 'timecop', '~>0.3.4'
30
+ s.add_development_dependency 'yajl-ruby', '~>0.7.5'
31
+ s.add_development_dependency 'mongoid', '2.0.0.rc.6'
32
+ s.add_development_dependency 'bson', '1.2.0'
33
+ s.add_development_dependency 'bson_ext', '1.2.0'
34
+ s.add_development_dependency 'sdoc', '~>0.2.20'
35
+ end
@@ -0,0 +1,123 @@
1
+ require 'spec_helper'
2
+
3
+ describe OAuth2::Provider.access_token_class do
4
+ describe "any instance" do
5
+ subject do
6
+ OAuth2::Provider.access_token_class.new :authorization => build_authorization
7
+ end
8
+
9
+ it "is valid with an access grant, expiry time and access token" do
10
+ subject.expires_at.should_not be_nil
11
+ subject.access_token.should_not be_nil
12
+ subject.authorization.should_not be_nil
13
+
14
+ subject.should be_valid
15
+ end
16
+
17
+ it "is invalid without an access token" do
18
+ subject.access_token = nil
19
+ subject.should_not be_valid
20
+ end
21
+
22
+ it "is invalid without an access grant" do
23
+ subject.authorization = nil
24
+ subject.should_not be_valid
25
+ end
26
+
27
+ it "is invalid when expires_at isn't set" do
28
+ subject.expires_at = nil
29
+ subject.should_not be_valid
30
+ end
31
+
32
+ it "is invalid if expires_at is later than the authorization's value" do
33
+ subject.authorization.expires_at = 1.minute.from_now
34
+ subject.expires_at = 10.minutes.from_now
35
+ subject.should_not be_valid
36
+ end
37
+
38
+ it "returns time in seconds until expiry when expires_in called" do
39
+ subject.expires_at = 60.minutes.from_now
40
+ subject.expires_in.should == (60 * 60)
41
+ end
42
+
43
+ it "returns 0 for expired_in when already expired" do
44
+ subject.expires_at = 60.minutes.ago
45
+ subject.expires_in.should == 0
46
+ end
47
+
48
+ it "include expires_in, refresh_token and access token as JSON format" do
49
+ subject.as_json.should == {"expires_in" => subject.expires_in, "access_token" => subject.access_token, "refresh_token" => subject.refresh_token}
50
+ end
51
+
52
+ it "include only expires_in and access token as JSON format if no refresh token set" do
53
+ subject.refresh_token = nil
54
+ subject.as_json.should == {"expires_in" => subject.expires_in, "access_token" => subject.access_token}
55
+ end
56
+
57
+ it "is refreshable, if it has a refresh token" do
58
+ subject.refresh_token = 'abcd1234'
59
+ subject.should be_refreshable
60
+ end
61
+
62
+ it "is not refreshable if it has no refresh token" do
63
+ subject.refresh_token = nil
64
+ subject.should_not be_refreshable
65
+ end
66
+
67
+ it "is not refreshable if it has a refresh token, but its authorization has expired" do
68
+ subject.refresh_token = 'abcd1234'
69
+ subject.authorization.expires_at = 60.minutes.ago
70
+ subject.should_not be_refreshable
71
+ end
72
+ end
73
+
74
+ describe "a new instance" do
75
+ subject do
76
+ OAuth2::Provider.access_token_class.new
77
+ end
78
+
79
+ it "is assigned a randomly generated access token" do
80
+ subject.access_token.should_not be_nil
81
+ OAuth2::Provider.access_token_class.new.access_token.should_not be_nil
82
+ subject.access_token.should_not == OAuth2::Provider.access_token_class.new.access_token
83
+ end
84
+
85
+ it "is assigned a randomly generated refresh token" do
86
+ subject.refresh_token.should_not be_nil
87
+ OAuth2::Provider.access_token_class.new.refresh_token.should_not be_nil
88
+ subject.access_token.should_not == OAuth2::Provider.access_token_class.new.refresh_token
89
+ end
90
+
91
+ it "expires in 1 month by default" do
92
+ subject.expires_at.should == 1.month.from_now
93
+ end
94
+ end
95
+
96
+ describe "refreshing an existing token" do
97
+ subject do
98
+ OAuth2::Provider.access_token_class.create! :authorization => create_authorization, :expires_at => 23.days.ago
99
+ end
100
+
101
+ it "returns a new access token with the same client, resource_owner and scope, but a new expiry time" do
102
+ result = OAuth2::Provider.access_token_class.refresh_with(subject.refresh_token)
103
+ result.should_not be_nil
104
+ result.expires_at.should == 1.month.from_now
105
+ result.authorization.should == subject.authorization
106
+ end
107
+
108
+ it "returns token with expires_at set to authorization.expires_at if validation would fail otherwise" do
109
+ subject.authorization.update_attributes(:expires_at => 5.minutes.from_now)
110
+ result = OAuth2::Provider.access_token_class.refresh_with(subject.refresh_token)
111
+ result.expires_at.should == 5.minutes.from_now
112
+ end
113
+
114
+ it "returns nil if the provided token doesn't match" do
115
+ OAuth2::Provider.access_token_class.refresh_with('wrong').should be_nil
116
+ end
117
+
118
+ it "returns nil if the existing refresh token is nil, whatever value is provided" do
119
+ subject.update_attributes(:refresh_token => nil)
120
+ OAuth2::Provider.access_token_class.refresh_with(nil).should be_nil
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,115 @@
1
+ require 'spec_helper'
2
+
3
+ describe OAuth2::Provider.authorization_code_class do
4
+ describe "any instance" do
5
+ subject do
6
+ OAuth2::Provider.authorization_code_class.new(
7
+ :authorization => create_authorization,
8
+ :redirect_uri => "http://redirect.example.com/callback"
9
+ )
10
+ end
11
+
12
+ it "is valid with an access grant, expiry time, redirect uri and code" do
13
+ subject.should be_valid
14
+ end
15
+
16
+ it "is invalid without a redirect_uri" do
17
+ subject.redirect_uri = nil
18
+ subject.should_not be_valid
19
+ end
20
+
21
+ it "is invalid without a code" do
22
+ subject.code = nil
23
+ subject.should_not be_valid
24
+ end
25
+
26
+ it "is invalid without an access grant" do
27
+ subject.authorization = nil
28
+ subject.should_not be_valid
29
+ end
30
+
31
+ it "is invalid when expires_at isn't set" do
32
+ subject.expires_at = nil
33
+ subject.should_not be_valid
34
+ end
35
+
36
+ it "has expired when expires_at is in the past" do
37
+ subject.expires_at = 1.second.ago
38
+ subject.should be_expired
39
+ end
40
+
41
+ it "has not expired when expires_at is now or in the future" do
42
+ subject.expires_at = Time.now
43
+ subject.should_not be_expired
44
+ end
45
+ end
46
+
47
+ describe "a new instance" do
48
+ subject do
49
+ OAuth2::Provider.authorization_code_class.new
50
+ end
51
+
52
+ it "is assigned a randomly generated code" do
53
+ subject.code.should_not be_nil
54
+ OAuth2::Provider.authorization_code_class.new.code.should_not be_nil
55
+ subject.code.should_not == OAuth2::Provider.authorization_code_class.new.code
56
+ end
57
+
58
+ it "expires in 1 minute by default" do
59
+ subject.expires_at.should == 1.minute.from_now
60
+ end
61
+ end
62
+
63
+ describe "a saved instance" do
64
+ subject do
65
+ OAuth2::Provider.authorization_code_class.create!(
66
+ :authorization => create_authorization,
67
+ :redirect_uri => "https://client.example.com/callback/here"
68
+ )
69
+ end
70
+
71
+ it "can be claimed with the correct code and redirect_uri" do
72
+ OAuth2::Provider.authorization_code_class.claim(subject.code, subject.redirect_uri).should_not be_nil
73
+ end
74
+
75
+ it "returns an access token when claimed" do
76
+ OAuth2::Provider.authorization_code_class.claim(subject.code, subject.redirect_uri).should be_instance_of(OAuth2::Provider.access_token_class)
77
+ end
78
+
79
+ it "can't be claimed twice" do
80
+ OAuth2::Provider.authorization_code_class.claim(subject.code, subject.redirect_uri)
81
+ OAuth2::Provider.authorization_code_class.claim(subject.code, subject.redirect_uri).should be_nil
82
+ end
83
+
84
+ it "can't be claimed without a matching code" do
85
+ OAuth2::Provider.authorization_code_class.claim("incorrectCode", subject.redirect_uri).should be_nil
86
+ end
87
+
88
+ it "can't be claimed without a matching redirect_uri" do
89
+ OAuth2::Provider.authorization_code_class.claim(subject.code, "https://wrong.example.com").should be_nil
90
+ end
91
+
92
+ it "can't be claimed once expired" do
93
+ Timecop.travel subject.expires_at + 1.minute
94
+ OAuth2::Provider.authorization_code_class.claim(subject.code, subject.redirect_uri).should be_nil
95
+ end
96
+ end
97
+
98
+ describe "the access token returned when a code is claimed" do
99
+ subject do
100
+ @code = OAuth2::Provider.authorization_code_class.create!(
101
+ :authorization => create_authorization,
102
+ :redirect_uri => "https://client.example.com/callback/here"
103
+ )
104
+ OAuth2::Provider.authorization_code_class.claim(@code.code, @code.redirect_uri)
105
+ end
106
+
107
+ it "is saved to the database" do
108
+ subject.should_not be_new_record
109
+ end
110
+
111
+ it "has same access grant as claimed code" do
112
+ subject.authorization.should == @code.authorization
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,110 @@
1
+ require 'spec_helper'
2
+
3
+ describe OAuth2::Provider.authorization_class do
4
+ describe "any instance" do
5
+ subject do
6
+ result = OAuth2::Provider.authorization_class.new :client => create_client
7
+ end
8
+
9
+ it "is valid with a client" do
10
+ subject.client.should_not be_nil
11
+ subject.should be_valid
12
+ end
13
+
14
+ it "is invalid without a client" do
15
+ subject.client = nil
16
+ subject.should_not be_valid
17
+ end
18
+
19
+ it "has a given scope, if scope string includes scope" do
20
+ subject.scope = "first second third"
21
+ subject.should have_scope("first")
22
+ subject.should have_scope("second")
23
+ subject.should have_scope("third")
24
+ end
25
+
26
+ it "doesn't have a given scope, if scope string doesn't scope" do
27
+ subject.scope = "first second third"
28
+ subject.should_not have_scope("fourth")
29
+ end
30
+ end
31
+
32
+ describe "a new instance" do
33
+ subject do
34
+ OAuth2::Provider.authorization_class.new
35
+ end
36
+
37
+ it "has no expiry time by default" do
38
+ subject.expires_at.should be_nil
39
+ end
40
+
41
+ it "is never expired" do
42
+ subject.should_not be_expired
43
+ Timecop.travel(100.years.from_now)
44
+ subject.should_not be_expired
45
+ end
46
+ end
47
+
48
+ describe "after being persisted and restored" do
49
+ before :each do
50
+ @client = create_client
51
+ @owner = create_resource_owner
52
+ @original = OAuth2::Provider.authorization_class.create!(:client => @client, :resource_owner => @owner, :expires_at => 1.year.from_now)
53
+ end
54
+
55
+ subject do
56
+ OAuth2::Provider.authorization_class.find(@original.id)
57
+ end
58
+
59
+ it "remembers client" do
60
+ subject.client.should eql(@client)
61
+ end
62
+
63
+ it "remembers resource owner" do
64
+ subject.resource_owner.should eql(@owner)
65
+ end
66
+ end
67
+
68
+ describe "obtain all authorizations for a resource owner" do
69
+ before :each do
70
+ @client = create_client
71
+ @owner = create_resource_owner
72
+ @authorization = OAuth2::Provider.authorization_class.create!(:client => @client, :resource_owner => @owner, :expires_at => 1.year.from_now)
73
+ end
74
+
75
+ subject do
76
+ OAuth2::Provider.authorization_class.all_for(@owner)
77
+ end
78
+
79
+ it "returns correct number of authorizations" do
80
+ subject.count.should eql(1)
81
+ end
82
+
83
+ it "should hold information on the authorized client" do
84
+ subject[0].client.should eql(@client)
85
+ end
86
+ end
87
+
88
+ describe "being revoked" do
89
+ subject do
90
+ OAuth2::Provider.authorization_class.create! :client => create_client
91
+ end
92
+
93
+ it "destroys itself" do
94
+ subject.revoke
95
+ subject.should be_destroyed
96
+ end
97
+
98
+ it "destroys any related authorization codes" do
99
+ subject.authorization_codes.create! :redirect_uri => 'https://example.com'
100
+ subject.revoke
101
+ subject.authorization_codes.should be_empty
102
+ end
103
+
104
+ it "destroys any related access tokens" do
105
+ subject.access_tokens.create!
106
+ subject.revoke
107
+ subject.access_tokens.should be_empty
108
+ end
109
+ end
110
+ end