sorcery 0.11.0 → 0.16.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (116) hide show
  1. checksums.yaml +5 -5
  2. data/.github/FUNDING.yml +1 -0
  3. data/.github/ISSUE_TEMPLATE.md +20 -0
  4. data/.github/PULL_REQUEST_TEMPLATE.md +5 -0
  5. data/.github/workflows/ruby.yml +49 -0
  6. data/.rubocop.yml +55 -0
  7. data/.rubocop_todo.yml +163 -0
  8. data/CHANGELOG.md +84 -0
  9. data/CODE_OF_CONDUCT.md +14 -0
  10. data/Gemfile +2 -2
  11. data/{LICENSE.txt → LICENSE.md} +1 -1
  12. data/README.md +34 -8
  13. data/Rakefile +3 -1
  14. data/SECURITY.md +19 -0
  15. data/gemfiles/rails_52.gemfile +7 -0
  16. data/gemfiles/rails_60.gemfile +7 -0
  17. data/lib/generators/sorcery/USAGE +1 -1
  18. data/lib/generators/sorcery/helpers.rb +4 -0
  19. data/lib/generators/sorcery/install_generator.rb +21 -21
  20. data/lib/generators/sorcery/templates/initializer.rb +176 -69
  21. data/lib/generators/sorcery/templates/migration/activity_logging.rb +5 -5
  22. data/lib/generators/sorcery/templates/migration/brute_force_protection.rb +4 -4
  23. data/lib/generators/sorcery/templates/migration/core.rb +4 -4
  24. data/lib/generators/sorcery/templates/migration/external.rb +3 -3
  25. data/lib/generators/sorcery/templates/migration/magic_login.rb +9 -0
  26. data/lib/generators/sorcery/templates/migration/remember_me.rb +3 -3
  27. data/lib/generators/sorcery/templates/migration/reset_password.rb +5 -4
  28. data/lib/generators/sorcery/templates/migration/user_activation.rb +4 -4
  29. data/lib/sorcery.rb +2 -0
  30. data/lib/sorcery/adapters/active_record_adapter.rb +4 -3
  31. data/lib/sorcery/adapters/mongoid_adapter.rb +23 -11
  32. data/lib/sorcery/controller.rb +26 -15
  33. data/lib/sorcery/controller/config.rb +7 -5
  34. data/lib/sorcery/controller/submodules/activity_logging.rb +9 -3
  35. data/lib/sorcery/controller/submodules/external.rb +49 -33
  36. data/lib/sorcery/controller/submodules/http_basic_auth.rb +2 -0
  37. data/lib/sorcery/controller/submodules/remember_me.rb +3 -8
  38. data/lib/sorcery/controller/submodules/session_timeout.rb +28 -5
  39. data/lib/sorcery/crypto_providers/aes256.rb +2 -1
  40. data/lib/sorcery/crypto_providers/bcrypt.rb +8 -2
  41. data/lib/sorcery/engine.rb +16 -3
  42. data/lib/sorcery/model.rb +14 -10
  43. data/lib/sorcery/model/config.rb +12 -4
  44. data/lib/sorcery/model/submodules/brute_force_protection.rb +6 -7
  45. data/lib/sorcery/model/submodules/external.rb +19 -3
  46. data/lib/sorcery/model/submodules/magic_login.rb +130 -0
  47. data/lib/sorcery/model/submodules/reset_password.rb +25 -2
  48. data/lib/sorcery/model/submodules/user_activation.rb +1 -1
  49. data/lib/sorcery/model/temporary_token.rb +3 -1
  50. data/lib/sorcery/protocols/oauth.rb +1 -0
  51. data/lib/sorcery/providers/auth0.rb +46 -0
  52. data/lib/sorcery/providers/battlenet.rb +51 -0
  53. data/lib/sorcery/providers/discord.rb +52 -0
  54. data/lib/sorcery/providers/heroku.rb +1 -0
  55. data/lib/sorcery/providers/instagram.rb +73 -0
  56. data/lib/sorcery/providers/line.rb +63 -0
  57. data/lib/sorcery/providers/linkedin.rb +45 -36
  58. data/lib/sorcery/providers/vk.rb +5 -4
  59. data/lib/sorcery/providers/wechat.rb +8 -6
  60. data/lib/sorcery/test_helpers/internal.rb +5 -4
  61. data/lib/sorcery/test_helpers/internal/rails.rb +11 -11
  62. data/lib/sorcery/test_helpers/rails/request.rb +20 -0
  63. data/lib/sorcery/version.rb +1 -1
  64. data/sorcery.gemspec +27 -11
  65. data/spec/active_record/user_activation_spec.rb +2 -2
  66. data/spec/active_record/user_activity_logging_spec.rb +2 -2
  67. data/spec/active_record/user_brute_force_protection_spec.rb +2 -2
  68. data/spec/active_record/user_magic_login_spec.rb +15 -0
  69. data/spec/active_record/user_oauth_spec.rb +2 -2
  70. data/spec/active_record/user_remember_me_spec.rb +2 -2
  71. data/spec/active_record/user_reset_password_spec.rb +2 -2
  72. data/spec/active_record/user_spec.rb +0 -10
  73. data/spec/controllers/controller_http_basic_auth_spec.rb +1 -1
  74. data/spec/controllers/controller_oauth2_spec.rb +230 -123
  75. data/spec/controllers/controller_oauth_spec.rb +13 -7
  76. data/spec/controllers/controller_remember_me_spec.rb +16 -8
  77. data/spec/controllers/controller_session_timeout_spec.rb +90 -3
  78. data/spec/controllers/controller_spec.rb +13 -3
  79. data/spec/orm/active_record.rb +2 -2
  80. data/spec/providers/example_provider_spec.rb +17 -0
  81. data/spec/providers/example_spec.rb +17 -0
  82. data/spec/providers/vk_spec.rb +42 -0
  83. data/spec/rails_app/app/assets/config/manifest.js +1 -0
  84. data/spec/rails_app/app/controllers/application_controller.rb +2 -0
  85. data/spec/rails_app/app/controllers/sorcery_controller.rb +152 -33
  86. data/spec/rails_app/app/mailers/sorcery_mailer.rb +7 -0
  87. data/spec/rails_app/app/views/sorcery_mailer/magic_login_email.html.erb +13 -0
  88. data/spec/rails_app/app/views/sorcery_mailer/magic_login_email.text.erb +6 -0
  89. data/spec/rails_app/config/application.rb +8 -3
  90. data/spec/rails_app/config/boot.rb +1 -1
  91. data/spec/rails_app/config/environment.rb +1 -1
  92. data/spec/rails_app/config/routes.rb +17 -0
  93. data/spec/rails_app/config/secrets.yml +4 -0
  94. data/spec/rails_app/db/migrate/activity_logging/20101224223624_add_activity_logging_to_users.rb +2 -2
  95. data/spec/rails_app/db/migrate/invalidate_active_sessions/20180221093235_add_invalidate_active_sessions_before_to_users.rb +9 -0
  96. data/spec/rails_app/db/migrate/magic_login/20170924151831_add_magic_login_to_users.rb +17 -0
  97. data/spec/rails_app/db/migrate/reset_password/20101224223622_add_reset_password_to_users.rb +2 -0
  98. data/spec/rails_app/db/schema.rb +7 -9
  99. data/spec/shared_examples/user_magic_login_shared_examples.rb +150 -0
  100. data/spec/shared_examples/user_oauth_shared_examples.rb +1 -1
  101. data/spec/shared_examples/user_remember_me_shared_examples.rb +1 -1
  102. data/spec/shared_examples/user_reset_password_shared_examples.rb +37 -5
  103. data/spec/shared_examples/user_shared_examples.rb +104 -43
  104. data/spec/sorcery_crypto_providers_spec.rb +61 -1
  105. data/spec/sorcery_temporary_token_spec.rb +27 -0
  106. data/spec/spec.opts +1 -1
  107. data/spec/spec_helper.rb +2 -2
  108. data/spec/support/migration_helper.rb +29 -0
  109. data/spec/support/providers/example.rb +11 -0
  110. data/spec/support/providers/example_provider.rb +11 -0
  111. metadata +97 -34
  112. data/.travis.yml +0 -57
  113. data/gemfiles/active_record-rails40.gemfile +0 -7
  114. data/gemfiles/active_record-rails41.gemfile +0 -7
  115. data/gemfiles/active_record-rails42.gemfile +0 -7
  116. data/spec/rails_app/config/initializers/secret_token.rb +0 -7
@@ -20,7 +20,7 @@ def stub_all_oauth_requests!
20
20
  'in_reply_to_status_id_str' => nil, 'created_at' => 'Sun Mar 06 23:01:12 +0000 2011',
21
21
  'contributors' => nil, 'place' => nil, 'retweeted' => false, 'in_reply_to_status_id' => nil,
22
22
  'in_reply_to_user_id_str' => nil, 'coordinates' => nil, 'retweet_count' => 0,
23
- 'id' => 44533012284706816, 'id_str' => '44533012284706816'
23
+ 'id' => 44_533_012_284_706_816, 'id_str' => '44533012284706816'
24
24
  },
25
25
  'show_all_inline_media' => false, 'geo_enabled' => true,
26
26
  'profile_sidebar_border_color' => 'a8c7f7', 'url' => nil, 'followers_count' => 10,
@@ -32,7 +32,7 @@ def stub_all_oauth_requests!
32
32
  'is_translator' => false, 'contributors_enabled' => false, 'protected' => false,
33
33
  'follow_request_sent' => false, 'time_zone' => 'Greenland', 'profile_text_color' => '333333',
34
34
  'name' => 'Noam Ben Ari', 'friends_count' => 10, 'profile_sidebar_fill_color' => 'C0DFEC',
35
- 'id' => 123, 'id_str' => '91434812', 'profile_background_tile' => false, 'utc_offset' => -10800
35
+ 'id' => 123, 'id_str' => '91434812', 'profile_background_tile' => false, 'utc_offset' => -10_800
36
36
  }.to_json
37
37
 
38
38
  session[:request_token] = req_token.token
@@ -50,7 +50,7 @@ describe SorceryController, type: :controller do
50
50
 
51
51
  before(:all) do
52
52
  sorcery_reload!([:external])
53
- sorcery_controller_property_set(:external_providers, [:twitter, :jira])
53
+ sorcery_controller_property_set(:external_providers, %i[twitter jira])
54
54
  sorcery_controller_external_property_set(:twitter, :key, 'eYVNBjBDi33aa9GkA3w')
55
55
  sorcery_controller_external_property_set(:twitter, :secret, 'XpbeSdCoaKSmQGSeokz5qcUATClRW5u08QWNfv71N8')
56
56
  sorcery_controller_external_property_set(:twitter, :callback_url, 'http://blabla.com')
@@ -84,11 +84,17 @@ describe SorceryController, type: :controller do
84
84
  end
85
85
 
86
86
  context 'when callback_url begin with http://' do
87
+ before do
88
+ sorcery_controller_external_property_set(:twitter, :callback_url, '/oauth/twitter/callback')
89
+ end
87
90
  it 'login_at redirects correctly', pending: true do
88
91
  get :login_at_test
89
92
  expect(response).to be_a_redirect
90
93
  expect(response).to redirect_to('http://myapi.com/oauth/authorize?oauth_callback=http%3A%2F%2Fblabla.com&oauth_token=')
91
94
  end
95
+ after do
96
+ sorcery_controller_external_property_set(:twitter, :callback_url, 'http://blabla.com')
97
+ end
92
98
  end
93
99
 
94
100
  it 'logins if user exists' do
@@ -179,7 +185,7 @@ describe SorceryController, type: :controller do
179
185
 
180
186
  describe SorceryController, 'OAuth with user activation features' do
181
187
  before(:all) do
182
- sorcery_reload!([:activity_logging, :external])
188
+ sorcery_reload!(%i[activity_logging external])
183
189
  end
184
190
 
185
191
  context 'when twitter' do
@@ -215,16 +221,16 @@ describe SorceryController, type: :controller do
215
221
  describe SorceryController, 'OAuth with session timeout features' do
216
222
  before(:all) do
217
223
  if SORCERY_ORM == :active_record
218
- ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate/external")
224
+ MigrationHelper.migrate("#{Rails.root}/db/migrate/external")
219
225
  User.reset_column_information
220
226
  end
221
227
 
222
- sorcery_reload!([:session_timeout, :external])
228
+ sorcery_reload!(%i[session_timeout external])
223
229
  end
224
230
 
225
231
  after(:all) do
226
232
  if SORCERY_ORM == :active_record
227
- ActiveRecord::Migrator.rollback("#{Rails.root}/db/migrate/external")
233
+ MigrationHelper.rollback("#{Rails.root}/db/migrate/external")
228
234
  end
229
235
  end
230
236
 
@@ -6,12 +6,18 @@ 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
- after(:each) do
13
- session = nil
14
- cookies = nil
17
+ after(:all) do
18
+ if SORCERY_ORM == :active_record
19
+ MigrationHelper.rollback("#{Rails.root}/db/migrate/remember_me")
20
+ end
15
21
  end
16
22
 
17
23
  before(:each) do
@@ -31,17 +37,17 @@ describe SorceryController, type: :controller do
31
37
  end
32
38
 
33
39
  it 'clears cookie on forget_me!' do
34
- cookies['remember_me_token'] == { value: 'asd54234dsfsd43534', expires: 3600 }
35
- get :test_logout
40
+ request.cookies[:remember_me_token] = { value: 'asd54234dsfsd43534', expires: 3600 }
41
+ get :test_logout_with_forget_me
36
42
 
37
- expect(cookies['remember_me_token']).to be_nil
43
+ expect(response.cookies[:remember_me_token]).to be_nil
38
44
  end
39
45
 
40
46
  it 'clears cookie on force_forget_me!' do
41
- cookies['remember_me_token'] == { value: 'asd54234dsfsd43534', expires: 3600 }
47
+ request.cookies[:remember_me_token] = { value: 'asd54234dsfsd43534', expires: 3600 }
42
48
  get :test_logout_with_force_forget_me
43
49
 
44
- expect(cookies['remember_me_token']).to be_nil
50
+ expect(response.cookies[:remember_me_token]).to be_nil
45
51
  end
46
52
 
47
53
  it 'login(email,password,remember_me) logs user in and remembers' do
@@ -80,6 +86,8 @@ describe SorceryController, type: :controller do
80
86
 
81
87
  expect(User.sorcery_adapter).to receive(:find_by_remember_me_token).with('token').and_return(user)
82
88
 
89
+ expect(subject).to receive(:after_remember_me!).with(user)
90
+
83
91
  get :test_login_from_cookie
84
92
 
85
93
  expect(assigns[:current_user]).to eq user
@@ -24,7 +24,7 @@ describe SorceryController, type: :controller do
24
24
  get :test_should_be_logged_in
25
25
 
26
26
  expect(session[:user_id]).not_to be_nil
27
- expect(response).to be_a_success
27
+ expect(response).to be_successful
28
28
  end
29
29
 
30
30
  it 'resets session after session timeout' do
@@ -36,6 +36,87 @@ describe SorceryController, type: :controller do
36
36
  expect(response).to be_a_redirect
37
37
  end
38
38
 
39
+ context "with 'invalidate_active_sessions_enabled'" do
40
+ it 'does not reset the session if invalidate_sessions_before is nil' do
41
+ sorcery_controller_property_set(:session_timeout_invalidate_active_sessions_enabled, true)
42
+ login_user user
43
+ allow(user).to receive(:invalidate_sessions_before) { nil }
44
+
45
+ get :test_should_be_logged_in
46
+
47
+ expect(session[:user_id]).not_to be_nil
48
+ expect(response).to be_successful
49
+ end
50
+
51
+ it 'does not reset the session if it was not created before invalidate_sessions_before' do
52
+ sorcery_controller_property_set(:session_timeout_invalidate_active_sessions_enabled, true)
53
+ login_user user
54
+ allow(user).to receive(:invalidate_sessions_before) { Time.now.in_time_zone - 10.minutes }
55
+
56
+ get :test_should_be_logged_in
57
+
58
+ expect(session[:user_id]).not_to be_nil
59
+ expect(response).to be_successful
60
+ end
61
+
62
+ it 'resets the session if the session was created before invalidate_sessions_before' do
63
+ sorcery_controller_property_set(:session_timeout_invalidate_active_sessions_enabled, true)
64
+ login_user user
65
+ allow(user).to receive(:invalidate_sessions_before) { Time.now.in_time_zone }
66
+ get :test_should_be_logged_in
67
+
68
+ expect(session[:user_id]).to be_nil
69
+ expect(response).to be_a_redirect
70
+ end
71
+
72
+ it 'resets active sessions on next action if invalidate_active_sessions! is called' do
73
+ sorcery_controller_property_set(:session_timeout_invalidate_active_sessions_enabled, true)
74
+ # precondition that the user is logged in
75
+ login_user user
76
+ get :test_should_be_logged_in
77
+ expect(response).to be_successful
78
+
79
+ allow(user).to receive(:send) { |_method, value| allow(user).to receive(:invalidate_sessions_before) { value } }
80
+ allow(user).to receive(:save)
81
+ get :test_invalidate_active_session
82
+ expect(response).to be_successful
83
+
84
+ get :test_should_be_logged_in
85
+ expect(session[:user_id]).to be_nil
86
+ expect(response).to be_a_redirect
87
+ end
88
+
89
+ it 'allows login after invalidate_active_sessions! is called' do
90
+ sorcery_controller_property_set(:session_timeout_invalidate_active_sessions_enabled, true)
91
+ # precondition that the user is logged in
92
+ login_user user
93
+ get :test_should_be_logged_in
94
+ expect(response).to be_successful
95
+
96
+ allow(user).to receive(:send) { |_method, value| allow(user).to receive(:invalidate_sessions_before) { value } }
97
+ allow(user).to receive(:save)
98
+ # Call to invalidate
99
+ get :test_invalidate_active_session
100
+ expect(response).to be_successful
101
+
102
+ # Check that existing sessions were logged out
103
+ get :test_should_be_logged_in
104
+ expect(session[:user_id]).to be_nil
105
+ expect(response).to be_a_redirect
106
+
107
+ # Check that new session is allowed to login
108
+ login_user user
109
+ get :test_should_be_logged_in
110
+ expect(response).to be_successful
111
+ expect(session[:user_id]).not_to be_nil
112
+
113
+ # Check an additional request to make sure not logged out on next request
114
+ get :test_should_be_logged_in
115
+ expect(response).to be_successful
116
+ expect(session[:user_id]).not_to be_nil
117
+ end
118
+ end
119
+
39
120
  it 'works if the session is stored as a string or a Time' do
40
121
  session[:login_time] = Time.now.to_s
41
122
  # TODO: ???
@@ -44,7 +125,7 @@ describe SorceryController, type: :controller do
44
125
  get :test_login, params: { email: 'bla@bla.com', password: 'secret' }
45
126
 
46
127
  expect(session[:user_id]).not_to be_nil
47
- expect(response).to be_a_success
128
+ expect(response).to be_successful
48
129
  end
49
130
 
50
131
  context "with 'session_timeout_from_last_action'" do
@@ -62,7 +143,7 @@ describe SorceryController, type: :controller do
62
143
  get :test_should_be_logged_in
63
144
 
64
145
  expect(session[:user_id]).not_to be_nil
65
- expect(response).to be_a_success
146
+ expect(response).to be_successful
66
147
  end
67
148
 
68
149
  it "with 'session_timeout_from_last_action' logs out if there was no activity" do
@@ -75,5 +156,11 @@ describe SorceryController, type: :controller do
75
156
  expect(response).to be_a_redirect
76
157
  end
77
158
  end
159
+
160
+ it 'registers login time on remember_me callback' do
161
+ expect(subject).to receive(:register_login_time).with(user)
162
+
163
+ subject.send(:after_remember_me!, user)
164
+ end
78
165
  end
79
166
  end
@@ -132,7 +132,7 @@ describe SorceryController, type: :controller do
132
132
  sorcery_controller_property_set(:not_authenticated_action, :test_not_authenticated_action)
133
133
  get :test_logout
134
134
 
135
- expect(response).to be_a_success
135
+ expect(response).to be_successful
136
136
  end
137
137
 
138
138
  it 'require_login before_action saves the url that the user originally wanted' do
@@ -143,13 +143,23 @@ describe SorceryController, type: :controller do
143
143
  end
144
144
 
145
145
  it 'require_login before_action does not save the url that the user originally wanted upon all non-get http methods' do
146
- [:post, :put, :delete].each do |m|
146
+ %i[post put delete].each do |m|
147
147
  send(m, :some_action)
148
148
 
149
149
  expect(session[:return_to_url]).to be_nil
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
 
@@ -9,11 +9,11 @@ class TestUser < ActiveRecord::Base
9
9
  end
10
10
 
11
11
  def setup_orm
12
- ActiveRecord::Migrator.migrate(migrations_path)
12
+ MigrationHelper.migrate(migrations_path)
13
13
  end
14
14
 
15
15
  def teardown_orm
16
- ActiveRecord::Migrator.rollback(migrations_path)
16
+ MigrationHelper.rollback(migrations_path)
17
17
  end
18
18
 
19
19
  def migrations_path
@@ -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
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+ require 'sorcery/providers/base'
3
+ require 'sorcery/providers/vk'
4
+ require 'webmock/rspec'
5
+
6
+ describe Sorcery::Providers::Vk do
7
+ include WebMock::API
8
+
9
+ let(:provider) { Sorcery::Controller::Config.vk }
10
+
11
+ before(:all) do
12
+ sorcery_reload!([:external])
13
+ sorcery_controller_property_set(:external_providers, [:vk])
14
+ sorcery_controller_external_property_set(:vk, :key, 'KEY')
15
+ sorcery_controller_external_property_set(:vk, :secret, 'SECRET')
16
+ end
17
+
18
+ def stub_vk_authorize
19
+ stub_request(:post, %r{https\:\/\/oauth\.vk\.com\/access_token}).to_return(
20
+ status: 200,
21
+ body: '{"access_token":"TOKEN","expires_in":86329,"user_id":1}',
22
+ headers: { 'content-type' => 'application/json' }
23
+ )
24
+ end
25
+
26
+ context 'getting user info hash' do
27
+ it 'should provide VK API version' do
28
+ stub_vk_authorize
29
+ sorcery_controller_external_property_set(:vk, :api_version, '5.71')
30
+
31
+ get_user = stub_request(
32
+ :get,
33
+ 'https://api.vk.com/method/getProfiles?access_token=TOKEN&fields=&scope=email&uids=1&v=5.71'
34
+ ).to_return(body: '{"response":[{"id":1}]}')
35
+
36
+ token = provider.process_callback({ code: 'CODE' }, nil)
37
+ provider.get_user_hash(token)
38
+
39
+ expect(get_user).to have_been_requested
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,2 @@
1
+ class ApplicationController < ActionController::Base
2
+ end
@@ -1,10 +1,16 @@
1
1
  require 'oauth'
2
2
 
3
- class SorceryController < ActionController::Base
3
+ class SorceryController < ApplicationController
4
4
  protect_from_forgery
5
5
 
6
6
  before_action :require_login_from_http_basic, only: [:test_http_basic_auth]
7
- before_action :require_login, only: [:test_logout, :test_logout_with_force_forget_me, :test_should_be_logged_in, :some_action]
7
+ before_action :require_login, only: %i[
8
+ test_logout
9
+ test_logout_with_forget_me
10
+ test_logout_with_force_forget_me
11
+ test_should_be_logged_in
12
+ some_action
13
+ ]
8
14
 
9
15
  def index; end
10
16
 
@@ -45,6 +51,13 @@ class SorceryController < ActionController::Base
45
51
  head :ok
46
52
  end
47
53
 
54
+ def test_logout_with_forget_me
55
+ remember_me!
56
+ forget_me!
57
+ logout
58
+ head :ok
59
+ end
60
+
48
61
  def test_logout_with_force_forget_me
49
62
  remember_me!
50
63
  force_forget_me!
@@ -52,6 +65,11 @@ class SorceryController < ActionController::Base
52
65
  head :ok
53
66
  end
54
67
 
68
+ def test_invalidate_active_session
69
+ invalidate_active_sessions!
70
+ head :ok
71
+ end
72
+
55
73
  def test_login_with_remember
56
74
  @user = login(params[:email], params[:password])
57
75
  remember_me!
@@ -132,12 +150,32 @@ class SorceryController < ActionController::Base
132
150
  login_at(:slack)
133
151
  end
134
152
 
153
+ def login_at_test_line
154
+ login_at(:line)
155
+ end
156
+
135
157
  def login_at_test_with_state
136
158
  login_at(:facebook, state: 'bla')
137
159
  end
138
160
 
161
+ def login_at_test_instagram
162
+ login_at(:instagram)
163
+ end
164
+
165
+ def login_at_test_auth0
166
+ login_at(:auth0)
167
+ end
168
+
169
+ def login_at_test_discord
170
+ login_at(:discord)
171
+ end
172
+
173
+ def login_at_test_battlenet
174
+ login_at(:battlenet)
175
+ end
176
+
139
177
  def test_login_from_twitter
140
- if @user = login_from(:twitter)
178
+ if (@user = login_from(:twitter))
141
179
  redirect_to 'bla', notice: 'Success!'
142
180
  else
143
181
  redirect_to 'blu', alert: 'Failed!'
@@ -147,7 +185,7 @@ class SorceryController < ActionController::Base
147
185
  alias test_login_from test_login_from_twitter
148
186
 
149
187
  def test_login_from_facebook
150
- if @user = login_from(:facebook)
188
+ if (@user = login_from(:facebook))
151
189
  redirect_to 'bla', notice: 'Success!'
152
190
  else
153
191
  redirect_to 'blu', alert: 'Failed!'
@@ -155,7 +193,7 @@ class SorceryController < ActionController::Base
155
193
  end
156
194
 
157
195
  def test_login_from_github
158
- if @user = login_from(:github)
196
+ if (@user = login_from(:github))
159
197
  redirect_to 'bla', notice: 'Success!'
160
198
  else
161
199
  redirect_to 'blu', alert: 'Failed!'
@@ -163,7 +201,7 @@ class SorceryController < ActionController::Base
163
201
  end
164
202
 
165
203
  def test_login_from_paypal
166
- if @user = login_from(:paypal)
204
+ if (@user = login_from(:paypal))
167
205
  redirect_to 'bla', notice: 'Success!'
168
206
  else
169
207
  redirect_to 'blu', alert: 'Failed!'
@@ -171,7 +209,7 @@ class SorceryController < ActionController::Base
171
209
  end
172
210
 
173
211
  def test_login_from_wechat
174
- if @user = login_from(:wechat)
212
+ if (@user = login_from(:wechat))
175
213
  redirect_to 'bla', notice: 'Success!'
176
214
  else
177
215
  redirect_to 'blu', alert: 'Failed!'
@@ -179,7 +217,7 @@ class SorceryController < ActionController::Base
179
217
  end
180
218
 
181
219
  def test_login_from_microsoft
182
- if @user = login_from(:microsoft)
220
+ if (@user = login_from(:microsoft))
183
221
  redirect_to 'bla', notice: 'Success!'
184
222
  else
185
223
  redirect_to 'blu', alert: 'Failed!'
@@ -187,7 +225,7 @@ class SorceryController < ActionController::Base
187
225
  end
188
226
 
189
227
  def test_login_from_google
190
- if @user = login_from(:google)
228
+ if (@user = login_from(:google))
191
229
  redirect_to 'bla', notice: 'Success!'
192
230
  else
193
231
  redirect_to 'blu', alert: 'Failed!'
@@ -195,7 +233,7 @@ class SorceryController < ActionController::Base
195
233
  end
196
234
 
197
235
  def test_login_from_liveid
198
- if @user = login_from(:liveid)
236
+ if (@user = login_from(:liveid))
199
237
  redirect_to 'bla', notice: 'Success!'
200
238
  else
201
239
  redirect_to 'blu', alert: 'Failed!'
@@ -203,7 +241,7 @@ class SorceryController < ActionController::Base
203
241
  end
204
242
 
205
243
  def test_login_from_vk
206
- if @user = login_from(:vk)
244
+ if (@user = login_from(:vk))
207
245
  redirect_to 'bla', notice: 'Success!'
208
246
  else
209
247
  redirect_to 'blu', alert: 'Failed!'
@@ -211,7 +249,7 @@ class SorceryController < ActionController::Base
211
249
  end
212
250
 
213
251
  def test_login_from_jira
214
- if @user = login_from(:jira)
252
+ if (@user = login_from(:jira))
215
253
  redirect_to 'bla', notice: 'Success!'
216
254
  else
217
255
  redirect_to 'blu', alert: 'Failed!'
@@ -219,7 +257,7 @@ class SorceryController < ActionController::Base
219
257
  end
220
258
 
221
259
  def test_login_from_salesforce
222
- if @user = login_from(:salesforce)
260
+ if (@user = login_from(:salesforce))
223
261
  redirect_to 'bla', notice: 'Success!'
224
262
  else
225
263
  redirect_to 'blu', alert: 'Failed!'
@@ -227,7 +265,47 @@ class SorceryController < ActionController::Base
227
265
  end
228
266
 
229
267
  def test_login_from_slack
230
- if @user = login_from(:slack)
268
+ if (@user = login_from(:slack))
269
+ redirect_to 'bla', notice: 'Success!'
270
+ else
271
+ redirect_to 'blu', alert: 'Failed!'
272
+ end
273
+ end
274
+
275
+ def test_login_from_instagram
276
+ if (@user = login_from(:instagram))
277
+ redirect_to 'bla', notice: 'Success!'
278
+ else
279
+ redirect_to 'blu', alert: 'Failed!'
280
+ end
281
+ end
282
+
283
+ def test_login_from_auth0
284
+ if (@user = login_from(:auth0))
285
+ redirect_to 'bla', notice: 'Success!'
286
+ else
287
+ redirect_to 'blu', alert: 'Failed!'
288
+ end
289
+ end
290
+
291
+ def test_login_from_line
292
+ if @user = login_from(:line)
293
+ redirect_to 'bla', notice: 'Success!'
294
+ else
295
+ redirect_to 'blu', alert: 'Failed!'
296
+ end
297
+ end
298
+
299
+ def test_login_from_discord
300
+ if (@user = login_from(:discord))
301
+ redirect_to 'bla', notice: 'Success!'
302
+ else
303
+ redirect_to 'blu', alert: 'Failed!'
304
+ end
305
+ end
306
+
307
+ def test_login_from_battlenet
308
+ if (@user = login_from(:battlenet))
231
309
  redirect_to 'bla', notice: 'Success!'
232
310
  else
233
311
  redirect_to 'blu', alert: 'Failed!'
@@ -235,7 +313,7 @@ class SorceryController < ActionController::Base
235
313
  end
236
314
 
237
315
  def test_return_to_with_external_twitter
238
- if @user = login_from(:twitter)
316
+ if (@user = login_from(:twitter))
239
317
  redirect_back_or_to 'bla', notice: 'Success!'
240
318
  else
241
319
  redirect_to 'blu', alert: 'Failed!'
@@ -243,7 +321,7 @@ class SorceryController < ActionController::Base
243
321
  end
244
322
 
245
323
  def test_return_to_with_external_jira
246
- if @user = login_from(:jira)
324
+ if (@user = login_from(:jira))
247
325
  redirect_back_or_to 'bla', notice: 'Success!'
248
326
  else
249
327
  redirect_to 'blu', alert: 'Failed!'
@@ -253,7 +331,7 @@ class SorceryController < ActionController::Base
253
331
  alias test_return_to_with_external test_return_to_with_external_twitter
254
332
 
255
333
  def test_return_to_with_external_facebook
256
- if @user = login_from(:facebook)
334
+ if (@user = login_from(:facebook))
257
335
  redirect_back_or_to 'bla', notice: 'Success!'
258
336
  else
259
337
  redirect_to 'blu', alert: 'Failed!'
@@ -261,7 +339,7 @@ class SorceryController < ActionController::Base
261
339
  end
262
340
 
263
341
  def test_return_to_with_external_github
264
- if @user = login_from(:github)
342
+ if (@user = login_from(:github))
265
343
  redirect_back_or_to 'bla', notice: 'Success!'
266
344
  else
267
345
  redirect_to 'blu', alert: 'Failed!'
@@ -269,7 +347,7 @@ class SorceryController < ActionController::Base
269
347
  end
270
348
 
271
349
  def test_return_to_with_external_paypal
272
- if @user = login_from(:paypal)
350
+ if (@user = login_from(:paypal))
273
351
  redirect_back_or_to 'bla', notice: 'Success!'
274
352
  else
275
353
  redirect_to 'blu', alert: 'Failed!'
@@ -277,7 +355,7 @@ class SorceryController < ActionController::Base
277
355
  end
278
356
 
279
357
  def test_return_to_with_external_wechat
280
- if @user = login_from(:wechat)
358
+ if (@user = login_from(:wechat))
281
359
  redirect_back_or_to 'bla', notice: 'Success!'
282
360
  else
283
361
  redirect_to 'blu', alert: 'Failed!'
@@ -285,7 +363,7 @@ class SorceryController < ActionController::Base
285
363
  end
286
364
 
287
365
  def test_return_to_with_external_microsoft
288
- if @user = login_from(:microsoft)
366
+ if (@user = login_from(:microsoft))
289
367
  redirect_back_or_to 'bla', notice: 'Success!'
290
368
  else
291
369
  redirect_to 'blu', alert: 'Failed!'
@@ -293,7 +371,7 @@ class SorceryController < ActionController::Base
293
371
  end
294
372
 
295
373
  def test_return_to_with_external_google
296
- if @user = login_from(:google)
374
+ if (@user = login_from(:google))
297
375
  redirect_back_or_to 'bla', notice: 'Success!'
298
376
  else
299
377
  redirect_to 'blu', alert: 'Failed!'
@@ -301,7 +379,7 @@ class SorceryController < ActionController::Base
301
379
  end
302
380
 
303
381
  def test_return_to_with_external_liveid
304
- if @user = login_from(:liveid)
382
+ if (@user = login_from(:liveid))
305
383
  redirect_back_or_to 'bla', notice: 'Success!'
306
384
  else
307
385
  redirect_to 'blu', alert: 'Failed!'
@@ -309,7 +387,7 @@ class SorceryController < ActionController::Base
309
387
  end
310
388
 
311
389
  def test_return_to_with_external_vk
312
- if @user = login_from(:vk)
390
+ if (@user = login_from(:vk))
313
391
  redirect_back_or_to 'bla', notice: 'Success!'
314
392
  else
315
393
  redirect_to 'blu', alert: 'Failed!'
@@ -317,7 +395,7 @@ class SorceryController < ActionController::Base
317
395
  end
318
396
 
319
397
  def test_return_to_with_external_salesforce
320
- if @user = login_from(:salesforce)
398
+ if (@user = login_from(:salesforce))
321
399
  redirect_back_or_to 'bla', notice: 'Success!'
322
400
  else
323
401
  redirect_to 'blu', alert: 'Failed!'
@@ -325,7 +403,47 @@ class SorceryController < ActionController::Base
325
403
  end
326
404
 
327
405
  def test_return_to_with_external_slack
328
- if @user = login_from(:slack)
406
+ if (@user = login_from(:slack))
407
+ redirect_back_or_to 'bla', notice: 'Success!'
408
+ else
409
+ redirect_to 'blu', alert: 'Failed!'
410
+ end
411
+ end
412
+
413
+ def test_return_to_with_external_instagram
414
+ if (@user = login_from(:instagram))
415
+ redirect_back_or_to 'bla', notice: 'Success!'
416
+ else
417
+ redirect_to 'blu', alert: 'Failed!'
418
+ end
419
+ end
420
+
421
+ def test_return_to_with_external_auth0
422
+ if (@user = login_from(:auth0))
423
+ redirect_back_or_to 'bla', notice: 'Success!'
424
+ else
425
+ redirect_to 'blu', alert: 'Failed!'
426
+ end
427
+ end
428
+
429
+ def test_return_to_with_external_line
430
+ if @user = login_from(:line)
431
+ redirect_back_or_to 'bla', notice: 'Success!'
432
+ else
433
+ redirect_to 'blu', alert: 'Failed!'
434
+ end
435
+ end
436
+
437
+ def test_return_to_with_external_discord
438
+ if (@user = login_from(:discord))
439
+ redirect_back_or_to 'bla', notice: 'Success!'
440
+ else
441
+ redirect_to 'blu', alert: 'Failed!'
442
+ end
443
+ end
444
+
445
+ def test_return_to_with_external_battlenet
446
+ if (@user = login_from(:battlenet))
329
447
  redirect_back_or_to 'bla', notice: 'Success!'
330
448
  else
331
449
  redirect_to 'blu', alert: 'Failed!'
@@ -335,7 +453,7 @@ class SorceryController < ActionController::Base
335
453
  def test_create_from_provider
336
454
  provider = params[:provider]
337
455
  login_from(provider)
338
- if @user = create_from(provider)
456
+ if (@user = create_from(provider))
339
457
  redirect_to 'bla', notice: 'Success!'
340
458
  else
341
459
  redirect_to 'blu', alert: 'Failed!'
@@ -344,12 +462,13 @@ class SorceryController < ActionController::Base
344
462
 
345
463
  def test_add_second_provider
346
464
  provider = params[:provider]
347
- if logged_in?
348
- if @user = add_provider_to_user(provider)
349
- redirect_to 'bla', notice: 'Success!'
350
- else
351
- redirect_to 'blu', alert: 'Failed!'
352
- end
465
+
466
+ return unless logged_in?
467
+
468
+ if (@user = add_provider_to_user(provider))
469
+ redirect_to 'bla', notice: 'Success!'
470
+ else
471
+ redirect_to 'blu', alert: 'Failed!'
353
472
  end
354
473
  end
355
474