doorkeeper 1.4.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of doorkeeper might be problematic. Click here for more details.

Files changed (127) hide show
  1. checksums.yaml +4 -4
  2. data/.hound.yml +3 -0
  3. data/.travis.yml +38 -10
  4. data/CHANGELOG.md +43 -1
  5. data/CONTRIBUTING.md +35 -0
  6. data/Gemfile +4 -26
  7. data/README.md +21 -55
  8. data/Rakefile +3 -1
  9. data/app/controllers/doorkeeper/application_controller.rb +2 -2
  10. data/app/controllers/doorkeeper/applications_controller.rb +4 -5
  11. data/app/controllers/doorkeeper/authorizations_controller.rb +4 -2
  12. data/app/controllers/doorkeeper/tokens_controller.rb +2 -2
  13. data/app/helpers/doorkeeper/{form_errors_helper.rb → dashboard_helper.rb} +5 -1
  14. data/app/validators/redirect_uri_validator.rb +6 -0
  15. data/app/views/doorkeeper/applications/_delete_form.html.erb +1 -1
  16. data/app/views/doorkeeper/applications/_form.html.erb +3 -3
  17. data/app/views/doorkeeper/applications/index.html.erb +1 -1
  18. data/config/locales/en.yml +6 -3
  19. data/doorkeeper.gemspec +3 -3
  20. data/gemfiles/Gemfile.common.rb +11 -0
  21. data/gemfiles/Gemfile.mongo_mapper.rb +5 -0
  22. data/gemfiles/Gemfile.mongoid2.rb +5 -0
  23. data/gemfiles/Gemfile.mongoid3.rb +4 -0
  24. data/gemfiles/Gemfile.mongoid4.rb +5 -0
  25. data/lib/doorkeeper/config.rb +34 -24
  26. data/lib/doorkeeper/engine.rb +1 -2
  27. data/lib/doorkeeper/generators/doorkeeper/mongo_mapper/indexes_generator.rb +12 -0
  28. data/lib/doorkeeper/models/access_grant_mixin.rb +36 -0
  29. data/lib/doorkeeper/models/access_token_mixin.rb +122 -0
  30. data/lib/doorkeeper/models/application_mixin.rb +60 -0
  31. data/lib/doorkeeper/models/{expirable.rb → concerns/expirable.rb} +6 -5
  32. data/lib/doorkeeper/models/{ownership.rb → concerns/ownership.rb} +7 -7
  33. data/lib/doorkeeper/models/{revocable.rb → concerns/revocable.rb} +1 -1
  34. data/lib/doorkeeper/models/concerns/scopes.rb +17 -0
  35. data/lib/doorkeeper/oauth/authorization/token.rb +6 -6
  36. data/lib/doorkeeper/oauth/client.rb +1 -1
  37. data/lib/doorkeeper/oauth/password_access_token_request.rb +3 -3
  38. data/lib/doorkeeper/oauth/pre_authorization.rb +5 -1
  39. data/lib/doorkeeper/oauth/refresh_token_request.rb +6 -6
  40. data/lib/doorkeeper/oauth/scopes.rb +6 -1
  41. data/lib/doorkeeper/oauth/token.rb +3 -2
  42. data/lib/doorkeeper/orm/active_record/access_grant.rb +7 -0
  43. data/lib/doorkeeper/orm/active_record/access_token.rb +21 -0
  44. data/lib/doorkeeper/{models → orm}/active_record/application.rb +1 -3
  45. data/lib/doorkeeper/orm/active_record.rb +17 -0
  46. data/lib/doorkeeper/{models → orm}/mongo_mapper/access_grant.rb +4 -5
  47. data/lib/doorkeeper/{models → orm}/mongo_mapper/access_token.rb +12 -17
  48. data/lib/doorkeeper/{models → orm}/mongo_mapper/application.rb +3 -4
  49. data/lib/doorkeeper/orm/mongo_mapper.rb +11 -0
  50. data/lib/doorkeeper/{models → orm}/mongoid2/access_grant.rb +5 -3
  51. data/lib/doorkeeper/{models → orm}/mongoid2/access_token.rb +10 -12
  52. data/lib/doorkeeper/{models → orm}/mongoid2/application.rb +3 -0
  53. data/lib/doorkeeper/orm/mongoid2/concerns/scopes.rb +30 -0
  54. data/lib/doorkeeper/orm/mongoid2.rb +11 -0
  55. data/lib/doorkeeper/orm/mongoid3/access_grant.rb +22 -0
  56. data/lib/doorkeeper/orm/mongoid3/access_token.rb +37 -0
  57. data/lib/doorkeeper/{models/mongoid3_4 → orm/mongoid3}/application.rb +3 -0
  58. data/lib/doorkeeper/orm/mongoid3/concerns/scopes.rb +30 -0
  59. data/lib/doorkeeper/orm/mongoid3.rb +11 -0
  60. data/lib/doorkeeper/orm/mongoid4/access_grant.rb +22 -0
  61. data/lib/doorkeeper/orm/mongoid4/access_token.rb +37 -0
  62. data/lib/doorkeeper/orm/mongoid4/application.rb +25 -0
  63. data/lib/doorkeeper/orm/mongoid4/concerns/scopes.rb +17 -0
  64. data/lib/doorkeeper/orm/mongoid4.rb +11 -0
  65. data/lib/doorkeeper/rails/helpers.rb +63 -0
  66. data/lib/doorkeeper/rails/routes.rb +1 -12
  67. data/lib/doorkeeper/request/code.rb +0 -1
  68. data/lib/doorkeeper/request/token.rb +0 -1
  69. data/lib/doorkeeper/server.rb +1 -1
  70. data/lib/doorkeeper/version.rb +1 -1
  71. data/lib/doorkeeper.rb +15 -6
  72. data/lib/generators/doorkeeper/application_owner_generator.rb +4 -1
  73. data/lib/generators/doorkeeper/application_scopes_generator.rb +34 -0
  74. data/lib/generators/doorkeeper/templates/add_scopes_to_oauth_applications.rb +5 -0
  75. data/lib/generators/doorkeeper/templates/initializer.rb +8 -1
  76. data/lib/generators/doorkeeper/templates/migration.rb +1 -0
  77. data/lib/generators/doorkeeper/views_generator.rb +4 -5
  78. data/spec/controllers/applications_controller_spec.rb +7 -7
  79. data/spec/controllers/protected_resources_controller_spec.rb +25 -175
  80. data/spec/controllers/tokens_controller_spec.rb +15 -9
  81. data/spec/dummy/app/controllers/full_protected_resources_controller.rb +2 -2
  82. data/spec/dummy/app/controllers/metal_controller.rb +2 -2
  83. data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +2 -2
  84. data/spec/dummy/app/models/user.rb +5 -5
  85. data/spec/dummy/config/application.rb +3 -1
  86. data/spec/dummy/config/boot.rb +4 -1
  87. data/spec/dummy/db/development.sqlite3 +0 -0
  88. data/spec/dummy/db/migrate/20141209001746_add_scopes_to_oauth_applications.rb +5 -0
  89. data/spec/dummy/db/schema.rb +41 -40
  90. data/spec/factories.rb +24 -0
  91. data/spec/lib/config_spec.rb +30 -10
  92. data/spec/lib/models/expirable_spec.rb +1 -1
  93. data/spec/lib/models/revocable_spec.rb +8 -3
  94. data/spec/lib/models/scopes_spec.rb +3 -3
  95. data/spec/lib/oauth/client_spec.rb +1 -1
  96. data/spec/lib/oauth/password_access_token_request_spec.rb +1 -1
  97. data/spec/lib/oauth/pre_authorization_spec.rb +43 -9
  98. data/spec/lib/oauth/token_request_spec.rb +28 -1
  99. data/spec/lib/oauth/token_spec.rb +1 -1
  100. data/spec/models/doorkeeper/application_spec.rb +16 -1
  101. data/spec/requests/applications/applications_request_spec.rb +6 -4
  102. data/spec/requests/flows/implicit_grant_spec.rb +32 -0
  103. data/spec/requests/flows/refresh_token_spec.rb +12 -3
  104. data/spec/spec_helper_integration.rb +8 -2
  105. data/spec/support/shared/controllers_shared_context.rb +2 -2
  106. data/spec/validators/redirect_uri_validator_spec.rb +30 -3
  107. metadata +52 -39
  108. data/lib/doorkeeper/doorkeeper_for.rb +0 -69
  109. data/lib/doorkeeper/helpers/filter.rb +0 -64
  110. data/lib/doorkeeper/models/access_grant.rb +0 -30
  111. data/lib/doorkeeper/models/access_token.rb +0 -106
  112. data/lib/doorkeeper/models/active_record/access_grant.rb +0 -9
  113. data/lib/doorkeeper/models/active_record/access_token.rb +0 -25
  114. data/lib/doorkeeper/models/application.rb +0 -40
  115. data/lib/doorkeeper/models/mongoid/scopes.rb +0 -15
  116. data/lib/doorkeeper/models/mongoid/version.rb +0 -15
  117. data/lib/doorkeeper/models/mongoid3_4/access_grant.rb +0 -27
  118. data/lib/doorkeeper/models/mongoid3_4/access_token.rb +0 -46
  119. data/lib/doorkeeper/models/scopes.rb +0 -21
  120. data/lib/generators/doorkeeper/mongo_mapper/indexes_generator.rb +0 -12
  121. data/script/rails +0 -5
  122. data/script/run_all +0 -14
  123. data/spec/factories/access_grant.rb +0 -9
  124. data/spec/factories/access_token.rb +0 -11
  125. data/spec/factories/application.rb +0 -6
  126. /data/lib/{generators/doorkeeper → doorkeeper/generators/doorkeeper/mongo_mapper}/templates/indexes.rb +0 -0
  127. /data/lib/doorkeeper/models/{accessible.rb → concerns/accessible.rb} +0 -0
@@ -8,6 +8,7 @@ module Doorkeeper
8
8
  def self.configure(&block)
9
9
  @config = Config::Builder.new(&block).build
10
10
  enable_orm
11
+ check_for_missing_columns
11
12
  setup_application_owner if @config.enable_application_owner?
12
13
  end
13
14
 
@@ -15,26 +16,42 @@ module Doorkeeper
15
16
  @config || (fail MissingConfiguration.new)
16
17
  end
17
18
 
18
- def self.orm_model_dir
19
- case configuration.orm
20
- when :mongoid3, :mongoid4
21
- 'mongoid3_4'
22
- else
23
- configuration.orm
19
+ def self.check_for_missing_columns
20
+ if Doorkeeper.configuration.orm == :active_record &&
21
+ !Application.new.attributes.include?("scopes")
22
+
23
+ puts <<-MSG.squish
24
+ [doorkeeper] Missing column: `applications.scopes`.
25
+ If you are using ActiveRecord run `rails generate doorkeeper:application_scopes
26
+ && rake db:migrate` to add it.
27
+ MSG
24
28
  end
29
+ rescue ActiveRecord::StatementInvalid
30
+ # trap error when DB is not yet setup
25
31
  end
26
32
 
27
33
  def self.enable_orm
28
- require "doorkeeper/models/#{orm_model_dir}/access_grant"
29
- require "doorkeeper/models/#{orm_model_dir}/access_token"
30
- require "doorkeeper/models/#{orm_model_dir}/application"
31
- require 'doorkeeper/models/access_grant'
32
- require 'doorkeeper/models/access_token'
33
- require 'doorkeeper/models/application'
34
+ class_name = "doorkeeper/orm/#{configuration.orm}".classify
35
+ class_name.constantize.initialize_models!
36
+ rescue NameError => e
37
+ if e.instance_of?(NameError)
38
+ fail e, "ORM adapter not found (#{configuration.orm})", <<-error_msg
39
+ [doorkeeper] ORM adapter not found (#{configuration.orm}), or there was an error
40
+ trying to load it.
41
+
42
+ You probably need to add the related gem for this adapter to work with
43
+ doorkeeper.
44
+
45
+ If you are working on the adapter itself, double check that the constant exists,
46
+ and that your `initialize_models!` method doesn't raise any errors.\n
47
+ error_msg
48
+ else
49
+ raise e
50
+ end
34
51
  end
35
52
 
36
53
  def self.setup_application_owner
37
- require File.join(File.dirname(__FILE__), 'models', 'ownership')
54
+ require File.join(File.dirname(__FILE__), 'models', 'concerns', 'ownership')
38
55
  Application.send :include, Models::Ownership
39
56
  end
40
57
 
@@ -86,12 +103,8 @@ module Doorkeeper
86
103
  @config.instance_variable_set("@reuse_access_token", true)
87
104
  end
88
105
 
89
- def test_redirect_uri(uri)
90
- warn <<-TEXT
91
- DEPRECATION: test_redirect_uri has renamed to native_redirect_uri. use "native_redirect_uri '#{uri}'".
92
- TEXT
93
-
94
- @config.instance_variable_set('@native_redirect_uri', uri)
106
+ def force_ssl_in_redirect_uri(boolean)
107
+ @config.instance_variable_set("@force_ssl_in_redirect_uri", boolean)
95
108
  end
96
109
  end
97
110
 
@@ -180,6 +193,7 @@ module Doorkeeper
180
193
  option :active_record_options, default: {}
181
194
  option :realm, default: 'Doorkeeper'
182
195
  option :wildcard_redirect_uri, default: false
196
+ option :force_ssl_in_redirect_uri, default: !Rails.env.development?
183
197
  option :grant_flows,
184
198
  default: %w(authorization_code implicit password client_credentials)
185
199
 
@@ -209,10 +223,6 @@ module Doorkeeper
209
223
  @scopes ||= default_scopes + optional_scopes
210
224
  end
211
225
 
212
- def orm_name
213
- [:mongoid2, :mongoid3, :mongoid4].include?(orm) ? :mongoid : orm
214
- end
215
-
216
226
  def client_credentials_methods
217
227
  @client_credentials ||= [:from_basic, :from_params]
218
228
  end
@@ -233,7 +243,7 @@ module Doorkeeper
233
243
  @token_grant_types ||= calculate_token_grant_types
234
244
  end
235
245
 
236
- private
246
+ private
237
247
 
238
248
  # Determines what values are acceptable for 'response_type' param in
239
249
  # authorization request endpoint, and return them as an array of strings.
@@ -1,13 +1,12 @@
1
1
  module Doorkeeper
2
2
  class Engine < Rails::Engine
3
3
  initializer 'doorkeeper.routes' do
4
- Doorkeeper::Rails::Routes.warn_if_using_mount_method!
5
4
  Doorkeeper::Rails::Routes.install!
6
5
  end
7
6
 
8
7
  initializer 'doorkeeper.helpers' do
9
8
  ActiveSupport.on_load(:action_controller) do
10
- include Doorkeeper::Helpers::Filter
9
+ include Doorkeeper::Rails::Helpers
11
10
  end
12
11
  end
13
12
  end
@@ -0,0 +1,12 @@
1
+ module Doorkeeper
2
+ module MongoMapper
3
+ class IndexesGenerator < ::Rails::Generators::Base
4
+ source_root File.expand_path('templates', __FILE__)
5
+ desc "'Creates an indexes file for use with MongoMapper's rake db:index'"
6
+
7
+ def install
8
+ template 'indexes.rb', 'db/indexes.rb'
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,36 @@
1
+ module Doorkeeper
2
+ module AccessGrantMixin
3
+ extend ActiveSupport::Concern
4
+
5
+ include OAuth::Helpers
6
+ include Models::Expirable
7
+ include Models::Revocable
8
+ include Models::Accessible
9
+ include Models::Scopes
10
+
11
+ included do
12
+ belongs_to :application, class_name: 'Doorkeeper::Application', inverse_of: :access_grants
13
+
14
+ if ::Rails.version.to_i < 4 || defined?(::ProtectedAttributes)
15
+ attr_accessible :resource_owner_id, :application_id, :expires_in, :redirect_uri, :scopes
16
+ end
17
+
18
+ validates :resource_owner_id, :application_id, :token, :expires_in, :redirect_uri, presence: true
19
+ validates :token, uniqueness: true
20
+
21
+ before_validation :generate_token, on: :create
22
+ end
23
+
24
+ module ClassMethods
25
+ def by_token(token)
26
+ where(token: token).limit(1).to_a.first
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ def generate_token
33
+ self.token = UniqueToken.generate
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,122 @@
1
+ module Doorkeeper
2
+ module AccessTokenMixin
3
+ extend ActiveSupport::Concern
4
+
5
+ include OAuth::Helpers
6
+ include Models::Expirable
7
+ include Models::Revocable
8
+ include Models::Accessible
9
+ include Models::Scopes
10
+
11
+ included do
12
+ belongs_to :application,
13
+ class_name: 'Doorkeeper::Application',
14
+ inverse_of: :access_tokens
15
+
16
+ validates :token, presence: true, uniqueness: true
17
+ validates :refresh_token, uniqueness: true, if: :use_refresh_token?
18
+
19
+ attr_writer :use_refresh_token
20
+
21
+ if ::Rails.version.to_i < 4 || defined?(::ProtectedAttributes)
22
+ attr_accessible :application_id, :resource_owner_id, :expires_in,
23
+ :scopes, :use_refresh_token
24
+ end
25
+
26
+ before_validation :generate_token, on: :create
27
+ before_validation :generate_refresh_token,
28
+ on: :create,
29
+ if: :use_refresh_token?
30
+ end
31
+
32
+ module ClassMethods
33
+ def by_token(token)
34
+ where(token: token).limit(1).to_a.first
35
+ end
36
+
37
+ def by_refresh_token(refresh_token)
38
+ where(refresh_token: refresh_token).first
39
+ end
40
+
41
+ def revoke_all_for(application_id, resource_owner)
42
+ where(application_id: application_id,
43
+ resource_owner_id: resource_owner.id,
44
+ revoked_at: nil).
45
+ map(&:revoke)
46
+ end
47
+
48
+ def matching_token_for(application, resource_owner_or_id, scopes)
49
+ resource_owner_id = if resource_owner_or_id.respond_to?(:to_key)
50
+ resource_owner_or_id.id
51
+ else
52
+ resource_owner_or_id
53
+ end
54
+ token = last_authorized_token_for(application.try(:id), resource_owner_id)
55
+ token if token && Doorkeeper::OAuth::Helpers::ScopeChecker.matches?(token.scopes, scopes)
56
+ end
57
+
58
+ def find_or_create_for(application, resource_owner_id, scopes, expires_in, use_refresh_token)
59
+ if Doorkeeper.configuration.reuse_access_token
60
+ access_token = matching_token_for(application, resource_owner_id, scopes)
61
+ if access_token && !access_token.expired?
62
+ return access_token
63
+ end
64
+ end
65
+ create!(
66
+ application_id: application.try(:id),
67
+ resource_owner_id: resource_owner_id,
68
+ scopes: scopes.to_s,
69
+ expires_in: expires_in,
70
+ use_refresh_token: use_refresh_token
71
+ )
72
+ end
73
+
74
+ def last_authorized_token_for(application_id, resource_owner_id)
75
+ where(application_id: application_id,
76
+ resource_owner_id: resource_owner_id,
77
+ revoked_at: nil).
78
+ send(order_method, created_at_desc).
79
+ limit(1).
80
+ to_a.
81
+ first
82
+ end
83
+ end
84
+
85
+ def token_type
86
+ 'bearer'
87
+ end
88
+
89
+ def use_refresh_token?
90
+ !!@use_refresh_token
91
+ end
92
+
93
+ def as_json(_options = {})
94
+ {
95
+ resource_owner_id: resource_owner_id,
96
+ scopes: scopes,
97
+ expires_in_seconds: expires_in_seconds,
98
+ application: { uid: application.try(:uid) }
99
+ }
100
+ end
101
+
102
+ # It indicates whether the tokens have the same credential
103
+ def same_credential?(access_token)
104
+ application_id == access_token.application_id &&
105
+ resource_owner_id == access_token.resource_owner_id
106
+ end
107
+
108
+ def acceptable?(scopes)
109
+ accessible? && includes_scope?(*scopes)
110
+ end
111
+
112
+ private
113
+
114
+ def generate_refresh_token
115
+ write_attribute :refresh_token, UniqueToken.generate
116
+ end
117
+
118
+ def generate_token
119
+ self.token = UniqueToken.generate
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,60 @@
1
+ module Doorkeeper
2
+ module ApplicationMixin
3
+ extend ActiveSupport::Concern
4
+
5
+ include OAuth::Helpers
6
+ include Models::Scopes
7
+
8
+ included do
9
+ has_many :access_grants, dependent: :destroy, class_name: 'Doorkeeper::AccessGrant'
10
+ has_many :access_tokens, dependent: :destroy, class_name: 'Doorkeeper::AccessToken'
11
+
12
+ validates :name, :secret, :uid, presence: true
13
+ validates :uid, uniqueness: true
14
+ validates :redirect_uri, redirect_uri: true
15
+
16
+ before_validation :generate_uid, :generate_secret, on: :create
17
+
18
+ if ::Rails.version.to_i < 4 || defined?(::ProtectedAttributes)
19
+ attr_accessible :name, :redirect_uri
20
+ end
21
+ end
22
+
23
+ module ClassMethods
24
+ def by_uid_and_secret(uid, secret)
25
+ where(uid: uid, secret: secret).limit(1).to_a.first
26
+ end
27
+
28
+ def by_uid(uid)
29
+ where(uid: uid).limit(1).to_a.first
30
+ end
31
+ end
32
+
33
+ alias_method :original_scopes, :scopes
34
+ def scopes
35
+ if has_scopes?
36
+ original_scopes
37
+ else
38
+ fail NameError, "Missing column: `applications.scopes`.", <<-MSG.squish
39
+ If you are using ActiveRecord run `rails generate doorkeeper:application_scopes
40
+ && rake db:migrate` to add it.
41
+ MSG
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ def has_scopes?
48
+ Doorkeeper.configuration.orm != :active_record ||
49
+ Application.new.attributes.include?("scopes")
50
+ end
51
+
52
+ def generate_uid
53
+ self.uid ||= UniqueToken.generate
54
+ end
55
+
56
+ def generate_secret
57
+ self.secret ||= UniqueToken.generate
58
+ end
59
+ end
60
+ end
@@ -5,17 +5,18 @@ module Doorkeeper
5
5
  expires_in && Time.now > expired_time
6
6
  end
7
7
 
8
- def expired_time
9
- created_at + expires_in.seconds
10
- end
11
-
12
8
  def expires_in_seconds
13
9
  return nil if expires_in.nil?
14
10
  expires = (created_at + expires_in.seconds) - Time.now
15
11
  expires_sec = expires.seconds.round(0)
16
12
  expires_sec > 0 ? expires_sec : 0
17
13
  end
18
- private :expired_time
14
+
15
+ private
16
+
17
+ def expired_time
18
+ created_at + expires_in.seconds
19
+ end
19
20
  end
20
21
  end
21
22
  end
@@ -1,15 +1,15 @@
1
1
  module Doorkeeper
2
2
  module Models
3
3
  module Ownership
4
- def validate_owner?
5
- Doorkeeper.configuration.confirm_application_owner?
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ belongs_to :owner, polymorphic: true
8
+ validates :owner, presence: true, if: :validate_owner?
6
9
  end
7
10
 
8
- def self.included(base)
9
- base.class_eval do
10
- belongs_to :owner, polymorphic: true
11
- validates :owner, presence: true, if: :validate_owner?
12
- end
11
+ def validate_owner?
12
+ Doorkeeper.configuration.confirm_application_owner?
13
13
  end
14
14
  end
15
15
  end
@@ -6,7 +6,7 @@ module Doorkeeper
6
6
  end
7
7
 
8
8
  def revoked?
9
- revoked_at.present?
9
+ !!(revoked_at && revoked_at <= DateTime.now)
10
10
  end
11
11
  end
12
12
  end
@@ -0,0 +1,17 @@
1
+ module Doorkeeper
2
+ module Models
3
+ module Scopes
4
+ def scopes
5
+ OAuth::Scopes.from_string(self[:scopes])
6
+ end
7
+
8
+ def scopes_string
9
+ self[:scopes]
10
+ end
11
+
12
+ def includes_scope?(*required_scopes)
13
+ required_scopes.blank? || required_scopes.any? { |s| scopes.exists?(s.to_s) }
14
+ end
15
+ end
16
+ end
17
+ end
@@ -10,12 +10,12 @@ module Doorkeeper
10
10
  end
11
11
 
12
12
  def issue_token
13
- @token ||= AccessToken.create!(
14
- application_id: pre_auth.client.id,
15
- resource_owner_id: resource_owner.id,
16
- scopes: pre_auth.scopes.to_s,
17
- expires_in: configuration.access_token_expires_in,
18
- use_refresh_token: false
13
+ @token ||= AccessToken.find_or_create_for(
14
+ pre_auth.client,
15
+ resource_owner.id,
16
+ pre_auth.scopes,
17
+ configuration.access_token_expires_in,
18
+ false
19
19
  )
20
20
  end
21
21
 
@@ -10,7 +10,7 @@ module Doorkeeper
10
10
  end
11
11
  end
12
12
 
13
- def self.authenticate(credentials, method = Application.method(:authenticate))
13
+ def self.authenticate(credentials, method = Application.method(:by_uid_and_secret))
14
14
  return false if credentials.blank?
15
15
  if application = method.call(credentials.uid, credentials.secret)
16
16
  new(application)
@@ -6,7 +6,7 @@ module Doorkeeper
6
6
  include OAuth::Helpers
7
7
 
8
8
  validate :client, error: :invalid_client
9
- validate :resource_owner, error: :invalid_resource_owner
9
+ validate :resource_owner, error: :invalid_grant
10
10
  validate :scopes, error: :invalid_scope
11
11
 
12
12
  attr_accessor :server, :resource_owner, :credentials, :access_token
@@ -19,8 +19,8 @@ module Doorkeeper
19
19
  @original_scopes = parameters[:scope]
20
20
 
21
21
  if credentials
22
- @client = Application.authenticate credentials.uid,
23
- credentials.secret
22
+ @client = Application.by_uid_and_secret credentials.uid,
23
+ credentials.secret
24
24
  end
25
25
  end
26
26
 
@@ -48,7 +48,11 @@ module Doorkeeper
48
48
 
49
49
  def validate_scopes
50
50
  return true unless scope.present?
51
- Helpers::ScopeChecker.valid? scope, server.scopes
51
+ if client.application.scopes.empty?
52
+ Helpers::ScopeChecker.valid?(scope, server.scopes)
53
+ else
54
+ Helpers::ScopeChecker.valid?(scope, server.scopes & client.application.scopes)
55
+ end
52
56
  end
53
57
 
54
58
  # TODO: test uri should be matched against the client's one
@@ -14,14 +14,14 @@ module Doorkeeper
14
14
  attr_accessor :client
15
15
 
16
16
  def initialize(server, refresh_token, credentials, parameters = {})
17
- @server = server
18
- @refresh_token = refresh_token
19
- @credentials = credentials
20
- @original_scopes = parameters[:scopes]
17
+ @server = server
18
+ @refresh_token = refresh_token
19
+ @credentials = credentials
20
+ @original_scopes = parameters[:scopes]
21
21
 
22
22
  if credentials
23
- @client = Application.authenticate credentials.uid,
24
- credentials.secret
23
+ @client = Application.by_uid_and_secret credentials.uid,
24
+ credentials.secret
25
25
  end
26
26
  end
27
27
 
@@ -17,7 +17,7 @@ module Doorkeeper
17
17
  end
18
18
  end
19
19
 
20
- delegate :each, to: :@scopes
20
+ delegate :each, :empty?, to: :@scopes
21
21
 
22
22
  def initialize
23
23
  @scopes = []
@@ -55,6 +55,11 @@ module Doorkeeper
55
55
  def <=>(other)
56
56
  self.map(&:to_s).sort <=> other.map(&:to_s).sort
57
57
  end
58
+
59
+ def &(other)
60
+ other_array = other.present? ? other.all : []
61
+ self.class.from_array(all & other_array)
62
+ end
58
63
  end
59
64
  end
60
65
  end
@@ -54,8 +54,9 @@ module Doorkeeper
54
54
  end
55
55
 
56
56
  def self.authenticate(request, *methods)
57
- token = from_request request, *methods
58
- AccessToken.authenticate(token) if token
57
+ if token = from_request(request, *methods)
58
+ AccessToken.by_token(token)
59
+ end
59
60
  end
60
61
  end
61
62
  end
@@ -0,0 +1,7 @@
1
+ module Doorkeeper
2
+ class AccessGrant < ActiveRecord::Base
3
+ include AccessGrantMixin
4
+
5
+ self.table_name = "#{table_name_prefix}oauth_access_grants#{table_name_suffix}".to_sym
6
+ end
7
+ end
@@ -0,0 +1,21 @@
1
+ module Doorkeeper
2
+ class AccessToken < ActiveRecord::Base
3
+ include AccessTokenMixin
4
+
5
+ self.table_name = "#{table_name_prefix}oauth_access_tokens#{table_name_suffix}".to_sym
6
+
7
+ def self.delete_all_for(application_id, resource_owner)
8
+ where(application_id: application_id,
9
+ resource_owner_id: resource_owner.id).delete_all
10
+ end
11
+ private_class_method :delete_all_for
12
+
13
+ def self.order_method
14
+ :order
15
+ end
16
+
17
+ def self.created_at_desc
18
+ 'created_at desc'
19
+ end
20
+ end
21
+ end
@@ -1,8 +1,6 @@
1
1
  module Doorkeeper
2
2
  class Application < ActiveRecord::Base
3
- if Doorkeeper.configuration.active_record_options[:establish_connection]
4
- establish_connection Doorkeeper.configuration.active_record_options[:establish_connection]
5
- end
3
+ include ApplicationMixin
6
4
 
7
5
  self.table_name = "#{table_name_prefix}oauth_applications#{table_name_suffix}".to_sym
8
6
 
@@ -0,0 +1,17 @@
1
+ module Doorkeeper
2
+ module Orm
3
+ module ActiveRecord
4
+ def self.initialize_models!
5
+ require 'doorkeeper/orm/active_record/access_grant'
6
+ require 'doorkeeper/orm/active_record/access_token'
7
+ require 'doorkeeper/orm/active_record/application'
8
+
9
+ if Doorkeeper.configuration.active_record_options[:establish_connection]
10
+ [Doorkeeper::AccessGrant, Doorkeeper::Application, Doorkeeper::AccessGrant].each do |c|
11
+ c.send :establish_connection, Doorkeeper.configuration.active_record_options[:establish_connection]
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -1,6 +1,9 @@
1
1
  module Doorkeeper
2
2
  class AccessGrant
3
3
  include MongoMapper::Document
4
+
5
+ include AccessGrantMixin
6
+
4
7
  safe
5
8
  timestamps!
6
9
 
@@ -9,14 +12,10 @@ module Doorkeeper
9
12
  key :resource_owner_id, ObjectId
10
13
  key :application_id, ObjectId
11
14
  key :token, String
15
+ key :scopes, String
12
16
  key :expires_in, Integer
13
17
  key :redirect_uri, String
14
18
  key :revoked_at, DateTime
15
- key :scopes, String
16
-
17
- def scopes=(value)
18
- write_attribute :scopes, value if value.present?
19
- end
20
19
 
21
20
  def self.create_indexes
22
21
  ensure_index :token, unique: true