doorkeeper-sequel 1.4.0 → 1.5.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.
- checksums.yaml +4 -4
- data/.gitmodules +1 -0
- data/CHANGELOG.md +6 -0
- data/README.md +4 -3
- data/Rakefile +1 -0
- data/config/locales/en.yml +1 -0
- data/doorkeeper-sequel.gemspec +1 -2
- data/lib/doorkeeper-sequel.rb +12 -7
- data/lib/doorkeeper-sequel/gem_version.rb +1 -1
- data/lib/doorkeeper-sequel/generators/confidential_applications_generator.rb +14 -0
- data/lib/doorkeeper-sequel/generators/templates/add_confidential_to_application_migration.rb +7 -0
- data/lib/doorkeeper-sequel/generators/templates/create_doorkeeper_tables.rb +1 -0
- data/lib/doorkeeper-sequel/mixins/access_grant_mixin.rb +46 -0
- data/lib/doorkeeper-sequel/mixins/access_token_mixin.rb +164 -0
- data/lib/doorkeeper-sequel/mixins/application_mixin.rb +93 -0
- data/lib/doorkeeper-sequel/mixins/concerns/ownership.rb +15 -0
- data/lib/doorkeeper-sequel/mixins/concerns/sequel_compat.rb +63 -0
- data/lib/doorkeeper-sequel/validators/redirect_uri_validator.rb +65 -0
- data/lib/doorkeeper/orm/sequel.rb +2 -3
- data/lib/doorkeeper/orm/sequel/access_grant.rb +1 -3
- data/lib/doorkeeper/orm/sequel/access_token.rb +1 -8
- data/lib/doorkeeper/orm/sequel/application.rb +5 -3
- data/spec/stubs/config/initializers/db.rb +1 -0
- data/spec/stubs/models/user.rb +1 -1
- metadata +62 -36
- data/lib/doorkeeper/orm/sequel/models/access_grant_mixin.rb +0 -50
- data/lib/doorkeeper/orm/sequel/models/access_token_mixin.rb +0 -168
- data/lib/doorkeeper/orm/sequel/models/application_mixin.rb +0 -70
- data/lib/doorkeeper/orm/sequel/models/concerns/ownership.rb +0 -19
- data/lib/doorkeeper/orm/sequel/models/concerns/sequel_compat.rb +0 -59
- data/lib/doorkeeper/orm/sequel/validators/redirect_uri_validator.rb +0 -57
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 553728671816109cbf8e780da862de70222768b0
|
4
|
+
data.tar.gz: c241ff98bec1bef3de150659beebcc4b73853ad4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d98ed140d5c131fbfc3d1967199c1a664baf9e6f2d2e398415fe52ad3e316c599f524bf6f058d9bbdd85c3f11cc17544a3eef7f78f41c39a63b86c8bb47c1225
|
7
|
+
data.tar.gz: 9fb3f5c993b40d5ef0a85dfe6ffbbd5b806ed74c5f3adaeb51429c8fbbe0f78a6f01c6de0de7f2633fe88ab00f260d595a1567d41a777547a4f3952924fdacdb
|
data/.gitmodules
CHANGED
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,12 @@ Reverse Chronological Order:
|
|
6
6
|
|
7
7
|
https://github.com/nbulaj/doorkeeper-sequel/compare/1.3.2...master
|
8
8
|
|
9
|
+
## `1.5.0` (2018-10-03)
|
10
|
+
|
11
|
+
https://github.com/nbulaj/doorkeeper-sequel/compare/1.5.0...1.4.0
|
12
|
+
|
13
|
+
* Support Doorkeeper >= 4.2.7 && < 5.0.0
|
14
|
+
|
9
15
|
## `1.4.0` (2018-02-08)
|
10
16
|
|
11
17
|
https://github.com/nbulaj/doorkeeper-sequel/compare/1.3.1...1.4.0
|
data/README.md
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
# Doorkeeper Sequel ORM extension
|
2
|
-
[](https://rubygems.org/gems/doorkeeper-sequel)
|
3
3
|
[](https://travis-ci.org/nbulaj/doorkeeper-sequel)
|
4
|
-
[](https://gemnasium.com/nbulaj/doorkeeper-sequel)
|
5
4
|
[](https://codeclimate.com/github/nbulaj/doorkeeper-sequel)
|
6
5
|
[](#license)
|
7
6
|
|
@@ -18,7 +17,8 @@
|
|
18
17
|
To start using the Doorkeeper Sequel ORM, add to your Gemfile:
|
19
18
|
|
20
19
|
``` ruby
|
21
|
-
gem 'doorkeeper
|
20
|
+
gem 'doorkeeper', '~> 4.0'
|
21
|
+
gem 'doorkeeper-sequel', '~> 1.4'
|
22
22
|
```
|
23
23
|
|
24
24
|
Or you can use git `master` branch for the latest gem version:
|
@@ -41,6 +41,7 @@ Generate migrations:
|
|
41
41
|
rake doorkeeper_sequel:generate:migration
|
42
42
|
rake doorkeeper_sequel:generate:application_owner
|
43
43
|
rake doorkeeper_sequel:generate:previous_refresh_token
|
44
|
+
rake doorkeeper_sequel:generate:confidential_applications # for Doorkeeper >= 4.4
|
44
45
|
```
|
45
46
|
|
46
47
|
## Tests
|
data/Rakefile
CHANGED
@@ -32,6 +32,7 @@ class ExtensionIntegrator
|
|
32
32
|
FileUtils.cp_r('spec/stubs/support/sequel.rb', 'spec/support/orm/sequel.rb')
|
33
33
|
FileUtils.rm('spec/dummy/config/initializers/active_record_belongs_to_required_by_default.rb', force: true)
|
34
34
|
FileUtils.rm('spec/dummy/config/initializers/new_framework_defaults.rb', force: true)
|
35
|
+
FileUtils.rm('spec/models/doorkeeper/base_record_spec.rb', force: true)
|
35
36
|
# Remove generators specs because we are using our own
|
36
37
|
FileUtils.rm(Dir.glob('spec/generators/*.rb'))
|
37
38
|
end
|
data/config/locales/en.yml
CHANGED
data/doorkeeper-sequel.gemspec
CHANGED
@@ -6,7 +6,6 @@ Gem::Specification.new do |gem|
|
|
6
6
|
gem.name = 'doorkeeper-sequel'
|
7
7
|
gem.version = DoorkeeperSequel.gem_version
|
8
8
|
gem.authors = ['Nikita Bulai']
|
9
|
-
gem.date = '2018-02-08'
|
10
9
|
gem.email = ['bulajnikita@gmail.com']
|
11
10
|
gem.homepage = 'http://github.com/nbulaj/doorkeeper-sequel'
|
12
11
|
gem.summary = 'Doorkeeper Sequel ORM'
|
@@ -21,7 +20,7 @@ Gem::Specification.new do |gem|
|
|
21
20
|
|
22
21
|
gem.required_ruby_version = '>= 2.0.0'
|
23
22
|
|
24
|
-
gem.add_runtime_dependency 'doorkeeper', '
|
23
|
+
gem.add_runtime_dependency 'doorkeeper', '>= 4.2.6', '< 5.0'
|
25
24
|
gem.add_runtime_dependency 'sequel', '>= 4.0.0', '< 6'
|
26
25
|
gem.add_runtime_dependency 'sequel_polymorphic', '~> 0.2', '< 1.0'
|
27
26
|
gem.add_runtime_dependency 'thor', '>= 0.18', '< 6'
|
data/lib/doorkeeper-sequel.rb
CHANGED
@@ -1,17 +1,22 @@
|
|
1
1
|
require 'doorkeeper-sequel/version'
|
2
2
|
|
3
3
|
if defined?(::Rails)
|
4
|
-
require 'thor/group'
|
5
|
-
|
6
|
-
require 'doorkeeper-sequel/generators/concerns/migration_actions'
|
7
|
-
require 'doorkeeper-sequel/generators/application_owner_generator'
|
8
|
-
require 'doorkeeper-sequel/generators/migration_generator'
|
9
|
-
require 'doorkeeper-sequel/generators/previous_refresh_token_generator'
|
10
|
-
|
11
4
|
require 'doorkeeper-sequel/railtie'
|
12
5
|
end
|
13
6
|
|
14
7
|
require 'doorkeeper'
|
8
|
+
require 'thor/group'
|
9
|
+
|
10
|
+
require 'doorkeeper-sequel/generators/concerns/migration_actions'
|
11
|
+
require 'doorkeeper-sequel/generators/application_owner_generator'
|
12
|
+
require 'doorkeeper-sequel/generators/migration_generator'
|
13
|
+
require 'doorkeeper-sequel/generators/previous_refresh_token_generator'
|
14
|
+
|
15
|
+
require 'doorkeeper-sequel/mixins/concerns/sequel_compat'
|
16
|
+
require 'doorkeeper-sequel/mixins/access_token_mixin'
|
17
|
+
require 'doorkeeper-sequel/mixins/access_grant_mixin'
|
18
|
+
require 'doorkeeper-sequel/mixins/application_mixin'
|
19
|
+
|
15
20
|
require 'doorkeeper/orm/sequel'
|
16
21
|
|
17
22
|
module DoorkeeperSequel
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module DoorkeeperSequel
|
2
|
+
class ConfidentialApplicationsGenerator < ::Thor::Group
|
3
|
+
include ::Thor::Actions
|
4
|
+
include MigrationActions
|
5
|
+
|
6
|
+
source_root File.expand_path('../templates', __FILE__)
|
7
|
+
|
8
|
+
desc 'Add confidential column to Doorkeeper applications.'
|
9
|
+
|
10
|
+
def install
|
11
|
+
create_migration 'add_confidential_to_application_migration'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module DoorkeeperSequel
|
2
|
+
module AccessGrantMixin
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
include SequelCompat
|
6
|
+
include Doorkeeper::OAuth::Helpers
|
7
|
+
include Doorkeeper::Models::Expirable
|
8
|
+
include Doorkeeper::Models::Revocable
|
9
|
+
include Doorkeeper::Models::Accessible
|
10
|
+
include Doorkeeper::Models::Scopes
|
11
|
+
|
12
|
+
included do
|
13
|
+
plugin :validation_helpers
|
14
|
+
plugin :timestamps
|
15
|
+
|
16
|
+
many_to_one :application, class: 'Doorkeeper::Application'
|
17
|
+
|
18
|
+
set_allowed_columns :resource_owner_id, :application_id,
|
19
|
+
:expires_in, :redirect_uri, :scopes
|
20
|
+
|
21
|
+
def before_validation
|
22
|
+
generate_token if new?
|
23
|
+
super
|
24
|
+
end
|
25
|
+
|
26
|
+
def validate
|
27
|
+
super
|
28
|
+
validates_presence [:resource_owner_id, :application_id,
|
29
|
+
:token, :expires_in, :redirect_uri]
|
30
|
+
validates_unique [:token]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
module ClassMethods
|
35
|
+
def by_token(token)
|
36
|
+
first(token: token.to_s)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def generate_token
|
43
|
+
self.token = UniqueToken.generate
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,164 @@
|
|
1
|
+
module DoorkeeperSequel
|
2
|
+
module AccessTokenMixin
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
include SequelCompat
|
6
|
+
include Doorkeeper::OAuth::Helpers
|
7
|
+
include Doorkeeper::Models::Expirable
|
8
|
+
include Doorkeeper::Models::Revocable
|
9
|
+
include Doorkeeper::Models::Accessible
|
10
|
+
include Doorkeeper::Models::Scopes
|
11
|
+
|
12
|
+
included do
|
13
|
+
plugin :validation_helpers
|
14
|
+
plugin :timestamps
|
15
|
+
|
16
|
+
many_to_one :application, class: 'Doorkeeper::Application'
|
17
|
+
|
18
|
+
attr_writer :use_refresh_token
|
19
|
+
|
20
|
+
set_allowed_columns :application_id, :resource_owner_id, :expires_in,
|
21
|
+
:scopes, :use_refresh_token, :previous_refresh_token
|
22
|
+
|
23
|
+
def before_validation
|
24
|
+
if new?
|
25
|
+
generate_token
|
26
|
+
generate_refresh_token if use_refresh_token?
|
27
|
+
end
|
28
|
+
|
29
|
+
super
|
30
|
+
end
|
31
|
+
|
32
|
+
def validate
|
33
|
+
super
|
34
|
+
validates_presence [:token]
|
35
|
+
validates_unique [:token]
|
36
|
+
|
37
|
+
validates_unique [:refresh_token] if use_refresh_token?
|
38
|
+
end
|
39
|
+
|
40
|
+
def application_id?
|
41
|
+
application_id.present?
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
module ClassMethods
|
46
|
+
def by_token(token)
|
47
|
+
first(token: token.to_s)
|
48
|
+
end
|
49
|
+
|
50
|
+
def by_refresh_token(refresh_token)
|
51
|
+
first(refresh_token: refresh_token.to_s)
|
52
|
+
end
|
53
|
+
|
54
|
+
def revoke_all_for(application_id, resource_owner, clock = Time)
|
55
|
+
where(application_id: application_id,
|
56
|
+
resource_owner_id: resource_owner.id,
|
57
|
+
revoked_at: nil)
|
58
|
+
.update(revoked_at: clock.now.utc)
|
59
|
+
end
|
60
|
+
|
61
|
+
def matching_token_for(application, resource_owner_or_id, scopes)
|
62
|
+
resource_owner_id = if resource_owner_or_id.respond_to?(:to_key)
|
63
|
+
resource_owner_or_id.id
|
64
|
+
else
|
65
|
+
resource_owner_or_id
|
66
|
+
end
|
67
|
+
token = last_authorized_token_for(application.try(:id), resource_owner_id)
|
68
|
+
if token && scopes_match?(token.scopes, scopes, application.try(:scopes))
|
69
|
+
token
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def scopes_match?(token_scopes, param_scopes, app_scopes)
|
74
|
+
(token_scopes.blank? && param_scopes.blank?) ||
|
75
|
+
Doorkeeper::OAuth::Helpers::ScopeChecker.match?(
|
76
|
+
token_scopes.to_s,
|
77
|
+
param_scopes,
|
78
|
+
app_scopes
|
79
|
+
)
|
80
|
+
end
|
81
|
+
|
82
|
+
def find_or_create_for(application, resource_owner_id, scopes, expires_in, use_refresh_token)
|
83
|
+
if Doorkeeper.configuration.reuse_access_token
|
84
|
+
access_token = matching_token_for(application, resource_owner_id, scopes)
|
85
|
+
return access_token if access_token && !access_token.expired?
|
86
|
+
end
|
87
|
+
|
88
|
+
create!(
|
89
|
+
application_id: application.try(:id),
|
90
|
+
resource_owner_id: resource_owner_id,
|
91
|
+
scopes: scopes.to_s,
|
92
|
+
expires_in: expires_in,
|
93
|
+
use_refresh_token: use_refresh_token
|
94
|
+
)
|
95
|
+
end
|
96
|
+
|
97
|
+
def last_authorized_token_for(application_id, resource_owner_id)
|
98
|
+
where(application_id: application_id,
|
99
|
+
resource_owner_id: resource_owner_id,
|
100
|
+
revoked_at: nil)
|
101
|
+
.send(order_method, created_at_desc)
|
102
|
+
.first
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def token_type
|
107
|
+
'Bearer'
|
108
|
+
end
|
109
|
+
|
110
|
+
def use_refresh_token?
|
111
|
+
!!@use_refresh_token
|
112
|
+
end
|
113
|
+
|
114
|
+
def as_json(_options = {})
|
115
|
+
{
|
116
|
+
resource_owner_id: resource_owner_id,
|
117
|
+
scopes: scopes,
|
118
|
+
expires_in_seconds: expires_in_seconds,
|
119
|
+
application: { uid: application.try(:uid) },
|
120
|
+
created_at: created_at.to_i
|
121
|
+
}
|
122
|
+
end
|
123
|
+
|
124
|
+
# It indicates whether the tokens have the same credential
|
125
|
+
def same_credential?(access_token)
|
126
|
+
application_id == access_token.application_id &&
|
127
|
+
resource_owner_id == access_token.resource_owner_id
|
128
|
+
end
|
129
|
+
|
130
|
+
def acceptable?(scopes)
|
131
|
+
accessible? && includes_scope?(*scopes)
|
132
|
+
end
|
133
|
+
|
134
|
+
private
|
135
|
+
|
136
|
+
def generate_refresh_token
|
137
|
+
self[:refresh_token] = UniqueToken.generate
|
138
|
+
end
|
139
|
+
|
140
|
+
def generate_token
|
141
|
+
self[:created_at] ||= Time.now.utc
|
142
|
+
|
143
|
+
generator = token_generator
|
144
|
+
unless generator.respond_to?(:generate)
|
145
|
+
raise Doorkeeper::Errors::UnableToGenerateToken, "#{generator} does not respond to `.generate`."
|
146
|
+
end
|
147
|
+
|
148
|
+
self[:token] = generator.generate(
|
149
|
+
resource_owner_id: resource_owner_id,
|
150
|
+
scopes: scopes,
|
151
|
+
application: application,
|
152
|
+
expires_in: expires_in,
|
153
|
+
created_at: created_at
|
154
|
+
)
|
155
|
+
end
|
156
|
+
|
157
|
+
def token_generator
|
158
|
+
generator_name = Doorkeeper.configuration.access_token_generator
|
159
|
+
generator_name.constantize
|
160
|
+
rescue NameError
|
161
|
+
raise Doorkeeper::Errors::TokenGeneratorNotFound, "#{generator_name} not found"
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require_relative '../validators/redirect_uri_validator'
|
2
|
+
|
3
|
+
module DoorkeeperSequel
|
4
|
+
module ApplicationMixin
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
include SequelCompat
|
8
|
+
include Doorkeeper::OAuth::Helpers
|
9
|
+
include Doorkeeper::Models::Scopes
|
10
|
+
include DoorkeeperSequel::RedirectUriValidator
|
11
|
+
|
12
|
+
included do
|
13
|
+
plugin :validation_helpers
|
14
|
+
plugin :timestamps
|
15
|
+
plugin :association_dependencies
|
16
|
+
|
17
|
+
one_to_many :access_grants, class: 'Doorkeeper::AccessGrant'
|
18
|
+
one_to_many :access_tokens, class: 'Doorkeeper::AccessToken'
|
19
|
+
|
20
|
+
add_association_dependencies access_grants: :delete, access_tokens: :delete
|
21
|
+
|
22
|
+
set_allowed_columns :name, :redirect_uri, :scopes, :confidential
|
23
|
+
|
24
|
+
def before_validation
|
25
|
+
generate_uid
|
26
|
+
generate_secret
|
27
|
+
super
|
28
|
+
end
|
29
|
+
|
30
|
+
def validate
|
31
|
+
super
|
32
|
+
validates_presence [:name, :secret, :uid]
|
33
|
+
validates_unique [:uid]
|
34
|
+
validates_redirect_uri :redirect_uri
|
35
|
+
validates_includes [true, false], :confidential, allow_missing: true
|
36
|
+
|
37
|
+
if respond_to?(:validate_owner?)
|
38
|
+
validates_presence [:owner_id] if validate_owner?
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
module ClassMethods
|
44
|
+
def by_uid_and_secret(uid, secret)
|
45
|
+
app = by_uid(uid)
|
46
|
+
return unless app
|
47
|
+
return app if secret.blank? && !app.confidential?
|
48
|
+
return unless app.secret == secret
|
49
|
+
app
|
50
|
+
end
|
51
|
+
|
52
|
+
def by_uid(uid)
|
53
|
+
first(uid: uid.to_s)
|
54
|
+
end
|
55
|
+
|
56
|
+
def supports_confidentiality?
|
57
|
+
column_names.include?('confidential')
|
58
|
+
end
|
59
|
+
|
60
|
+
def column_names
|
61
|
+
columns.map(&:to_s)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Fallback to existing, default behaviour of assuming all apps to be
|
66
|
+
# confidential if the migration hasn't been run
|
67
|
+
def confidential
|
68
|
+
return super if self.class.supports_confidentiality?
|
69
|
+
|
70
|
+
ActiveSupport::Deprecation.warn 'You are susceptible to security bug ' \
|
71
|
+
'CVE-2018-1000211. Please follow instructions outlined in ' \
|
72
|
+
'Doorkeeper::CVE_2018_1000211_WARNING'
|
73
|
+
|
74
|
+
true
|
75
|
+
end
|
76
|
+
|
77
|
+
alias_method :confidential?, :confidential
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
def has_scopes?
|
82
|
+
Doorkeeper::Application.columns.include?('scopes')
|
83
|
+
end
|
84
|
+
|
85
|
+
def generate_uid
|
86
|
+
self.uid = UniqueToken.generate if uid.blank? && new?
|
87
|
+
end
|
88
|
+
|
89
|
+
def generate_secret
|
90
|
+
self.secret = UniqueToken.generate if secret.blank? && new?
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|