sorcery 0.14.0 → 0.15.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bfe20ba10b3d52ae3bd1c37f487d5a3e42da98387127033d26978831f523e4a1
4
- data.tar.gz: 5a3f0f7279d060ce1515e8635d9f87c5c52a840d6c15916e064171714b1d26a5
3
+ metadata.gz: 2eacf343e86db96ee2b99e31a647efbdca41cc859dd3aaa5d5300fcf80cb2f6f
4
+ data.tar.gz: 0ab8e2eb73204b108e52ec39c4622e654cf48fa2ec75159bd5a3686a2855156e
5
5
  SHA512:
6
- metadata.gz: a1ff57ddfbfebe031dab7bc2d21bab6a045d48cc03f9b5b1cc50786ce6eb541a89e799d8dc6d68cf4b9995aa89409f101166cc8f0c8aa17056daad4af6bba502
7
- data.tar.gz: 8d3eae6eb8a66f9e93ae312f4e9300587bdea66e6800b3608bcfe87e5c2f437e2af85ccc865575471f27c011a7ba947f80836f880bf00d21229bbb6ccdc3e42f
6
+ metadata.gz: f4d4e09af8fd96f8c4a025a50c7d9d539ae584fac256f443a488063a91acffe2e1539a0a89b7aa4323116fdc6b9a6bb4e881072d91113e5f98be697e2296005b
7
+ data.tar.gz: b61da2da586d75af4f1f4df8046accfc7928428005ba3101e6c59fb30421c27b7e358b8b37f6e702c839a2002987e5b43af8c8de7adfd91e70ee8c749ebabf3d
@@ -3,7 +3,7 @@ inherit_from: .rubocop_todo.yml
3
3
  AllCops:
4
4
  Exclude:
5
5
  - 'lib/generators/sorcery/templates/**/*'
6
- TargetRubyVersion: 2.2
6
+ TargetRubyVersion: 2.6
7
7
 
8
8
  # See: https://github.com/rubocop-hq/rubocop/issues/3344
9
9
  Style/DoubleNegation:
@@ -21,7 +21,7 @@ Metrics/BlockLength:
21
21
  Exclude:
22
22
  - 'lib/**/*'
23
23
  - 'spec/**/*'
24
- Metrics/LineLength:
24
+ Layout/LineLength:
25
25
  Exclude:
26
26
  - 'lib/**/*'
27
27
  - 'spec/**/*'
@@ -1,7 +1,145 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config`
3
- # on 2018-11-01 18:13:47 -0700 using RuboCop version 0.59.2.
3
+ # on 2019-12-18 16:18:24 -0800 using RuboCop version 0.78.0.
4
4
  # The point is for the user to remove these configuration records
5
5
  # one by one as the offenses are removed from the code base.
6
6
  # Note that changes in the inspected code, or installation of new
7
7
  # versions of RuboCop, may require this file to be generated again.
8
+
9
+ # Offense count: 1
10
+ # Configuration parameters: Include.
11
+ # Include: **/*.gemspec
12
+ Gemspec/RequiredRubyVersion:
13
+ Exclude:
14
+ - 'sorcery.gemspec'
15
+
16
+ # Offense count: 1
17
+ # Cop supports --auto-correct.
18
+ # Configuration parameters: AllowAdjacentOneLineDefs, NumberOfEmptyLines.
19
+ Layout/EmptyLineBetweenDefs:
20
+ Exclude:
21
+ - 'lib/sorcery/providers/line.rb'
22
+
23
+ # Offense count: 83
24
+ # Cop supports --auto-correct.
25
+ # Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle.
26
+ # SupportedHashRocketStyles: key, separator, table
27
+ # SupportedColonStyles: key, separator, table
28
+ # SupportedLastArgumentHashStyles: always_inspect, always_ignore, ignore_implicit, ignore_explicit
29
+ Layout/HashAlignment:
30
+ Enabled: false
31
+
32
+ # Offense count: 2
33
+ # Configuration parameters: AllowSafeAssignment.
34
+ Lint/AssignmentInCondition:
35
+ Exclude:
36
+ - 'spec/rails_app/app/controllers/sorcery_controller.rb'
37
+
38
+ # Offense count: 1
39
+ # Cop supports --auto-correct.
40
+ Lint/NonDeterministicRequireOrder:
41
+ Exclude:
42
+ - 'spec/spec_helper.rb'
43
+
44
+ # Offense count: 4
45
+ # Cop supports --auto-correct.
46
+ Lint/RedundantCopDisableDirective:
47
+ Exclude:
48
+ - 'lib/sorcery/controller.rb'
49
+ - 'lib/sorcery/model.rb'
50
+ - 'spec/rails_app/config/application.rb'
51
+ - 'spec/shared_examples/user_shared_examples.rb'
52
+
53
+ # Offense count: 4
54
+ # Cop supports --auto-correct.
55
+ Lint/SendWithMixinArgument:
56
+ Exclude:
57
+ - 'lib/sorcery.rb'
58
+ - 'lib/sorcery/engine.rb'
59
+ - 'lib/sorcery/test_helpers/internal/rails.rb'
60
+
61
+ # Offense count: 4
62
+ # Configuration parameters: AllowComments.
63
+ Lint/SuppressedException:
64
+ Exclude:
65
+ - 'lib/sorcery/controller.rb'
66
+ - 'lib/sorcery/model.rb'
67
+ - 'spec/rails_app/config/application.rb'
68
+ - 'spec/shared_examples/user_shared_examples.rb'
69
+
70
+ # Offense count: 2
71
+ # Cop supports --auto-correct.
72
+ # Configuration parameters: IgnoreEmptyBlocks, AllowUnusedKeywordArguments.
73
+ Lint/UnusedBlockArgument:
74
+ Exclude:
75
+ - 'spec/shared_examples/user_shared_examples.rb'
76
+
77
+ # Offense count: 1
78
+ # Configuration parameters: EnforcedStyle.
79
+ # SupportedStyles: annotated, template, unannotated
80
+ Style/FormatStringToken:
81
+ Exclude:
82
+ - 'lib/generators/sorcery/install_generator.rb'
83
+
84
+ # Offense count: 121
85
+ # Cop supports --auto-correct.
86
+ # Configuration parameters: EnforcedStyle.
87
+ # SupportedStyles: always, never
88
+ Style/FrozenStringLiteralComment:
89
+ Enabled: false
90
+
91
+ # Offense count: 3
92
+ # Configuration parameters: MinBodyLength.
93
+ Style/GuardClause:
94
+ Exclude:
95
+ - 'lib/sorcery/controller/submodules/brute_force_protection.rb'
96
+ - 'lib/sorcery/controller/submodules/http_basic_auth.rb'
97
+ - 'lib/sorcery/controller/submodules/remember_me.rb'
98
+
99
+ # Offense count: 3
100
+ # Cop supports --auto-correct.
101
+ # Configuration parameters: EnforcedStyle, UseHashRocketsWithSymbolValues, PreferHashRocketsForNonAlnumEndingSymbols.
102
+ # SupportedStyles: ruby19, hash_rockets, no_mixed_keys, ruby19_no_mixed_keys
103
+ Style/HashSyntax:
104
+ Exclude:
105
+ - 'lib/sorcery/adapters/active_record_adapter.rb'
106
+ - 'lib/sorcery/test_helpers/rails/integration.rb'
107
+
108
+ # Offense count: 49
109
+ # Cop supports --auto-correct.
110
+ Style/IfUnlessModifier:
111
+ Enabled: false
112
+
113
+ # Offense count: 2
114
+ # Cop supports --auto-correct.
115
+ Style/RedundantBegin:
116
+ Exclude:
117
+ - 'lib/sorcery/controller.rb'
118
+ - 'lib/sorcery/model.rb'
119
+
120
+ # Offense count: 4
121
+ # Cop supports --auto-correct.
122
+ # Configuration parameters: ConvertCodeThatCanStartToReturnNil, AllowedMethods.
123
+ # AllowedMethods: present?, blank?, presence, try, try!
124
+ Style/SafeNavigation:
125
+ Exclude:
126
+ - 'lib/sorcery/controller/config.rb'
127
+ - 'lib/sorcery/controller/submodules/brute_force_protection.rb'
128
+ - 'lib/sorcery/controller/submodules/remember_me.rb'
129
+ - 'lib/sorcery/model.rb'
130
+
131
+ # Offense count: 7
132
+ # Cop supports --auto-correct.
133
+ # Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline.
134
+ # SupportedStyles: single_quotes, double_quotes
135
+ Style/StringLiterals:
136
+ Exclude:
137
+ - 'spec/controllers/controller_oauth2_spec.rb'
138
+ - 'spec/sorcery_crypto_providers_spec.rb'
139
+
140
+ # Offense count: 2
141
+ # Cop supports --auto-correct.
142
+ Style/UnpackFirst:
143
+ Exclude:
144
+ - 'lib/sorcery/crypto_providers/aes256.rb'
145
+ - 'spec/sorcery_crypto_providers_spec.rb'
@@ -1,12 +1,8 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.2.9
4
- - 2.3.6
5
- - 2.4.3
6
- - 2.5.0
3
+ - 2.4.9
4
+ - 2.5.7
5
+ - 2.6.5
7
6
 
8
7
  gemfile:
9
8
  - Gemfile
10
-
11
- before_script:
12
- - mysql -e 'create database sorcery_test;'
@@ -1,6 +1,23 @@
1
1
  # Changelog
2
2
  ## HEAD
3
3
 
4
+ ## 0.15.0
5
+
6
+ * Fix brute force vuln due to callbacks no being ran [#235](https://github.com/Sorcery/sorcery/pull/235)
7
+ * Revert on_load change due to breaking existing applications [#234](https://github.com/Sorcery/sorcery/pull/234)
8
+ * Add forget_me! and force_forget_me! test cases [#216](https://github.com/Sorcery/sorcery/pull/216)
9
+ * In `generic_send_email`, check responds_to [#211](https://github.com/Sorcery/sorcery/pull/211)
10
+ * Fix typo [#219](https://github.com/Sorcery/sorcery/pull/219)
11
+ * Fix deprecation warnings in Rails 6 [#209](https://github.com/Sorcery/sorcery/pull/209)
12
+ * Add ruby 2.6.5 to the travis build [#215](https://github.com/Sorcery/sorcery/pull/215)
13
+ * Add discord provider [#185](https://github.com/Sorcery/sorcery/pull/185)
14
+ * Remove MySQL database creation call [#214](https://github.com/Sorcery/sorcery/pull/214)
15
+ * Use id instead of uid for VK provider [#199](https://github.com/Sorcery/sorcery/pull/199)
16
+ * Don't :return_t JSON requests after login [#197](https://github.com/Sorcery/sorcery/pull/197)
17
+ * Fix email scope for LinkedIn Provider [#191](https://github.com/Sorcery/sorcery/pull/191)
18
+ * Ignore cookies when undefined cookies [#187](https://github.com/Sorcery/sorcery/pull/187)
19
+ * Allow for custom providers with multi-word class names. [#190](https://github.com/Sorcery/sorcery/pull/190)
20
+
4
21
  ## 0.14.0
5
22
 
6
23
  * Update LinkedIn to use OAuth 2 [#189](https://github.com/Sorcery/sorcery/pull/189)
@@ -88,11 +88,19 @@ Rails.application.config.sorcery.configure do |config|
88
88
  #
89
89
  # config.ca_file =
90
90
 
91
+ # Linkedin requires r_emailaddress scope to fetch user's email address.
92
+ # You can skip including the email field if you use an intermediary signup form. (using build_from method).
93
+ # The r_emailaddress scope is only necessary if you are using the create_from method directly.
94
+ #
91
95
  # config.linkedin.key = ""
92
96
  # config.linkedin.secret = ""
93
97
  # config.linkedin.callback_url = "http://0.0.0.0:3000/oauth/callback?provider=linkedin"
94
- # config.linkedin.user_info_mapping = {first_name: "firstName", last_name: "lastName"}
95
- # config.linkedin.scope = "r_basicprofile"
98
+ # config.linkedin.user_info_mapping = {
99
+ # first_name: 'localizedFirstName',
100
+ # last_name: 'localizedLastName',
101
+ # email: 'emailAddress'
102
+ # }
103
+ # config.linkedin.scope = "r_liteprofile r_emailaddress"
96
104
  #
97
105
  #
98
106
  # For information about XING API:
@@ -215,6 +223,12 @@ Rails.application.config.sorcery.configure do |config|
215
223
  # config.line.secret = ""
216
224
  # config.line.callback_url = "http://mydomain.com:3000/oauth/callback?provider=line"
217
225
 
226
+ # For infromation about Discord API
227
+ # https://discordapp.com/developers/docs/topics/oauth2
228
+ # config.discord.key = "xxxxxx"
229
+ # config.discord.secret = "xxxxxx"
230
+ # config.discord.callback_url = "http://localhost:3000/oauth/callback?provider=discord"
231
+ # config.discord.scope = "email guilds"
218
232
  # --- user config ---
219
233
  config.user_config do |user|
220
234
  # -- core --
@@ -25,7 +25,10 @@ module Sorcery
25
25
  def require_login
26
26
  return if logged_in?
27
27
 
28
- session[:return_to_url] = request.url if Config.save_return_to_url && request.get? && !request.xhr?
28
+ if Config.save_return_to_url && request.get? && !request.xhr? && !request.format.json?
29
+ session[:return_to_url] = request.url
30
+ end
31
+
29
32
  send(Config.not_authenticated_action)
30
33
  end
31
34
 
@@ -26,6 +26,7 @@ module Sorcery
26
26
  require 'sorcery/providers/instagram'
27
27
  require 'sorcery/providers/auth0'
28
28
  require 'sorcery/providers/line'
29
+ require 'sorcery/providers/discord'
29
30
 
30
31
  Config.module_eval do
31
32
  class << self
@@ -38,7 +39,7 @@ module Sorcery
38
39
  providers.each do |name|
39
40
  class_eval <<-RUBY, __FILE__, __LINE__ + 1
40
41
  def self.#{name}
41
- @#{name} ||= Sorcery::Providers.const_get('#{name}'.to_s.capitalize).new
42
+ @#{name} ||= Sorcery::Providers.const_get('#{name}'.to_s.classify).new
42
43
  end
43
44
  RUBY
44
45
  end
@@ -59,7 +59,7 @@ module Sorcery
59
59
  # and logs the user in if found.
60
60
  # Runs as a login source. See 'current_user' method for how it is used.
61
61
  def login_from_cookie
62
- user = cookies.signed[:remember_me_token] && user_class.sorcery_adapter.find_by_remember_me_token(cookies.signed[:remember_me_token])
62
+ user = cookies.signed[:remember_me_token] && user_class.sorcery_adapter.find_by_remember_me_token(cookies.signed[:remember_me_token]) if defined? cookies
63
63
  if user && user.has_remember_me_token?
64
64
  set_remember_me_cookie!(user)
65
65
  session[:user_id] = user.id.to_s
@@ -7,12 +7,18 @@ module Sorcery
7
7
  class Engine < Rails::Engine
8
8
  config.sorcery = ::Sorcery::Controller::Config
9
9
 
10
+ # TODO: Should this include a modified version of the helper methods?
10
11
  initializer 'extend Controller with sorcery' do
11
- # TODO: Should this include a modified version of the helper methods?
12
+ # FIXME: on_load is needed to fix Rails 6 deprecations, but it breaks
13
+ # applications due to undefined method errors.
14
+ # ActiveSupport.on_load(:action_controller_api) do
12
15
  if defined?(ActionController::API)
13
16
  ActionController::API.send(:include, Sorcery::Controller)
14
17
  end
15
18
 
19
+ # FIXME: on_load is needed to fix Rails 6 deprecations, but it breaks
20
+ # applications due to undefined method errors.
21
+ # ActiveSupport.on_load(:action_controller_base) do
16
22
  if defined?(ActionController::Base)
17
23
  ActionController::Base.send(:include, Sorcery::Controller)
18
24
  ActionController::Base.helper_method :current_user
@@ -102,10 +102,6 @@ module Sorcery
102
102
 
103
103
  set_encryption_attributes
104
104
 
105
- unless user.valid_password?(credentials[1])
106
- return authentication_response(user: user, failure: :invalid_password, &block)
107
- end
108
-
109
105
  if user.respond_to?(:active_for_authentication?) && !user.active_for_authentication?
110
106
  return authentication_response(user: user, failure: :inactive, &block)
111
107
  end
@@ -118,6 +114,10 @@ module Sorcery
118
114
  end
119
115
  end
120
116
 
117
+ unless user.valid_password?(credentials[1])
118
+ return authentication_response(user: user, failure: :invalid_password, &block)
119
+ end
120
+
121
121
  authentication_response(user: user, return_value: user, &block)
122
122
  end
123
123
 
@@ -206,7 +206,7 @@ module Sorcery
206
206
  def generic_send_email(method, mailer)
207
207
  config = sorcery_config
208
208
  mail = config.send(mailer).send(config.send(method), self)
209
- return unless defined?(ActionMailer) && config.send(mailer).is_a?(Class) && config.send(mailer) < ActionMailer::Base
209
+ return unless mail.respond_to?(config.email_delivery_method)
210
210
 
211
211
  mail.send(config.email_delivery_method)
212
212
  end
@@ -0,0 +1,52 @@
1
+ module Sorcery
2
+ module Providers
3
+ # This class adds support for OAuth with discordapp.com
4
+
5
+ class Discord < Base
6
+ include Protocols::Oauth2
7
+
8
+ attr_accessor :auth_path, :scope, :token_url, :user_info_path
9
+
10
+ def initialize
11
+ super
12
+
13
+ @scope = 'identify'
14
+ @site = 'https://discordapp.com/'
15
+ @auth_path = '/api/oauth2/authorize'
16
+ @token_url = '/api/oauth2/token'
17
+ @user_info_path = '/api/users/@me'
18
+ @state = SecureRandom.hex(16)
19
+ end
20
+
21
+ def get_user_hash(access_token)
22
+ response = access_token.get(user_info_path)
23
+ body = JSON.parse(response.body)
24
+ auth_hash(access_token).tap do |h|
25
+ h[:user_info] = body
26
+ h[:uid] = body['id']
27
+ end
28
+ end
29
+
30
+ # calculates and returns the url to which the user should be redirected,
31
+ # to get authenticated at the external provider's site.
32
+ def login_url(_params, _session)
33
+ authorize_url(authorize_url: auth_path)
34
+ end
35
+
36
+ # tries to login the user from access token
37
+ def process_callback(params, _session)
38
+ args = {}.tap do |a|
39
+ a[:code] = params[:code] if params[:code]
40
+ end
41
+ get_access_token(
42
+ args,
43
+ token_url: token_url,
44
+ client_id: @key,
45
+ client_secret: @secret,
46
+ grant_type: 'authorization_code',
47
+ token_method: :post
48
+ )
49
+ end
50
+ end
51
+ end
52
+ end
@@ -9,25 +9,26 @@ module Sorcery
9
9
  class Linkedin < Base
10
10
  include Protocols::Oauth2
11
11
 
12
- attr_accessor :auth_url, :scope, :token_url, :user_info_url
12
+ attr_accessor :auth_url, :scope, :token_url, :user_info_url, :email_info_url
13
13
 
14
14
  def initialize
15
15
  super
16
16
 
17
- @site = 'https://api.linkedin.com'
18
- @auth_url = '/oauth/v2/authorization'
19
- @token_url = '/oauth/v2/accessToken'
20
- @user_info_url = 'https://api.linkedin.com/v2/me'
21
- @scope = 'r_liteprofile'
22
- @state = SecureRandom.hex(16)
17
+ @site = 'https://api.linkedin.com'
18
+ @auth_url = '/oauth/v2/authorization'
19
+ @token_url = '/oauth/v2/accessToken'
20
+ @user_info_url = 'https://api.linkedin.com/v2/me'
21
+ @email_info_url = 'https://api.linkedin.com/v2/emailAddress?q=members&projection=(elements*(handle~))'
22
+ @scope = 'r_liteprofile r_emailaddress'
23
+ @state = SecureRandom.hex(16)
23
24
  end
24
25
 
25
26
  def get_user_hash(access_token)
26
- response = access_token.get(user_info_url)
27
+ user_info = get_user_info(access_token)
27
28
 
28
29
  auth_hash(access_token).tap do |h|
29
- h[:user_info] = JSON.parse(response.body)
30
- h[:uid] = h[:user_info]['id']
30
+ h[:user_info] = user_info
31
+ h[:uid] = h[:user_info]['id']
31
32
  end
32
33
  end
33
34
 
@@ -45,6 +46,30 @@ module Sorcery
45
46
 
46
47
  get_access_token(args, token_url: token_url, token_method: :post)
47
48
  end
49
+
50
+ def get_user_info(access_token)
51
+ response = access_token.get(user_info_url)
52
+ user_info = JSON.parse(response.body)
53
+
54
+ if email_in_scope?
55
+ email = fetch_email(access_token)
56
+
57
+ return user_info.merge(email)
58
+ end
59
+
60
+ user_info
61
+ end
62
+
63
+ def email_in_scope?
64
+ scope.include?('r_emailaddress')
65
+ end
66
+
67
+ def fetch_email(access_token)
68
+ email_response = access_token.get(email_info_url)
69
+ email_info = JSON.parse(email_response.body)['elements'].first
70
+
71
+ email_info['handle~']
72
+ end
48
73
  end
49
74
  end
50
75
  end
@@ -37,7 +37,7 @@ module Sorcery
37
37
  user_hash[:user_info] = user_hash[:user_info]['response'][0]
38
38
  user_hash[:user_info]['full_name'] = [user_hash[:user_info]['first_name'], user_hash[:user_info]['last_name']].join(' ')
39
39
 
40
- user_hash[:uid] = user_hash[:user_info]['uid']
40
+ user_hash[:uid] = user_hash[:user_info]['id']
41
41
  user_hash[:user_info]['email'] = access_token.params['email']
42
42
  end
43
43
  user_hash
@@ -1,3 +1,3 @@
1
1
  module Sorcery
2
- VERSION = '0.14.0'.freeze
2
+ VERSION = '0.15.0'.freeze
3
3
  end
@@ -19,20 +19,20 @@ Gem::Specification.new do |s|
19
19
  ]
20
20
 
21
21
  # TODO: Cleanup formatting.
22
- # rubocop:disable Metrics/LineLength
22
+ # rubocop:disable Layout/LineLength
23
23
  s.description = 'Provides common authentication needs such as signing in/out, activating by email and resetting password.'
24
24
  s.summary = 'Magical authentication for Rails applications'
25
25
  s.homepage = 'https://github.com/Sorcery/sorcery'
26
26
  s.post_install_message = "As of version 1.0 oauth/oauth2 won't be automatically bundled so you may need to add those dependencies to your Gemfile.\n"
27
27
  s.post_install_message += 'You may need oauth2 if you use external providers such as any of these: https://github.com/Sorcery/sorcery/tree/master/lib/sorcery/providers'
28
- # rubocop:enable Metrics/LineLength
28
+ # rubocop:enable Layout/LineLength
29
29
 
30
30
  s.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
31
31
  s.require_paths = ['lib']
32
32
 
33
33
  s.licenses = ['MIT']
34
34
 
35
- s.required_ruby_version = '>= 2.2.9'
35
+ s.required_ruby_version = '>= 2.4.9'
36
36
 
37
37
  s.add_dependency 'bcrypt', '~> 3.1'
38
38
  s.add_dependency 'oauth', '~> 0.4', '>= 0.4.4'
@@ -155,7 +155,7 @@ describe SorceryController, active_record: true, type: :controller do
155
155
  expect(flash[:notice]).to eq 'Success!'
156
156
  end
157
157
 
158
- %i[github google liveid vk salesforce paypal slack wechat microsoft instagram auth0].each do |provider|
158
+ %i[github google liveid vk salesforce paypal slack wechat microsoft instagram auth0 discord].each do |provider|
159
159
  describe "with #{provider}" do
160
160
  it 'login_at redirects correctly' do
161
161
  get :"login_at_test_#{provider}"
@@ -217,6 +217,7 @@ describe SorceryController, active_record: true, type: :controller do
217
217
  instagram
218
218
  auth0
219
219
  line
220
+ discord
220
221
  ]
221
222
  )
222
223
 
@@ -261,6 +262,9 @@ describe SorceryController, active_record: true, type: :controller do
261
262
  sorcery_controller_external_property_set(:line, :key, "eYVNBjBDi33aa9GkA3w")
262
263
  sorcery_controller_external_property_set(:line, :secret, "XpbeSdCoaKSmQGSeokz5qcUATClRW5u08QWNfv71N8")
263
264
  sorcery_controller_external_property_set(:line, :callback_url, "http://blabla.com")
265
+ sorcery_controller_external_property_set(:discord, :key, 'eYVNBjBDi33aa9GkA3w')
266
+ sorcery_controller_external_property_set(:discord, :secret, 'XpbeSdCoaKSmQGSeokz5qcUATClRW5u08QWNfv71N8')
267
+ sorcery_controller_external_property_set(:discord, :callback_url, 'http://blabla.com')
264
268
  end
265
269
 
266
270
  after(:each) do
@@ -283,7 +287,7 @@ describe SorceryController, active_record: true, type: :controller do
283
287
  expect(ActionMailer::Base.deliveries.size).to eq old_size
284
288
  end
285
289
 
286
- %i[github google liveid vk salesforce paypal wechat microsoft instagram auth0].each do |provider|
290
+ %i[github google liveid vk salesforce paypal wechat microsoft instagram auth0 discord].each do |provider|
287
291
  it "does not send activation email to external users (#{provider})" do
288
292
  old_size = ActionMailer::Base.deliveries.size
289
293
  create_new_external_user provider
@@ -307,7 +311,7 @@ describe SorceryController, active_record: true, type: :controller do
307
311
  sorcery_reload!(%i[activity_logging external])
308
312
  end
309
313
 
310
- %w[facebook github google liveid vk salesforce slack].each do |provider|
314
+ %w[facebook github google liveid vk salesforce slack discord].each do |provider|
311
315
  context "when #{provider}" do
312
316
  before(:each) do
313
317
  sorcery_controller_property_set(:register_login_time, true)
@@ -346,7 +350,7 @@ describe SorceryController, active_record: true, type: :controller do
346
350
 
347
351
  let(:user) { double('user', id: 42) }
348
352
 
349
- %w[facebook github google liveid vk salesforce slack].each do |provider|
353
+ %w[facebook github google liveid vk salesforce slack discord].each do |provider|
350
354
  context "when #{provider}" do
351
355
  before(:each) do
352
356
  sorcery_model_property_set(:authentications_class, Authentication)
@@ -427,7 +431,7 @@ describe SorceryController, active_record: true, type: :controller do
427
431
  # response for VK auth
428
432
  'response' => [
429
433
  {
430
- 'uid' => '123',
434
+ 'id' => '123',
431
435
  'first_name' => 'Noam',
432
436
  'last_name' => 'Ben Ari'
433
437
  }
@@ -479,6 +483,7 @@ describe SorceryController, active_record: true, type: :controller do
479
483
  instagram
480
484
  auth0
481
485
  line
486
+ discord
482
487
  ]
483
488
  )
484
489
  sorcery_controller_external_property_set(:facebook, :key, 'eYVNBjBDi33aa9GkA3w')
@@ -521,6 +526,9 @@ describe SorceryController, active_record: true, type: :controller do
521
526
  sorcery_controller_external_property_set(:line, :key, "eYVNBjBDi33aa9GkA3w")
522
527
  sorcery_controller_external_property_set(:line, :secret, "XpbeSdCoaKSmQGSeokz5qcUATClRW5u08QWNfv71N8")
523
528
  sorcery_controller_external_property_set(:line, :callback_url, "http://blabla.com")
529
+ sorcery_controller_external_property_set(:discord, :key, 'eYVNBjBDi33aa9GkA3w')
530
+ sorcery_controller_external_property_set(:discord, :secret, 'XpbeSdCoaKSmQGSeokz5qcUATClRW5u08QWNfv71N8')
531
+ sorcery_controller_external_property_set(:discord, :callback_url, 'http://blabla.com')
524
532
  end
525
533
 
526
534
  def provider_url(provider)
@@ -535,7 +543,8 @@ describe SorceryController, active_record: true, type: :controller do
535
543
  wechat: "https://open.weixin.qq.com/connect/qrconnect?appid=#{::Sorcery::Controller::Config.wechat.key}&redirect_uri=http%3A%2F%2Fblabla.com&response_type=code&scope=snsapi_login&state=#wechat_redirect",
536
544
  microsoft: "https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=#{::Sorcery::Controller::Config.microsoft.key}&display&redirect_uri=http%3A%2F%2Fblabla.com&response_type=code&scope=openid+email+https%3A%2F%2Fgraph.microsoft.com%2FUser.Read&state",
537
545
  instagram: "https://api.instagram.com/oauth/authorize?client_id=#{::Sorcery::Controller::Config.instagram.key}&display&redirect_uri=http%3A%2F%2Fblabla.com&response_type=code&scope=#{::Sorcery::Controller::Config.instagram.scope}&state",
538
- auth0: "https://sorcery-test.auth0.com/authorize?client_id=#{::Sorcery::Controller::Config.auth0.key}&display&redirect_uri=http%3A%2F%2Fblabla.com&response_type=code&scope=openid+profile+email&state"
546
+ auth0: "https://sorcery-test.auth0.com/authorize?client_id=#{::Sorcery::Controller::Config.auth0.key}&display&redirect_uri=http%3A%2F%2Fblabla.com&response_type=code&scope=openid+profile+email&state",
547
+ discord: "https://discordapp.com/api/oauth2/authorize?client_id=#{::Sorcery::Controller::Config.discord.key}&display&redirect_uri=http%3A%2F%2Fblabla.com&response_type=code&scope=identify&state"
539
548
  }[provider]
540
549
  end
541
550
  end
@@ -6,14 +6,19 @@ describe SorceryController, type: :controller do
6
6
  # ----------------- REMEMBER ME -----------------------
7
7
  context 'with remember me features' do
8
8
  before(:all) do
9
+ if SORCERY_ORM == :active_record
10
+ MigrationHelper.migrate("#{Rails.root}/db/migrate/remember_me")
11
+ User.reset_column_information
12
+ end
13
+
9
14
  sorcery_reload!([:remember_me])
10
15
  end
11
16
 
12
- # TODO: Unused, remove?
13
- # after(:each) do
14
- # session = nil
15
- # cookies = nil
16
- # end
17
+ after(:all) do
18
+ if SORCERY_ORM == :active_record
19
+ MigrationHelper.rollback("#{Rails.root}/db/migrate/remember_me")
20
+ end
21
+ end
17
22
 
18
23
  before(:each) do
19
24
  allow(user).to receive(:remember_me_token)
@@ -32,19 +37,17 @@ describe SorceryController, type: :controller do
32
37
  end
33
38
 
34
39
  it 'clears cookie on forget_me!' do
35
- cookies['remember_me_token'] = { value: 'asd54234dsfsd43534', expires: 3600 }
36
- get :test_logout
40
+ request.cookies[:remember_me_token] = { value: 'asd54234dsfsd43534', expires: 3600 }
41
+ get :test_logout_with_forget_me
37
42
 
38
- pending 'Test previously broken, functionality might not be working here.'
39
- expect(cookies['remember_me_token']).to be_nil
43
+ expect(response.cookies[:remember_me_token]).to be_nil
40
44
  end
41
45
 
42
46
  it 'clears cookie on force_forget_me!' do
43
- cookies['remember_me_token'] = { value: 'asd54234dsfsd43534', expires: 3600 }
47
+ request.cookies[:remember_me_token] = { value: 'asd54234dsfsd43534', expires: 3600 }
44
48
  get :test_logout_with_force_forget_me
45
49
 
46
- pending 'Test previously broken, functionality might not be working here.'
47
- expect(cookies['remember_me_token']).to be_nil
50
+ expect(response.cookies[:remember_me_token]).to be_nil
48
51
  end
49
52
 
50
53
  it 'login(email,password,remember_me) logs user in and remembers' do
@@ -150,6 +150,16 @@ describe SorceryController, type: :controller do
150
150
  end
151
151
  end
152
152
 
153
+ it 'require_login before_action does not save the url for JSON requests' do
154
+ get :some_action, format: :json
155
+ expect(session[:return_to_url]).to be_nil
156
+ end
157
+
158
+ it 'require_login before_action does not save the url for XHR requests' do
159
+ get :some_action, xhr: true
160
+ expect(session[:return_to_url]).to be_nil
161
+ end
162
+
153
163
  it 'on successful login the user is redirected to the url he originally wanted' do
154
164
  session[:return_to_url] = 'http://test.host/some_action'
155
165
  post :test_return_to, params: { email: 'bla@bla.com', password: 'secret' }
@@ -161,7 +171,7 @@ describe SorceryController, type: :controller do
161
171
  # --- auto_login(user) ---
162
172
  specify { should respond_to(:auto_login) }
163
173
 
164
- it 'auto_login(user) los in a user instance' do
174
+ it 'auto_login(user) logs in a user instance' do
165
175
  session[:user_id] = nil
166
176
  subject.auto_login(user)
167
177
 
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'sorcery/providers/base'
5
+
6
+ describe Sorcery::Providers::ExampleProvider do
7
+ before(:all) do
8
+ sorcery_reload!([:external])
9
+ sorcery_controller_property_set(:external_providers, [:example_provider])
10
+ end
11
+
12
+ context 'fetching a multi-word custom provider' do
13
+ it 'returns the provider' do
14
+ expect(Sorcery::Controller::Config.example_provider).to be_a(Sorcery::Providers::ExampleProvider)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'sorcery/providers/base'
5
+
6
+ describe Sorcery::Providers::Example do
7
+ before(:all) do
8
+ sorcery_reload!([:external])
9
+ sorcery_controller_property_set(:external_providers, [:example])
10
+ end
11
+
12
+ context 'fetching a single-word custom provider' do
13
+ it 'returns the provider' do
14
+ expect(Sorcery::Controller::Config.example).to be_a(Sorcery::Providers::Example)
15
+ end
16
+ end
17
+ end
@@ -6,6 +6,7 @@ class SorceryController < ActionController::Base
6
6
  before_action :require_login_from_http_basic, only: [:test_http_basic_auth]
7
7
  before_action :require_login, only: %i[
8
8
  test_logout
9
+ test_logout_with_forget_me
9
10
  test_logout_with_force_forget_me
10
11
  test_should_be_logged_in
11
12
  some_action
@@ -50,6 +51,13 @@ class SorceryController < ActionController::Base
50
51
  head :ok
51
52
  end
52
53
 
54
+ def test_logout_with_forget_me
55
+ remember_me!
56
+ forget_me!
57
+ logout
58
+ head :ok
59
+ end
60
+
53
61
  def test_logout_with_force_forget_me
54
62
  remember_me!
55
63
  force_forget_me!
@@ -158,6 +166,10 @@ class SorceryController < ActionController::Base
158
166
  login_at(:auth0)
159
167
  end
160
168
 
169
+ def login_at_test_discord
170
+ login_at(:discord)
171
+ end
172
+
161
173
  def test_login_from_twitter
162
174
  if (@user = login_from(:twitter))
163
175
  redirect_to 'bla', notice: 'Success!'
@@ -280,6 +292,14 @@ class SorceryController < ActionController::Base
280
292
  end
281
293
  end
282
294
 
295
+ def test_login_from_discord
296
+ if (@user = login_from(:discord))
297
+ redirect_to 'bla', notice: 'Success!'
298
+ else
299
+ redirect_to 'blu', alert: 'Failed!'
300
+ end
301
+ end
302
+
283
303
  def test_return_to_with_external_twitter
284
304
  if (@user = login_from(:twitter))
285
305
  redirect_back_or_to 'bla', notice: 'Success!'
@@ -402,6 +422,14 @@ class SorceryController < ActionController::Base
402
422
  end
403
423
  end
404
424
 
425
+ def test_return_to_with_external_discord
426
+ if (@user = login_from(:discord))
427
+ redirect_back_or_to 'bla', notice: 'Success!'
428
+ else
429
+ redirect_to 'blu', alert: 'Failed!'
430
+ end
431
+ end
432
+
405
433
  def test_create_from_provider
406
434
  provider = params[:provider]
407
435
  login_from(provider)
@@ -11,6 +11,7 @@ AppRoot::Application.routes.draw do
11
11
  get :test_login_from_cookie
12
12
  get :test_login_from
13
13
  get :test_logout_with_remember
14
+ get :test_logout_with_forget_me
14
15
  get :test_logout_with_force_forget_me
15
16
  get :test_invalidate_active_session
16
17
  get :test_should_be_logged_in
@@ -33,6 +34,7 @@ AppRoot::Application.routes.draw do
33
34
  get :test_login_from_instagram
34
35
  get :test_login_from_auth0
35
36
  get :test_login_from_line
37
+ get :test_login_from_discord
36
38
  get :login_at_test
37
39
  get :login_at_test_twitter
38
40
  get :login_at_test_facebook
@@ -49,6 +51,7 @@ AppRoot::Application.routes.draw do
49
51
  get :login_at_test_instagram
50
52
  get :login_at_test_auth0
51
53
  get :login_at_test_line
54
+ get :login_at_test_discord
52
55
  get :test_return_to_with_external
53
56
  get :test_return_to_with_external_twitter
54
57
  get :test_return_to_with_external_facebook
@@ -65,6 +68,7 @@ AppRoot::Application.routes.draw do
65
68
  get :test_return_to_with_external_instagram
66
69
  get :test_return_to_with_external_auth0
67
70
  get :test_return_to_with_external_line
71
+ get :test_return_to_with_external_discord
68
72
  get :test_http_basic_auth
69
73
  get :some_action_making_a_non_persisted_change_to_the_user
70
74
  post :test_login_with_remember
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'sorcery/providers/base'
4
+
5
+ module Sorcery
6
+ module Providers
7
+ class Example < Base
8
+ include Protocols::Oauth2
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'sorcery/providers/base'
4
+
5
+ module Sorcery
6
+ module Providers
7
+ class ExampleProvider < Base
8
+ include Protocols::Oauth2
9
+ end
10
+ end
11
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sorcery
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.14.0
4
+ version: 0.15.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Noam Ben Ari
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2019-05-23 00:00:00.000000000 Z
15
+ date: 2020-05-02 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: bcrypt
@@ -52,22 +52,22 @@ dependencies:
52
52
  name: oauth2
53
53
  requirement: !ruby/object:Gem::Requirement
54
54
  requirements:
55
- - - "~>"
56
- - !ruby/object:Gem::Version
57
- version: '1.0'
58
55
  - - ">="
59
56
  - !ruby/object:Gem::Version
60
57
  version: 0.8.0
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '1.0'
61
61
  type: :runtime
62
62
  prerelease: false
63
63
  version_requirements: !ruby/object:Gem::Requirement
64
64
  requirements:
65
- - - "~>"
66
- - !ruby/object:Gem::Version
67
- version: '1.0'
68
65
  - - ">="
69
66
  - !ruby/object:Gem::Version
70
67
  version: 0.8.0
68
+ - - "~>"
69
+ - !ruby/object:Gem::Version
70
+ version: '1.0'
71
71
  - !ruby/object:Gem::Dependency
72
72
  name: byebug
73
73
  requirement: !ruby/object:Gem::Requirement
@@ -254,6 +254,7 @@ files:
254
254
  - lib/sorcery/protocols/oauth2.rb
255
255
  - lib/sorcery/providers/auth0.rb
256
256
  - lib/sorcery/providers/base.rb
257
+ - lib/sorcery/providers/discord.rb
257
258
  - lib/sorcery/providers/facebook.rb
258
259
  - lib/sorcery/providers/github.rb
259
260
  - lib/sorcery/providers/google.rb
@@ -295,10 +296,13 @@ files:
295
296
  - spec/controllers/controller_session_timeout_spec.rb
296
297
  - spec/controllers/controller_spec.rb
297
298
  - spec/orm/active_record.rb
299
+ - spec/providers/example_provider_spec.rb
300
+ - spec/providers/example_spec.rb
298
301
  - spec/providers/vk_spec.rb
299
302
  - spec/rails_app/app/active_record/authentication.rb
300
303
  - spec/rails_app/app/active_record/user.rb
301
304
  - spec/rails_app/app/active_record/user_provider.rb
305
+ - spec/rails_app/app/assets/config/manifest.js
302
306
  - spec/rails_app/app/controllers/sorcery_controller.rb
303
307
  - spec/rails_app/app/helpers/application_helper.rb
304
308
  - spec/rails_app/app/mailers/sorcery_mailer.rb
@@ -352,6 +356,8 @@ files:
352
356
  - spec/spec.opts
353
357
  - spec/spec_helper.rb
354
358
  - spec/support/migration_helper.rb
359
+ - spec/support/providers/example.rb
360
+ - spec/support/providers/example_provider.rb
355
361
  homepage: https://github.com/Sorcery/sorcery
356
362
  licenses:
357
363
  - MIT
@@ -366,15 +372,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
366
372
  requirements:
367
373
  - - ">="
368
374
  - !ruby/object:Gem::Version
369
- version: 2.2.9
375
+ version: 2.4.9
370
376
  required_rubygems_version: !ruby/object:Gem::Requirement
371
377
  requirements:
372
378
  - - ">="
373
379
  - !ruby/object:Gem::Version
374
380
  version: '0'
375
381
  requirements: []
376
- rubyforge_project:
377
- rubygems_version: 2.7.7
382
+ rubygems_version: 3.0.8
378
383
  signing_key:
379
384
  specification_version: 4
380
385
  summary: Magical authentication for Rails applications