sorcery 0.13.0 → 0.16.1
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/.github/FUNDING.yml +1 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +5 -0
- data/.github/workflows/ruby.yml +49 -0
- data/.rubocop.yml +2 -2
- data/.rubocop_todo.yml +157 -1
- data/CHANGELOG.md +49 -0
- data/CODE_OF_CONDUCT.md +14 -0
- data/Gemfile +1 -1
- data/README.md +4 -4
- data/Rakefile +3 -1
- data/SECURITY.md +19 -0
- data/gemfiles/rails_52.gemfile +7 -0
- data/gemfiles/rails_60.gemfile +7 -0
- data/lib/generators/sorcery/helpers.rb +4 -0
- data/lib/generators/sorcery/templates/initializer.rb +111 -85
- data/lib/generators/sorcery/templates/migration/activity_logging.rb +5 -5
- data/lib/generators/sorcery/templates/migration/brute_force_protection.rb +4 -4
- data/lib/generators/sorcery/templates/migration/core.rb +4 -4
- data/lib/generators/sorcery/templates/migration/external.rb +3 -3
- data/lib/generators/sorcery/templates/migration/magic_login.rb +4 -4
- data/lib/generators/sorcery/templates/migration/remember_me.rb +3 -3
- data/lib/generators/sorcery/templates/migration/reset_password.rb +5 -5
- data/lib/generators/sorcery/templates/migration/user_activation.rb +4 -4
- data/lib/sorcery/adapters/active_record_adapter.rb +2 -2
- data/lib/sorcery/controller.rb +4 -1
- data/lib/sorcery/controller/config.rb +6 -6
- data/lib/sorcery/controller/submodules/activity_logging.rb +5 -3
- data/lib/sorcery/controller/submodules/external.rb +4 -1
- data/lib/sorcery/controller/submodules/http_basic_auth.rb +1 -0
- data/lib/sorcery/controller/submodules/remember_me.rb +2 -1
- data/lib/sorcery/controller/submodules/session_timeout.rb +2 -0
- data/lib/sorcery/crypto_providers/aes256.rb +1 -1
- data/lib/sorcery/crypto_providers/bcrypt.rb +6 -1
- data/lib/sorcery/engine.rb +7 -1
- data/lib/sorcery/model.rb +6 -5
- data/lib/sorcery/model/config.rb +5 -0
- data/lib/sorcery/model/submodules/magic_login.rb +7 -4
- data/lib/sorcery/model/submodules/reset_password.rb +6 -2
- data/lib/sorcery/providers/battlenet.rb +51 -0
- data/lib/sorcery/providers/discord.rb +52 -0
- data/lib/sorcery/providers/line.rb +63 -0
- data/lib/sorcery/providers/linkedin.rb +45 -36
- data/lib/sorcery/providers/vk.rb +1 -1
- data/lib/sorcery/version.rb +1 -1
- data/sorcery.gemspec +5 -6
- data/spec/controllers/controller_oauth2_spec.rb +41 -6
- data/spec/controllers/controller_oauth_spec.rb +6 -0
- data/spec/controllers/controller_remember_me_spec.rb +15 -12
- data/spec/controllers/controller_spec.rb +11 -1
- data/spec/providers/example_provider_spec.rb +17 -0
- data/spec/providers/example_spec.rb +17 -0
- data/spec/rails_app/app/assets/config/manifest.js +1 -0
- data/spec/rails_app/app/controllers/application_controller.rb +2 -0
- data/spec/rails_app/app/controllers/sorcery_controller.rb +69 -1
- data/spec/rails_app/config/routes.rb +10 -0
- data/spec/shared_examples/user_reset_password_shared_examples.rb +18 -2
- data/spec/shared_examples/user_shared_examples.rb +63 -0
- data/spec/sorcery_crypto_providers_spec.rb +60 -0
- data/spec/support/migration_helper.rb +12 -2
- data/spec/support/providers/example.rb +11 -0
- data/spec/support/providers/example_provider.rb +11 -0
- metadata +25 -15
- data/.travis.yml +0 -38
- data/gemfiles/active_record_rails_40.gemfile +0 -6
- data/gemfiles/active_record_rails_41.gemfile +0 -6
- data/gemfiles/active_record_rails_42.gemfile +0 -6
@@ -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)
|
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
|
@@ -0,0 +1 @@
|
|
1
|
+
{}
|
@@ -1,11 +1,12 @@
|
|
1
1
|
require 'oauth'
|
2
2
|
|
3
|
-
class SorceryController <
|
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
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!
|
@@ -142,6 +150,10 @@ class SorceryController < ActionController::Base
|
|
142
150
|
login_at(:slack)
|
143
151
|
end
|
144
152
|
|
153
|
+
def login_at_test_line
|
154
|
+
login_at(:line)
|
155
|
+
end
|
156
|
+
|
145
157
|
def login_at_test_with_state
|
146
158
|
login_at(:facebook, state: 'bla')
|
147
159
|
end
|
@@ -154,6 +166,14 @@ class SorceryController < ActionController::Base
|
|
154
166
|
login_at(:auth0)
|
155
167
|
end
|
156
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
|
+
|
157
177
|
def test_login_from_twitter
|
158
178
|
if (@user = login_from(:twitter))
|
159
179
|
redirect_to 'bla', notice: 'Success!'
|
@@ -268,6 +288,30 @@ class SorceryController < ActionController::Base
|
|
268
288
|
end
|
269
289
|
end
|
270
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))
|
309
|
+
redirect_to 'bla', notice: 'Success!'
|
310
|
+
else
|
311
|
+
redirect_to 'blu', alert: 'Failed!'
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
271
315
|
def test_return_to_with_external_twitter
|
272
316
|
if (@user = login_from(:twitter))
|
273
317
|
redirect_back_or_to 'bla', notice: 'Success!'
|
@@ -382,6 +426,30 @@ class SorceryController < ActionController::Base
|
|
382
426
|
end
|
383
427
|
end
|
384
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))
|
447
|
+
redirect_back_or_to 'bla', notice: 'Success!'
|
448
|
+
else
|
449
|
+
redirect_to 'blu', alert: 'Failed!'
|
450
|
+
end
|
451
|
+
end
|
452
|
+
|
385
453
|
def test_create_from_provider
|
386
454
|
provider = params[:provider]
|
387
455
|
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
|
@@ -32,6 +33,9 @@ AppRoot::Application.routes.draw do
|
|
32
33
|
get :test_login_from_slack
|
33
34
|
get :test_login_from_instagram
|
34
35
|
get :test_login_from_auth0
|
36
|
+
get :test_login_from_line
|
37
|
+
get :test_login_from_discord
|
38
|
+
get :test_login_from_battlenet
|
35
39
|
get :login_at_test
|
36
40
|
get :login_at_test_twitter
|
37
41
|
get :login_at_test_facebook
|
@@ -47,6 +51,9 @@ AppRoot::Application.routes.draw do
|
|
47
51
|
get :login_at_test_slack
|
48
52
|
get :login_at_test_instagram
|
49
53
|
get :login_at_test_auth0
|
54
|
+
get :login_at_test_line
|
55
|
+
get :login_at_test_discord
|
56
|
+
get :login_at_test_battlenet
|
50
57
|
get :test_return_to_with_external
|
51
58
|
get :test_return_to_with_external_twitter
|
52
59
|
get :test_return_to_with_external_facebook
|
@@ -62,6 +69,9 @@ AppRoot::Application.routes.draw do
|
|
62
69
|
get :test_return_to_with_external_slack
|
63
70
|
get :test_return_to_with_external_instagram
|
64
71
|
get :test_return_to_with_external_auth0
|
72
|
+
get :test_return_to_with_external_line
|
73
|
+
get :test_return_to_with_external_discord
|
74
|
+
get :test_return_to_with_external_battlenet
|
65
75
|
get :test_http_basic_auth
|
66
76
|
get :some_action_making_a_non_persisted_change_to_the_user
|
67
77
|
post :test_login_with_remember
|
@@ -14,6 +14,8 @@ shared_examples_for 'rails_3_reset_password_model' do
|
|
14
14
|
context 'API' do
|
15
15
|
specify { expect(user).to respond_to :deliver_reset_password_instructions! }
|
16
16
|
|
17
|
+
specify { expect(user).to respond_to :change_password }
|
18
|
+
|
17
19
|
specify { expect(user).to respond_to :change_password! }
|
18
20
|
|
19
21
|
it 'responds to .load_from_reset_password_token' do
|
@@ -314,13 +316,27 @@ shared_examples_for 'rails_3_reset_password_model' do
|
|
314
316
|
end
|
315
317
|
end
|
316
318
|
|
317
|
-
it 'when change_password! is called, deletes reset_password_token' do
|
319
|
+
it 'when change_password! is called, deletes reset_password_token and calls #save!' do
|
318
320
|
user.deliver_reset_password_instructions!
|
319
321
|
|
320
322
|
expect(user.reset_password_token).not_to be_nil
|
323
|
+
expect(user).to_not receive(:save)
|
324
|
+
expect(user).to receive(:save!)
|
321
325
|
|
322
326
|
user.change_password!('blabulsdf')
|
323
|
-
|
327
|
+
|
328
|
+
expect(user.reset_password_token).to be_nil
|
329
|
+
end
|
330
|
+
|
331
|
+
it 'when change_password is called, deletes reset_password_token and calls #save' do
|
332
|
+
new_password = 'blabulsdf'
|
333
|
+
|
334
|
+
user.deliver_reset_password_instructions!
|
335
|
+
expect(user.reset_password_token).not_to be_nil
|
336
|
+
expect(user).to_not receive(:save!)
|
337
|
+
expect(user).to receive(:save)
|
338
|
+
|
339
|
+
user.change_password(new_password)
|
324
340
|
|
325
341
|
expect(user.reset_password_token).to be_nil
|
326
342
|
end
|
@@ -54,6 +54,13 @@ shared_examples_for 'rails_3_core_model' do
|
|
54
54
|
expect(User.sorcery_config.custom_encryption_provider).to eq Array
|
55
55
|
end
|
56
56
|
|
57
|
+
it "enables configuration option 'pepper'" do
|
58
|
+
pepper = '*$%&%*++'
|
59
|
+
sorcery_model_property_set(:pepper, pepper)
|
60
|
+
|
61
|
+
expect(User.sorcery_config.pepper).to eq pepper
|
62
|
+
end
|
63
|
+
|
57
64
|
it "enables configuration option 'salt_join_token'" do
|
58
65
|
salt_join_token = '--%%*&-'
|
59
66
|
sorcery_model_property_set(:salt_join_token, salt_join_token)
|
@@ -459,6 +466,14 @@ shared_examples_for 'rails_3_core_model' do
|
|
459
466
|
expect(User.encrypt(@text)).to eq Sorcery::CryptoProviders::SHA512.encrypt(@text)
|
460
467
|
end
|
461
468
|
|
469
|
+
it 'if encryption algo is bcrypt it works' do
|
470
|
+
sorcery_model_property_set(:encryption_algorithm, :bcrypt)
|
471
|
+
|
472
|
+
# comparison is done using BCrypt::Password#==(raw_token), not by String#==
|
473
|
+
expect(User.encrypt(@text)).to be_an_instance_of BCrypt::Password
|
474
|
+
expect(User.encrypt(@text)).to eq @text
|
475
|
+
end
|
476
|
+
|
462
477
|
it 'salt is random for each user and saved in db' do
|
463
478
|
sorcery_model_property_set(:salt_attribute_name, :salt)
|
464
479
|
|
@@ -488,6 +503,54 @@ shared_examples_for 'rails_3_core_model' do
|
|
488
503
|
|
489
504
|
expect(user.crypted_password).to eq Sorcery::CryptoProviders::SHA512.encrypt('secret', user.salt)
|
490
505
|
end
|
506
|
+
|
507
|
+
it 'if pepper is set uses it to encrypt' do
|
508
|
+
sorcery_model_property_set(:salt_attribute_name, :salt)
|
509
|
+
sorcery_model_property_set(:pepper, '++@^$')
|
510
|
+
sorcery_model_property_set(:encryption_algorithm, :bcrypt)
|
511
|
+
|
512
|
+
# password comparison is done using BCrypt::Password#==(raw_token), not String#==
|
513
|
+
bcrypt_password = BCrypt::Password.new(user.crypted_password)
|
514
|
+
allow(::BCrypt::Password).to receive(:create) do |token, options = {}|
|
515
|
+
# need to use common BCrypt's salt when genarating BCrypt::Password objects
|
516
|
+
# so that any generated password hashes can be compared each other
|
517
|
+
::BCrypt::Engine.hash_secret(token, bcrypt_password.salt)
|
518
|
+
end
|
519
|
+
|
520
|
+
expect(user.crypted_password).not_to eq Sorcery::CryptoProviders::BCrypt.encrypt('secret')
|
521
|
+
|
522
|
+
Sorcery::CryptoProviders::BCrypt.pepper = ''
|
523
|
+
|
524
|
+
expect(user.crypted_password).not_to eq Sorcery::CryptoProviders::BCrypt.encrypt('secret', user.salt)
|
525
|
+
|
526
|
+
Sorcery::CryptoProviders::BCrypt.pepper = User.sorcery_config.pepper
|
527
|
+
|
528
|
+
expect(user.crypted_password).to eq Sorcery::CryptoProviders::BCrypt.encrypt('secret', user.salt)
|
529
|
+
end
|
530
|
+
|
531
|
+
it 'if pepper is empty string (default) does not use pepper to encrypt' do
|
532
|
+
sorcery_model_property_set(:salt_attribute_name, :salt)
|
533
|
+
sorcery_model_property_set(:pepper, '')
|
534
|
+
sorcery_model_property_set(:encryption_algorithm, :bcrypt)
|
535
|
+
|
536
|
+
# password comparison is done using BCrypt::Password#==(raw_token), not String#==
|
537
|
+
bcrypt_password = BCrypt::Password.new(user.crypted_password)
|
538
|
+
allow(::BCrypt::Password).to receive(:create) do |token, options = {}|
|
539
|
+
# need to use common BCrypt's salt when genarating BCrypt::Password objects
|
540
|
+
# so that any generated password hashes can be compared each other
|
541
|
+
::BCrypt::Engine.hash_secret(token, bcrypt_password.salt)
|
542
|
+
end
|
543
|
+
|
544
|
+
expect(user.crypted_password).not_to eq Sorcery::CryptoProviders::BCrypt.encrypt('secret')
|
545
|
+
|
546
|
+
Sorcery::CryptoProviders::BCrypt.pepper = 'some_pepper'
|
547
|
+
|
548
|
+
expect(user.crypted_password).not_to eq Sorcery::CryptoProviders::BCrypt.encrypt('secret', user.salt)
|
549
|
+
|
550
|
+
Sorcery::CryptoProviders::BCrypt.pepper = User.sorcery_config.pepper
|
551
|
+
|
552
|
+
expect(user.crypted_password).to eq Sorcery::CryptoProviders::BCrypt.encrypt('secret', user.salt)
|
553
|
+
end
|
491
554
|
end
|
492
555
|
|
493
556
|
describe 'ORM adapter' do
|
@@ -148,6 +148,7 @@ describe 'Crypto Providers wrappers' do
|
|
148
148
|
before(:all) do
|
149
149
|
Sorcery::CryptoProviders::BCrypt.cost = 1
|
150
150
|
@digest = BCrypt::Password.create('Noam Ben-Ari', cost: Sorcery::CryptoProviders::BCrypt.cost)
|
151
|
+
@tokens = %w[password gq18WBnJYNh2arkC1kgH]
|
151
152
|
end
|
152
153
|
|
153
154
|
after(:each) do
|
@@ -181,5 +182,64 @@ describe 'Crypto Providers wrappers' do
|
|
181
182
|
# stubbed in Sorcery::TestHelpers::Internal
|
182
183
|
expect(Sorcery::CryptoProviders::BCrypt.cost).to eq 1
|
183
184
|
end
|
185
|
+
|
186
|
+
it 'matches token encrypted with salt from upstream' do
|
187
|
+
# note: actual comparison is done by BCrypt::Password#==(raw_token)
|
188
|
+
expect(Sorcery::CryptoProviders::BCrypt.encrypt(@tokens)).to eq @tokens.flatten.join
|
189
|
+
end
|
190
|
+
|
191
|
+
it 'respond_to?(:pepper) returns true' do
|
192
|
+
expect(Sorcery::CryptoProviders::BCrypt.respond_to?(:pepper)).to be true
|
193
|
+
end
|
194
|
+
|
195
|
+
context 'when pepper is provided' do
|
196
|
+
before(:each) do
|
197
|
+
Sorcery::CryptoProviders::BCrypt.pepper = 'pepper'
|
198
|
+
@digest = Sorcery::CryptoProviders::BCrypt.encrypt(@tokens) # a BCrypt::Password object
|
199
|
+
end
|
200
|
+
|
201
|
+
it 'matches token encrypted with salt and pepper from upstream' do
|
202
|
+
# note: actual comparison is done by BCrypt::Password#==(raw_token)
|
203
|
+
expect(@digest).to eq @tokens.flatten.join.concat('pepper')
|
204
|
+
end
|
205
|
+
|
206
|
+
it 'matches? returns true when matches' do
|
207
|
+
expect(Sorcery::CryptoProviders::BCrypt.matches?(@digest, *@tokens)).to be true
|
208
|
+
end
|
209
|
+
|
210
|
+
it 'matches? returns false when pepper is replaced with empty string' do
|
211
|
+
Sorcery::CryptoProviders::BCrypt.pepper = ''
|
212
|
+
expect(Sorcery::CryptoProviders::BCrypt.matches?(@digest, *@tokens)).to be false
|
213
|
+
end
|
214
|
+
|
215
|
+
it 'matches? returns false when no match' do
|
216
|
+
expect(Sorcery::CryptoProviders::BCrypt.matches?(@digest, 'a_random_incorrect_password')).to be false
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
context "when pepper is an empty string (default)" do
|
221
|
+
before(:each) do
|
222
|
+
Sorcery::CryptoProviders::BCrypt.pepper = ''
|
223
|
+
@digest = Sorcery::CryptoProviders::BCrypt.encrypt(@tokens) # a BCrypt::Password object
|
224
|
+
end
|
225
|
+
|
226
|
+
# make sure the default pepper '' does nothing
|
227
|
+
it 'matches token encrypted with salt only (without pepper)' do
|
228
|
+
expect(@digest).to eq @tokens.flatten.join # keep consistency with the older versions of #join_token
|
229
|
+
end
|
230
|
+
|
231
|
+
it 'matches? returns true when matches' do
|
232
|
+
expect(Sorcery::CryptoProviders::BCrypt.matches?(@digest, *@tokens)).to be true
|
233
|
+
end
|
234
|
+
|
235
|
+
it 'matches? returns false when pepper has changed' do
|
236
|
+
Sorcery::CryptoProviders::BCrypt.pepper = 'a new pepper'
|
237
|
+
expect(Sorcery::CryptoProviders::BCrypt.matches?(@digest, *@tokens)).to be false
|
238
|
+
end
|
239
|
+
|
240
|
+
it 'matches? returns false when no match' do
|
241
|
+
expect(Sorcery::CryptoProviders::BCrypt.matches?(@digest, 'a_random_incorrect_password')).to be false
|
242
|
+
end
|
243
|
+
end
|
184
244
|
end
|
185
245
|
end
|
@@ -1,7 +1,9 @@
|
|
1
1
|
class MigrationHelper
|
2
2
|
class << self
|
3
3
|
def migrate(path)
|
4
|
-
if ActiveRecord.version >= Gem::Version.new('
|
4
|
+
if ActiveRecord.version >= Gem::Version.new('6.0.0')
|
5
|
+
ActiveRecord::MigrationContext.new(path, schema_migration).migrate
|
6
|
+
elsif ActiveRecord.version >= Gem::Version.new('5.2.0')
|
5
7
|
ActiveRecord::MigrationContext.new(path).migrate
|
6
8
|
else
|
7
9
|
ActiveRecord::Migrator.migrate(path)
|
@@ -9,11 +11,19 @@ class MigrationHelper
|
|
9
11
|
end
|
10
12
|
|
11
13
|
def rollback(path)
|
12
|
-
if ActiveRecord.version >= Gem::Version.new('
|
14
|
+
if ActiveRecord.version >= Gem::Version.new('6.0.0')
|
15
|
+
ActiveRecord::MigrationContext.new(path, schema_migration).rollback
|
16
|
+
elsif ActiveRecord.version >= Gem::Version.new('5.2.0')
|
13
17
|
ActiveRecord::MigrationContext.new(path).rollback
|
14
18
|
else
|
15
19
|
ActiveRecord::Migrator.rollback(path)
|
16
20
|
end
|
17
21
|
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def schema_migration
|
26
|
+
ActiveRecord::Base.connection.schema_migration
|
27
|
+
end
|
18
28
|
end
|
19
29
|
end
|