doorkeeper 0.3.0 → 0.4.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 (176) hide show
  1. data/.gitignore +12 -0
  2. data/.rspec +1 -0
  3. data/.travis.yml +8 -0
  4. data/CHANGELOG.md +98 -0
  5. data/Gemfile +6 -0
  6. data/README.md +42 -6
  7. data/app/controllers/doorkeeper/application_controller.rb +4 -11
  8. data/app/controllers/doorkeeper/applications_controller.rb +7 -1
  9. data/app/controllers/doorkeeper/authorizations_controller.rb +11 -1
  10. data/app/controllers/doorkeeper/authorized_applications_controller.rb +3 -3
  11. data/app/controllers/doorkeeper/tokens_controller.rb +19 -5
  12. data/app/models/doorkeeper/access_grant.rb +28 -0
  13. data/app/models/doorkeeper/access_token.rb +65 -0
  14. data/app/models/doorkeeper/application.rb +54 -0
  15. data/app/views/doorkeeper/applications/index.html.erb +1 -1
  16. data/app/views/doorkeeper/authorizations/error.html.erb +1 -1
  17. data/app/views/doorkeeper/authorizations/new.html.erb +15 -15
  18. data/app/views/doorkeeper/authorized_applications/index.html.erb +1 -2
  19. data/config/locales/en.yml +3 -0
  20. data/doorkeeper.gemspec +28 -0
  21. data/gemfiles/gemfile.rails-3.1.x +7 -0
  22. data/gemfiles/gemfile.rails-3.2.x +7 -0
  23. data/lib/doorkeeper/config.rb +73 -12
  24. data/lib/doorkeeper/doorkeeper_for.rb +19 -15
  25. data/lib/doorkeeper/engine.rb +28 -0
  26. data/lib/doorkeeper/models/scopes.rb +13 -0
  27. data/lib/doorkeeper/oauth/access_token_request.rb +9 -20
  28. data/lib/doorkeeper/oauth/authorization/code.rb +1 -1
  29. data/lib/doorkeeper/oauth/authorization/token.rb +2 -2
  30. data/lib/doorkeeper/oauth/authorization_request.rb +18 -23
  31. data/lib/doorkeeper/oauth/client/credentials.rb +21 -0
  32. data/lib/doorkeeper/oauth/client/methods.rb +18 -0
  33. data/lib/doorkeeper/oauth/client.rb +27 -0
  34. data/lib/doorkeeper/oauth/client_credentials/creator.rb +29 -0
  35. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +35 -0
  36. data/lib/doorkeeper/oauth/client_credentials/response.rb +42 -0
  37. data/lib/doorkeeper/oauth/client_credentials/validation.rb +33 -0
  38. data/lib/doorkeeper/oauth/client_credentials_request.rb +46 -0
  39. data/lib/doorkeeper/oauth/error.rb +9 -0
  40. data/lib/doorkeeper/oauth/error_response.rb +30 -0
  41. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +2 -2
  42. data/lib/doorkeeper/oauth/password_access_token_request.rb +130 -0
  43. data/lib/doorkeeper/oauth/scopes.rb +60 -0
  44. data/lib/doorkeeper/version.rb +1 -1
  45. data/lib/doorkeeper.rb +23 -3
  46. data/lib/generators/doorkeeper/install_generator.rb +1 -0
  47. data/lib/generators/doorkeeper/templates/initializer.rb +12 -7
  48. data/lib/generators/doorkeeper/templates/migration.rb +1 -1
  49. data/lib/generators/doorkeeper/views_generator.rb +15 -0
  50. data/script/rails +6 -0
  51. data/script/run_all +11 -0
  52. data/spec/controllers/applications_controller_spec.rb +18 -0
  53. data/spec/controllers/authorizations_controller_spec.rb +131 -0
  54. data/spec/controllers/protected_resources_controller_spec.rb +308 -0
  55. data/spec/controllers/tokens_controller_spec.rb +34 -0
  56. data/spec/dummy/Rakefile +7 -0
  57. data/spec/dummy/app/assets/javascripts/application.js +9 -0
  58. data/spec/dummy/app/assets/stylesheets/application.css +7 -0
  59. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  60. data/spec/dummy/app/controllers/full_protected_resources_controller.rb +12 -0
  61. data/spec/dummy/app/controllers/home_controller.rb +17 -0
  62. data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +11 -0
  63. data/spec/dummy/app/helpers/application_helper.rb +5 -0
  64. data/spec/dummy/app/models/user.rb +11 -0
  65. data/spec/dummy/app/views/home/index.html.erb +0 -0
  66. data/spec/dummy/app/views/layouts/application.html.erb +16 -0
  67. data/spec/dummy/config/application.rb +53 -0
  68. data/spec/dummy/config/boot.rb +10 -0
  69. data/spec/dummy/config/database.yml +15 -0
  70. data/spec/dummy/config/environment.rb +5 -0
  71. data/spec/dummy/config/environments/development.rb +30 -0
  72. data/spec/dummy/config/environments/production.rb +60 -0
  73. data/spec/dummy/config/environments/test.rb +39 -0
  74. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  75. data/spec/dummy/config/initializers/doorkeeper.rb +41 -0
  76. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  77. data/spec/dummy/config/initializers/session_store.rb +8 -0
  78. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  79. data/spec/dummy/config/locales/doorkeeper.en.yml +5 -0
  80. data/spec/dummy/config/routes.rb +8 -0
  81. data/spec/dummy/config.ru +4 -0
  82. data/spec/dummy/db/migrate/20111122132257_create_users.rb +9 -0
  83. data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +5 -0
  84. data/spec/dummy/db/migrate/20120524202412_create_doorkeeper_tables.rb +42 -0
  85. data/spec/dummy/db/schema.rb +62 -0
  86. data/spec/dummy/public/404.html +26 -0
  87. data/spec/dummy/public/422.html +26 -0
  88. data/spec/dummy/public/500.html +26 -0
  89. data/spec/dummy/public/favicon.ico +0 -0
  90. data/spec/dummy/script/rails +6 -0
  91. data/spec/factories/access_grant.rb +9 -0
  92. data/spec/factories/access_token.rb +7 -0
  93. data/spec/factories/application.rb +6 -0
  94. data/spec/generators/install_generator_spec.rb +35 -0
  95. data/spec/generators/templates/routes.rb +3 -0
  96. data/spec/generators/views_generator_spec.rb +27 -0
  97. data/spec/lib/config_spec.rb +87 -0
  98. data/spec/lib/models/expirable_spec.rb +49 -0
  99. data/spec/lib/models/revocable_spec.rb +31 -0
  100. data/spec/lib/models/scopes_spec.rb +32 -0
  101. data/spec/lib/oauth/access_token_request_spec.rb +240 -0
  102. data/spec/lib/oauth/authorization/uri_builder_spec.rb +37 -0
  103. data/spec/lib/oauth/authorization_request_spec.rb +286 -0
  104. data/spec/lib/oauth/client/credentials_spec.rb +47 -0
  105. data/spec/lib/oauth/client/methods_spec.rb +54 -0
  106. data/spec/lib/oauth/client_credentials/creator_spec.rb +47 -0
  107. data/spec/lib/oauth/client_credentials/issuer_spec.rb +57 -0
  108. data/spec/lib/oauth/client_credentials/response_spec.rb +58 -0
  109. data/spec/lib/oauth/client_credentials/validation_spec.rb +29 -0
  110. data/spec/lib/oauth/client_credentials_integration_spec.rb +27 -0
  111. data/spec/lib/oauth/client_credentials_request_spec.rb +60 -0
  112. data/spec/lib/oauth/client_spec.rb +42 -0
  113. data/spec/lib/oauth/error_response_spec.rb +40 -0
  114. data/spec/lib/oauth/error_spec.rb +19 -0
  115. data/spec/lib/oauth/helpers/scope_checker_spec.rb +74 -0
  116. data/spec/lib/oauth/helpers/unique_token_spec.rb +38 -0
  117. data/spec/lib/oauth/helpers/uri_checker_spec.rb +64 -0
  118. data/spec/lib/oauth/password_access_token_request_spec.rb +152 -0
  119. data/spec/lib/oauth/scopes_spec.rb +115 -0
  120. data/spec/models/doorkeeper/access_grant_spec.rb +36 -0
  121. data/spec/models/doorkeeper/access_token_spec.rb +113 -0
  122. data/spec/models/doorkeeper/application_spec.rb +129 -0
  123. data/spec/requests/applications/applications_request_spec.rb +92 -0
  124. data/spec/requests/applications/authorized_applications_spec.rb +30 -0
  125. data/spec/requests/endpoints/authorization_spec.rb +63 -0
  126. data/spec/requests/endpoints/token_spec.rb +29 -0
  127. data/spec/requests/flows/authorization_code_errors_spec.rb +111 -0
  128. data/spec/requests/flows/authorization_code_spec.rb +125 -0
  129. data/spec/requests/flows/client_credentials_spec.rb +56 -0
  130. data/spec/requests/flows/implicit_grant_errors_spec.rb +31 -0
  131. data/spec/requests/flows/implicit_grant_spec.rb +19 -0
  132. data/spec/requests/flows/password_spec.rb +52 -0
  133. data/spec/requests/flows/refresh_token_spec.rb +66 -0
  134. data/spec/requests/flows/skip_authorization_spec.rb +40 -0
  135. data/spec/requests/protected_resources/private_api_spec.rb +43 -0
  136. data/spec/spec_helper.rb +1 -0
  137. data/spec/spec_helper_integration.rb +28 -0
  138. data/spec/support/dependencies/database_cleaner.rb +16 -0
  139. data/spec/support/dependencies/factory_girl.rb +5 -0
  140. data/spec/support/helpers/access_token_request_helper.rb +11 -0
  141. data/spec/support/helpers/authorization_request_helper.rb +32 -0
  142. data/spec/support/helpers/config_helper.rb +9 -0
  143. data/spec/support/helpers/model_helper.rb +45 -0
  144. data/spec/support/helpers/request_spec_helper.rb +72 -0
  145. data/spec/support/helpers/url_helper.rb +51 -0
  146. data/spec/support/shared/controllers_shared_context.rb +60 -0
  147. data/spec/support/shared/models_shared_examples.rb +44 -0
  148. metadata +163 -57
  149. data/app/controllers/doorkeeper/application_controller.rbc +0 -675
  150. data/app/controllers/doorkeeper/applications_controller.rbc +0 -954
  151. data/app/controllers/doorkeeper/authorizations_controller.rbc +0 -659
  152. data/app/controllers/doorkeeper/authorized_applications_controller.rbc +0 -393
  153. data/app/controllers/doorkeeper/tokens_controller.rbc +0 -423
  154. data/app/helpers/doorkeeper/application_helper.rbc +0 -127
  155. data/app/models/access_grant.rb +0 -31
  156. data/app/models/access_grant.rbc +0 -821
  157. data/app/models/access_token.rb +0 -70
  158. data/app/models/access_token.rbc +0 -979
  159. data/app/models/application.rb +0 -45
  160. data/app/models/application.rbc +0 -753
  161. data/config/initializers/form_errors.rbc +0 -272
  162. data/config/routes.rbc +0 -366
  163. data/lib/doorkeeper/config/scope.rb +0 -11
  164. data/lib/doorkeeper/config/scopes.rb +0 -61
  165. data/lib/doorkeeper/config/scopes_builder.rb +0 -18
  166. data/lib/doorkeeper/config.rbc +0 -1385
  167. data/lib/doorkeeper/doorkeeper_for.rbc +0 -1029
  168. data/lib/doorkeeper/engine.rbc +0 -318
  169. data/lib/doorkeeper/oauth/access_token_request.rbc +0 -2042
  170. data/lib/doorkeeper/oauth/authorization_request.rbc +0 -2272
  171. data/lib/doorkeeper/oauth/random_string.rbc +0 -437
  172. data/lib/doorkeeper/validations.rbc +0 -774
  173. data/lib/doorkeeper/version.rbc +0 -130
  174. data/lib/doorkeeper.rbc +0 -407
  175. data/lib/generators/doorkeeper/install_generator.rbc +0 -453
  176. data/lib/tasks/doorkeeper_tasks.rake.compiled.rbc +0 -40
@@ -0,0 +1,152 @@
1
+ require 'spec_helper_integration'
2
+
3
+ module Doorkeeper::OAuth
4
+ describe PasswordAccessTokenRequest do
5
+ let(:client) { Factory(:application) }
6
+ let(:owner) { User.create!(:name => "Joe", :password => "sekret") }
7
+ let(:params) {
8
+ {
9
+ :grant_type => "password"
10
+ }
11
+ }
12
+
13
+ describe "with a valid owner and client" do
14
+ subject { PasswordAccessTokenRequest.new(client, owner, params) }
15
+
16
+ before { subject.authorize }
17
+
18
+ it { should be_valid }
19
+
20
+ its(:token_type) { should == "bearer" }
21
+ its(:error) { should be_nil }
22
+ its(:refresh_token) { should be_nil }
23
+
24
+ it "has an access token" do
25
+ subject.access_token.token.should =~ /\w+/
26
+ end
27
+ end
28
+
29
+ describe "with a valid client but an invalid owner" do
30
+ subject { PasswordAccessTokenRequest.new(client, nil, params) }
31
+
32
+ before { subject.authorize }
33
+
34
+ it { should_not be_valid }
35
+ its(:error) { should == :invalid_resource_owner }
36
+ its(:access_token) { should be_nil }
37
+ its(:refresh_token) { should be_nil }
38
+ end
39
+
40
+ describe "with a valid owner but an invalid client" do
41
+ subject { PasswordAccessTokenRequest.new(nil, owner, params) }
42
+
43
+ before { subject.authorize }
44
+
45
+ it { should_not be_valid }
46
+ its(:error) { should == :invalid_client }
47
+ its(:access_token) { should be_nil }
48
+ its(:refresh_token) { should be_nil }
49
+ end
50
+
51
+ describe "creating the access token" do
52
+ subject { PasswordAccessTokenRequest.new(client, owner, params) }
53
+
54
+ it "creates with correct params" do
55
+ Doorkeeper::AccessToken.should_receive(:create!).with({
56
+ :application_id => client.id,
57
+ :resource_owner_id => owner.id,
58
+ :expires_in => 2.hours,
59
+ :scopes =>"",
60
+ :use_refresh_token => false,
61
+ })
62
+ subject.authorize
63
+ end
64
+
65
+ it "creates a refresh token if Doorkeeper is configured to do so" do
66
+ Doorkeeper.configure { use_refresh_token }
67
+
68
+ Doorkeeper::AccessToken.should_receive(:create!).with({
69
+ :application_id => client.id,
70
+ :resource_owner_id => owner.id,
71
+ :expires_in => 2.hours,
72
+ :scopes =>"",
73
+ :use_refresh_token => true,
74
+ })
75
+ subject.authorize
76
+ end
77
+ end
78
+
79
+ describe "with an existing valid access token" do
80
+ subject { PasswordAccessTokenRequest.new(client, owner, params) }
81
+
82
+ before { subject.authorize }
83
+ it { should be_valid }
84
+ its(:error) { should be_nil }
85
+
86
+ it "will not create a new token" do
87
+ subject.should_not_receive(:create_access_token)
88
+ subject.authorize
89
+ end
90
+ end
91
+
92
+ describe "with an existing expired access token" do
93
+ subject { PasswordAccessTokenRequest.new(client, owner, params) }
94
+
95
+ it "will create a new token" do
96
+ subject.authorize
97
+ expired_access_token = subject.access_token.dup
98
+ subject.access_token.created_at = Time.now - subject.access_token.expires_in - 1.second
99
+ subject.should_receive(:create_access_token)
100
+ subject.access_token.should_receive(:revoke)
101
+ subject.authorize
102
+ subject.access_token.should_not eq(expired_access_token)
103
+ end
104
+ end
105
+
106
+ describe "finding the current access token" do
107
+ subject { PasswordAccessTokenRequest.new(client, owner, params) }
108
+ it { should be_valid }
109
+ its(:error) { should be_nil }
110
+
111
+ before { subject.authorize }
112
+
113
+ it "should find the access token and not create a new one" do
114
+ subject.should_not_receive(:create_access_token)
115
+ access_token = subject.authorize
116
+ subject.access_token.should eq(access_token)
117
+ end
118
+ end
119
+
120
+ describe "creating the first access_token" do
121
+ subject { PasswordAccessTokenRequest.new(client, owner, params) }
122
+ it { should be_valid }
123
+ its(:error) { should be_nil }
124
+
125
+ it "should create a new access token" do
126
+ subject.should_receive(:create_access_token)
127
+ subject.authorize
128
+ end
129
+ end
130
+
131
+ describe "with errors" do
132
+ def token(params)
133
+ PasswordAccessTokenRequest.new(client, owner, params)
134
+ end
135
+
136
+ it "includes the error in the response" do
137
+ access_token = token(params.except(:grant_type))
138
+ access_token.error_response.name.should == :invalid_request
139
+ end
140
+
141
+ describe "when client is not present" do
142
+ subject { PasswordAccessTokenRequest.new(nil, owner, params) }
143
+ its(:error) { should == :invalid_client }
144
+ end
145
+
146
+ describe "when :grant_type is not 'password'" do
147
+ subject { token(params.merge(:grant_type => "invalid")) }
148
+ its(:error) { should == :unsupported_grant_type }
149
+ end
150
+ end
151
+ end
152
+ end
@@ -0,0 +1,115 @@
1
+ require 'spec_helper'
2
+ require 'active_support/core_ext/module/delegation'
3
+ require 'active_support/core_ext/string'
4
+ require 'doorkeeper/oauth/scopes'
5
+
6
+ module Doorkeeper::OAuth
7
+ describe Scopes do
8
+ describe :add do
9
+ it 'allows you to add scopes with symbols' do
10
+ subject.add :public
11
+ subject.all.should == [:public]
12
+ end
13
+
14
+ it 'allows you to add scopes with strings' do
15
+ subject.add "public"
16
+ subject.all.should == [:public]
17
+ end
18
+
19
+ it 'do not add already included scopes' do
20
+ subject.add :public
21
+ subject.add :public
22
+ subject.all.should == [:public]
23
+ end
24
+ end
25
+
26
+ describe :exists do
27
+ before do
28
+ subject.add :public
29
+ end
30
+
31
+ it 'returns true if scope with given name is present' do
32
+ subject.exists?("public").should be_true
33
+ end
34
+
35
+ it 'returns false if scope with given name does not exist' do
36
+ subject.exists?("other").should be_false
37
+ end
38
+
39
+ it 'handles symbols' do
40
+ subject.exists?(:public).should be_true
41
+ subject.exists?(:other).should be_false
42
+ end
43
+ end
44
+
45
+ describe ".from_string" do
46
+ let(:string) { "public write" }
47
+
48
+ subject { Scopes.from_string(string) }
49
+
50
+ it { should be_a(Scopes) }
51
+ its(:all) { should == [:public, :write] }
52
+ end
53
+
54
+ describe :+ do
55
+ it "can add to another scope object" do
56
+ scopes = Scopes.from_string("public") + Scopes.from_string("admin")
57
+ scopes.all.should == [:public, :admin]
58
+ end
59
+
60
+ it "does not change the existing object" do
61
+ origin = Scopes.from_string("public")
62
+ new_scope = origin + Scopes.from_string("admin")
63
+ origin.to_s.should == "public"
64
+ end
65
+
66
+ it "raises an error if cannot handle addition" do
67
+ expect {
68
+ Scopes.from_string("public") + "admin"
69
+ }.to raise_error(NoMethodError)
70
+ end
71
+ end
72
+
73
+ describe :== do
74
+ it 'is equal to another set of scopes' do
75
+ Scopes.from_string("public").should == Scopes.from_string("public")
76
+ end
77
+
78
+ it 'is equal to another set of scopes with no particular order' do
79
+ Scopes.from_string("public write").should == Scopes.from_string("write public")
80
+ end
81
+
82
+ it 'differs from another set of scopes when scopes are not the same' do
83
+ Scopes.from_string("public write").should_not == Scopes.from_string("write")
84
+ end
85
+ end
86
+
87
+ describe :has_scopes? do
88
+ subject { Scopes.from_string("public admin") }
89
+
90
+ it "returns true when at least one scope is included" do
91
+ subject.has_scopes?(Scopes.from_string("public")).should be_true
92
+ end
93
+
94
+ it "returns true when all scopes are included" do
95
+ subject.has_scopes?(Scopes.from_string("public admin")).should be_true
96
+ end
97
+
98
+ it "is true if all scopes are included in any order" do
99
+ subject.has_scopes?(Scopes.from_string("admin public")).should be_true
100
+ end
101
+
102
+ it "is false if no scopes are included" do
103
+ subject.has_scopes?(Scopes.from_string("notexistent")).should be_false
104
+ end
105
+
106
+ it "returns false when any scope is not included" do
107
+ subject.has_scopes?(Scopes.from_string("public nope")).should be_false
108
+ end
109
+
110
+ it "is false if no scopes are included even for existing ones" do
111
+ subject.has_scopes?(Scopes.from_string("public admin notexistent")).should be_false
112
+ end
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,36 @@
1
+ require 'spec_helper_integration'
2
+
3
+ describe Doorkeeper::AccessGrant do
4
+ subject { FactoryGirl.build(:access_grant) }
5
+
6
+ it { should be_valid }
7
+
8
+ it_behaves_like "an accessible token"
9
+ it_behaves_like "a revocable token"
10
+ it_behaves_like "an unique token" do
11
+ let(:factory_name) { :access_grant }
12
+ end
13
+
14
+ describe "validations" do
15
+ it "is invalid without resource_owner_id" do
16
+ subject.resource_owner_id = nil
17
+ should_not be_valid
18
+ end
19
+
20
+ it "is invalid without application_id" do
21
+ subject.application_id = nil
22
+ should_not be_valid
23
+ end
24
+
25
+ it "is invalid without token" do
26
+ subject.save
27
+ subject.token = nil
28
+ should_not be_valid
29
+ end
30
+
31
+ it "is invalid without expires_in" do
32
+ subject.expires_in = nil
33
+ should_not be_valid
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,113 @@
1
+ require 'spec_helper_integration'
2
+
3
+ module Doorkeeper
4
+ describe AccessToken do
5
+ subject { FactoryGirl.build(:access_token) }
6
+
7
+ it { should be_valid }
8
+
9
+ it_behaves_like "an accessible token"
10
+ it_behaves_like "a revocable token"
11
+ it_behaves_like "an unique token" do
12
+ let(:factory_name) { :access_token }
13
+ end
14
+
15
+ describe "validations" do
16
+ it "is valid without resource_owner_id" do
17
+ # For client credentials flow
18
+ subject.resource_owner_id = nil
19
+ should be_valid
20
+ end
21
+
22
+ it "is invalid without application_id" do
23
+ subject.application_id = nil
24
+ should_not be_valid
25
+ end
26
+ end
27
+
28
+ describe '.revoke_all_for' do
29
+ let(:resource_owner) { stub(:id => 100) }
30
+ let(:application) { FactoryGirl.create :application }
31
+ let(:default_attributes) do
32
+ { :application => application, :resource_owner_id => resource_owner.id }
33
+ end
34
+
35
+ it 'revokes all tokens for given application and resource owner' do
36
+ FactoryGirl.create :access_token, default_attributes
37
+ AccessToken.revoke_all_for application.id, resource_owner
38
+ AccessToken.all.should be_empty
39
+ end
40
+
41
+ it 'matches application' do
42
+ FactoryGirl.create :access_token, default_attributes.merge(:application => FactoryGirl.create(:application))
43
+ AccessToken.revoke_all_for application.id, resource_owner
44
+ AccessToken.all.should_not be_empty
45
+ end
46
+
47
+ it 'matches resource owner' do
48
+ FactoryGirl.create :access_token, default_attributes.merge(:resource_owner_id => 90)
49
+ AccessToken.revoke_all_for application.id, resource_owner
50
+ AccessToken.all.should_not be_empty
51
+ end
52
+ end
53
+
54
+ describe '.matching_token_for' do
55
+ let(:resource_owner_id) { 100 }
56
+ let(:application) { FactoryGirl.create :application }
57
+ let(:scopes) { Doorkeeper::OAuth::Scopes.from_string("public write") }
58
+ let(:default_attributes) do
59
+ { :application => application, :resource_owner_id => resource_owner_id, :scopes => scopes.to_s }
60
+ end
61
+
62
+ it 'returns only one token' do
63
+ token = FactoryGirl.create :access_token, default_attributes
64
+ last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
65
+ last_token.should == token
66
+ end
67
+
68
+ it 'accepts resource owner as object' do
69
+ resource_owner = stub(:kind_of? => true, :id => 100)
70
+ token = FactoryGirl.create :access_token, default_attributes
71
+ last_token = AccessToken.matching_token_for(application, resource_owner, scopes)
72
+ last_token.should == token
73
+ end
74
+
75
+ it 'accepts nil as resource owner' do
76
+ token = FactoryGirl.create :access_token, default_attributes.merge(:resource_owner_id => nil)
77
+ last_token = AccessToken.matching_token_for(application, nil, scopes)
78
+ last_token.should == token
79
+ end
80
+
81
+ it 'excludes revoked tokens' do
82
+ FactoryGirl.create :access_token, default_attributes.merge(:revoked_at => 1.day.ago)
83
+ last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
84
+ last_token.should be_nil
85
+ end
86
+
87
+ it 'matches the application' do
88
+ token = FactoryGirl.create :access_token, default_attributes.merge(:application => FactoryGirl.create(:application))
89
+ last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
90
+ last_token.should be_nil
91
+ end
92
+
93
+ it 'matches the resource owner' do
94
+ FactoryGirl.create :access_token, default_attributes.merge(:resource_owner_id => 2)
95
+ last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
96
+ last_token.should be_nil
97
+ end
98
+
99
+ it 'matches the scopes' do
100
+ FactoryGirl.create :access_token, default_attributes.merge(:scopes => 'public email')
101
+ last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
102
+ last_token.should be_nil
103
+ end
104
+
105
+ it 'returns the last created token' do
106
+ FactoryGirl.create :access_token, default_attributes.merge(:created_at => 1.day.ago)
107
+ token = FactoryGirl.create :access_token, default_attributes
108
+ last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
109
+ last_token.should == token
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,129 @@
1
+ require 'spec_helper_integration'
2
+
3
+ module Doorkeeper
4
+ describe Application do
5
+ let(:new_application) { FactoryGirl.build(:application) }
6
+
7
+ it 'is valid given valid attributes' do
8
+ new_application.should be_valid
9
+ end
10
+
11
+ it 'is invalid without a name' do
12
+ new_application.name = nil
13
+ new_application.should_not be_valid
14
+ end
15
+
16
+ it 'generates uid on create' do
17
+ new_application.uid.should be_nil
18
+ new_application.save
19
+ new_application.uid.should_not be_nil
20
+ end
21
+
22
+ it 'is invalid without uid' do
23
+ new_application.save
24
+ new_application.uid = nil
25
+ new_application.should_not be_valid
26
+ end
27
+
28
+ it 'is invalid without redirect_uri' do
29
+ new_application.save
30
+ new_application.redirect_uri = nil
31
+ new_application.should_not be_valid
32
+ end
33
+
34
+ it 'is invalid with a redirect_uri that is relative' do
35
+ new_application.save
36
+ new_application.redirect_uri = "/abcd"
37
+ new_application.should_not be_valid
38
+ end
39
+
40
+ it 'is invalid with a redirect_uri that has a fragment' do
41
+ new_application.save
42
+ new_application.redirect_uri = "http://example.com/abcd#xyz"
43
+ new_application.should_not be_valid
44
+ end
45
+
46
+ it 'is invalid with a redirect_uri that has a query parameter' do
47
+ new_application.save
48
+ new_application.redirect_uri = "http://example.com/abcd?xyz=123"
49
+ new_application.should_not be_valid
50
+ end
51
+
52
+ it 'checks uniqueness of uid' do
53
+ app1 = FactoryGirl.create(:application)
54
+ app2 = FactoryGirl.create(:application)
55
+ app2.uid = app1.uid
56
+ app2.should_not be_valid
57
+ end
58
+
59
+ it 'generate secret on create' do
60
+ new_application.secret.should be_nil
61
+ new_application.save
62
+ new_application.secret.should_not be_nil
63
+ end
64
+
65
+ it 'is invalid without secret' do
66
+ new_application.save
67
+ new_application.secret = nil
68
+ new_application.should_not be_valid
69
+ end
70
+
71
+ describe 'destroy related models on cascade' do
72
+ before(:each) do
73
+ new_application.save
74
+ end
75
+
76
+ it 'should destroy its access grants' do
77
+ FactoryGirl.create(:access_grant, :application => new_application)
78
+ expect { new_application.destroy }.to change { Doorkeeper::AccessGrant.count }.by(-1)
79
+ end
80
+
81
+ it 'should destroy its access tokens' do
82
+ FactoryGirl.create(:access_token, :application => new_application)
83
+ FactoryGirl.create(:access_token, :application => new_application, :revoked_at => Time.now)
84
+ expect { new_application.destroy }.to change { Doorkeeper::AccessToken.count }.by(-2)
85
+ end
86
+ end
87
+
88
+ describe :authorized_for do
89
+ let(:resource_owner) { double(:resource_owner, :id => 10) }
90
+
91
+ it "is empty if the application is not authorized for anyone" do
92
+ Application.authorized_for(resource_owner).should be_empty
93
+ end
94
+
95
+ it "returns only application for a specific resource owner" do
96
+ FactoryGirl.create(:access_token, :resource_owner_id => resource_owner.id + 1)
97
+ token = FactoryGirl.create(:access_token, :resource_owner_id => resource_owner.id)
98
+ Application.authorized_for(resource_owner).should == [token.application]
99
+ end
100
+
101
+ it "excludes revoked tokens" do
102
+ FactoryGirl.create(:access_token, :resource_owner_id => resource_owner.id, :revoked_at => 2.days.ago)
103
+ Application.authorized_for(resource_owner).should be_empty
104
+ end
105
+
106
+ it "returns all applications that have been authorized" do
107
+ token1 = FactoryGirl.create(:access_token, :resource_owner_id => resource_owner.id)
108
+ token2 = FactoryGirl.create(:access_token, :resource_owner_id => resource_owner.id)
109
+ Application.authorized_for(resource_owner).should == [token1.application, token2.application]
110
+ end
111
+
112
+ it "returns only one application even if it has been authorized twice" do
113
+ application = FactoryGirl.create(:application)
114
+ FactoryGirl.create(:access_token, :resource_owner_id => resource_owner.id, :application => application)
115
+ FactoryGirl.create(:access_token, :resource_owner_id => resource_owner.id, :application => application)
116
+ Application.authorized_for(resource_owner).should == [application]
117
+ end
118
+
119
+ it "should fail to mass assign a new application" do
120
+ mass_assign = { :name => 'Something',
121
+ :redirect_uri => 'http://somewhere.com/something',
122
+ :uid => 123,
123
+ :secret => 'something' }
124
+ Application.create(mass_assign).uid.should_not == 123
125
+ end
126
+
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,92 @@
1
+ require 'spec_helper_integration'
2
+
3
+ feature 'Adding applications' do
4
+ context 'in application form' do
5
+ background do
6
+ visit '/oauth/applications/new'
7
+ end
8
+
9
+ scenario 'adding a valid app' do
10
+ fill_in 'Name', :with => 'My Application'
11
+ fill_in 'Redirect uri', :with => 'http://example.com'
12
+ click_button 'Submit'
13
+ i_should_see 'Application created'
14
+ i_should_see 'My Application'
15
+ end
16
+
17
+ scenario 'adding invalid app' do
18
+ click_button 'Submit'
19
+ i_should_see 'Whoops! Check your form for possible errors'
20
+ end
21
+ end
22
+ end
23
+
24
+ feature 'Listing applications' do
25
+ background do
26
+ FactoryGirl.create :application, :name => 'Oauth Dude'
27
+ FactoryGirl.create :application, :name => 'Awesome App'
28
+ end
29
+
30
+ scenario 'application list' do
31
+ visit '/oauth/applications'
32
+ i_should_see 'Awesome App'
33
+ i_should_see 'Oauth Dude'
34
+ end
35
+ end
36
+
37
+ feature 'Show application' do
38
+ let :app do
39
+ FactoryGirl.create :application, :name => 'Just another oauth app'
40
+ end
41
+
42
+ scenario 'visiting application page' do
43
+ visit "/oauth/applications/#{app.id}"
44
+ i_should_see 'Just another oauth app'
45
+ end
46
+ end
47
+
48
+ feature 'Edit application' do
49
+ let :app do
50
+ FactoryGirl.create :application, :name => 'OMG my app'
51
+ end
52
+
53
+ background do
54
+ visit "/oauth/applications/#{app.id}/edit"
55
+ end
56
+
57
+ scenario 'updating a valid app' do
58
+ fill_in :name, :with => "Serious app"
59
+ click_button 'Submit'
60
+ i_should_see "Application updated"
61
+ i_should_see "Serious app"
62
+ i_should_not_see "OMG my app"
63
+ end
64
+
65
+ scenario 'updating an invalid app' do
66
+ fill_in :name, :with => ""
67
+ click_button 'Submit'
68
+ i_should_see 'Whoops! Check your form for possible errors'
69
+ end
70
+ end
71
+
72
+ feature 'Destroy application' do
73
+ background do
74
+ @app = FactoryGirl.create :application
75
+ end
76
+
77
+ scenario 'deleting an application from list' do
78
+ visit "/oauth/applications"
79
+ i_should_see @app.name
80
+ within(:css, "tr#application_#{@app.id}") do
81
+ click_link "Destroy"
82
+ end
83
+ i_should_see "Application deleted"
84
+ i_should_not_see @app.name
85
+ end
86
+
87
+ scenario 'deleting an application from show' do
88
+ visit "/oauth/applications/#{@app.id}"
89
+ click_link 'Remove'
90
+ i_should_see "Application deleted"
91
+ end
92
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper_integration'
2
+
3
+ feature 'Authorized applications' do
4
+ background do
5
+ @user = User.create!(:name => "Joe", :password => "sekret")
6
+ @client = client_exists(:name => "Amazing Client App")
7
+ resource_owner_is_authenticated @user
8
+ client_is_authorized @client, @user
9
+ end
10
+
11
+ scenario "display user's authorized applications" do
12
+ visit '/oauth/authorized_applications'
13
+ i_should_see 'Amazing Client App'
14
+ end
15
+
16
+ scenario "do not display other user's authorized applications" do
17
+ client = client_exists(:name => "Another Client App")
18
+ client_is_authorized client, User.create!(:name => "Joe", :password => "sekret")
19
+ visit '/oauth/authorized_applications'
20
+ i_should_not_see 'Another Client App'
21
+ end
22
+
23
+ scenario "user revoke access to application" do
24
+ visit '/oauth/authorized_applications'
25
+ i_should_see 'Amazing Client App'
26
+ click_on 'Revoke'
27
+ i_should_see 'Application revoked'
28
+ i_should_not_see 'Amazing Client App'
29
+ end
30
+ end