sorcery 0.11.0 → 0.16.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (114) hide show
  1. checksums.yaml +5 -5
  2. data/.github/ISSUE_TEMPLATE.md +20 -0
  3. data/.github/PULL_REQUEST_TEMPLATE.md +5 -0
  4. data/.github/workflows/ruby.yml +23 -0
  5. data/.rubocop.yml +55 -0
  6. data/.rubocop_todo.yml +155 -0
  7. data/.travis.yml +11 -51
  8. data/CHANGELOG.md +75 -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 -7
  13. data/SECURITY.md +18 -0
  14. data/gemfiles/rails_52.gemfile +7 -0
  15. data/gemfiles/rails_60.gemfile +7 -0
  16. data/lib/generators/sorcery/USAGE +1 -1
  17. data/lib/generators/sorcery/helpers.rb +4 -0
  18. data/lib/generators/sorcery/install_generator.rb +21 -21
  19. data/lib/generators/sorcery/templates/initializer.rb +176 -69
  20. data/lib/generators/sorcery/templates/migration/activity_logging.rb +5 -5
  21. data/lib/generators/sorcery/templates/migration/brute_force_protection.rb +4 -4
  22. data/lib/generators/sorcery/templates/migration/core.rb +4 -4
  23. data/lib/generators/sorcery/templates/migration/external.rb +3 -3
  24. data/lib/generators/sorcery/templates/migration/magic_login.rb +9 -0
  25. data/lib/generators/sorcery/templates/migration/remember_me.rb +3 -3
  26. data/lib/generators/sorcery/templates/migration/reset_password.rb +5 -4
  27. data/lib/generators/sorcery/templates/migration/user_activation.rb +4 -4
  28. data/lib/sorcery.rb +2 -0
  29. data/lib/sorcery/adapters/active_record_adapter.rb +4 -3
  30. data/lib/sorcery/adapters/mongoid_adapter.rb +23 -11
  31. data/lib/sorcery/controller.rb +26 -15
  32. data/lib/sorcery/controller/config.rb +7 -5
  33. data/lib/sorcery/controller/submodules/activity_logging.rb +9 -3
  34. data/lib/sorcery/controller/submodules/external.rb +52 -33
  35. data/lib/sorcery/controller/submodules/http_basic_auth.rb +2 -0
  36. data/lib/sorcery/controller/submodules/remember_me.rb +3 -8
  37. data/lib/sorcery/controller/submodules/session_timeout.rb +28 -5
  38. data/lib/sorcery/crypto_providers/aes256.rb +2 -1
  39. data/lib/sorcery/crypto_providers/bcrypt.rb +8 -2
  40. data/lib/sorcery/engine.rb +16 -3
  41. data/lib/sorcery/model.rb +14 -10
  42. data/lib/sorcery/model/config.rb +12 -4
  43. data/lib/sorcery/model/submodules/brute_force_protection.rb +6 -7
  44. data/lib/sorcery/model/submodules/external.rb +19 -3
  45. data/lib/sorcery/model/submodules/magic_login.rb +130 -0
  46. data/lib/sorcery/model/submodules/reset_password.rb +25 -2
  47. data/lib/sorcery/model/submodules/user_activation.rb +1 -1
  48. data/lib/sorcery/model/temporary_token.rb +3 -1
  49. data/lib/sorcery/protocols/oauth.rb +1 -0
  50. data/lib/sorcery/providers/auth0.rb +46 -0
  51. data/lib/sorcery/providers/battlenet.rb +51 -0
  52. data/lib/sorcery/providers/discord.rb +52 -0
  53. data/lib/sorcery/providers/heroku.rb +1 -0
  54. data/lib/sorcery/providers/instagram.rb +73 -0
  55. data/lib/sorcery/providers/line.rb +63 -0
  56. data/lib/sorcery/providers/linkedin.rb +45 -36
  57. data/lib/sorcery/providers/vk.rb +5 -4
  58. data/lib/sorcery/providers/wechat.rb +8 -6
  59. data/lib/sorcery/test_helpers/internal.rb +5 -4
  60. data/lib/sorcery/test_helpers/internal/rails.rb +11 -11
  61. data/lib/sorcery/test_helpers/rails/request.rb +20 -0
  62. data/lib/sorcery/version.rb +1 -1
  63. data/sorcery.gemspec +26 -10
  64. data/spec/active_record/user_activation_spec.rb +2 -2
  65. data/spec/active_record/user_activity_logging_spec.rb +2 -2
  66. data/spec/active_record/user_brute_force_protection_spec.rb +2 -2
  67. data/spec/active_record/user_magic_login_spec.rb +15 -0
  68. data/spec/active_record/user_oauth_spec.rb +2 -2
  69. data/spec/active_record/user_remember_me_spec.rb +2 -2
  70. data/spec/active_record/user_reset_password_spec.rb +2 -2
  71. data/spec/active_record/user_spec.rb +0 -10
  72. data/spec/controllers/controller_http_basic_auth_spec.rb +1 -1
  73. data/spec/controllers/controller_oauth2_spec.rb +230 -123
  74. data/spec/controllers/controller_oauth_spec.rb +13 -7
  75. data/spec/controllers/controller_remember_me_spec.rb +16 -8
  76. data/spec/controllers/controller_session_timeout_spec.rb +90 -3
  77. data/spec/controllers/controller_spec.rb +13 -3
  78. data/spec/orm/active_record.rb +2 -2
  79. data/spec/providers/example_provider_spec.rb +17 -0
  80. data/spec/providers/example_spec.rb +17 -0
  81. data/spec/providers/vk_spec.rb +42 -0
  82. data/spec/rails_app/app/assets/config/manifest.js +1 -0
  83. data/spec/rails_app/app/controllers/application_controller.rb +2 -0
  84. data/spec/rails_app/app/controllers/sorcery_controller.rb +152 -33
  85. data/spec/rails_app/app/mailers/sorcery_mailer.rb +7 -0
  86. data/spec/rails_app/app/views/sorcery_mailer/magic_login_email.html.erb +13 -0
  87. data/spec/rails_app/app/views/sorcery_mailer/magic_login_email.text.erb +6 -0
  88. data/spec/rails_app/config/application.rb +8 -3
  89. data/spec/rails_app/config/boot.rb +1 -1
  90. data/spec/rails_app/config/environment.rb +1 -1
  91. data/spec/rails_app/config/routes.rb +17 -0
  92. data/spec/rails_app/config/secrets.yml +4 -0
  93. data/spec/rails_app/db/migrate/activity_logging/20101224223624_add_activity_logging_to_users.rb +2 -2
  94. data/spec/rails_app/db/migrate/invalidate_active_sessions/20180221093235_add_invalidate_active_sessions_before_to_users.rb +9 -0
  95. data/spec/rails_app/db/migrate/magic_login/20170924151831_add_magic_login_to_users.rb +17 -0
  96. data/spec/rails_app/db/migrate/reset_password/20101224223622_add_reset_password_to_users.rb +2 -0
  97. data/spec/rails_app/db/schema.rb +7 -9
  98. data/spec/shared_examples/user_magic_login_shared_examples.rb +150 -0
  99. data/spec/shared_examples/user_oauth_shared_examples.rb +1 -1
  100. data/spec/shared_examples/user_remember_me_shared_examples.rb +1 -1
  101. data/spec/shared_examples/user_reset_password_shared_examples.rb +37 -5
  102. data/spec/shared_examples/user_shared_examples.rb +104 -43
  103. data/spec/sorcery_crypto_providers_spec.rb +61 -1
  104. data/spec/sorcery_temporary_token_spec.rb +27 -0
  105. data/spec/spec.opts +1 -1
  106. data/spec/spec_helper.rb +2 -2
  107. data/spec/support/migration_helper.rb +29 -0
  108. data/spec/support/providers/example.rb +11 -0
  109. data/spec/support/providers/example_provider.rb +11 -0
  110. metadata +92 -29
  111. data/gemfiles/active_record-rails40.gemfile +0 -7
  112. data/gemfiles/active_record-rails41.gemfile +0 -7
  113. data/gemfiles/active_record-rails42.gemfile +0 -7
  114. data/spec/rails_app/config/initializers/secret_token.rb +0 -7
@@ -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)
@@ -228,10 +235,13 @@ shared_examples_for 'rails_3_core_model' do
228
235
 
229
236
  expect(user).to receive(:save) { raise RuntimeError }
230
237
 
238
+ # rubocop:disable Lint/HandleExceptions
231
239
  begin
232
240
  user.save
233
- rescue
241
+ rescue RuntimeError
242
+ # Intentionally force exception during save
234
243
  end
244
+ # rubocop:enable Lint/HandleExceptions
235
245
 
236
246
  expect(user.password).not_to be_nil
237
247
  end
@@ -308,12 +318,12 @@ shared_examples_for 'rails_3_core_model' do
308
318
 
309
319
  describe 'generic send email' do
310
320
  before(:all) do
311
- ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate/activation")
321
+ MigrationHelper.migrate("#{Rails.root}/db/migrate/activation")
312
322
  User.reset_column_information
313
323
  end
314
324
 
315
325
  after(:all) do
316
- ActiveRecord::Migrator.rollback("#{Rails.root}/db/migrate/activation")
326
+ MigrationHelper.rollback("#{Rails.root}/db/migrate/activation")
317
327
  end
318
328
 
319
329
  before do
@@ -323,9 +333,11 @@ shared_examples_for 'rails_3_core_model' do
323
333
 
324
334
  it 'use deliver_later' do
325
335
  sorcery_reload!(
326
- [
327
- :user_activation, :user_activation_mailer,
328
- :activation_needed_email_method_name, :email_delivery_method
336
+ %i[
337
+ user_activation
338
+ user_activation_mailer
339
+ activation_needed_email_method_name
340
+ email_delivery_method
329
341
  ],
330
342
  user_activation_mailer: SorceryMailer,
331
343
  activation_needed_email_method_name: nil,
@@ -340,9 +352,10 @@ shared_examples_for 'rails_3_core_model' do
340
352
  it 'use deliver_now if rails version 4.2+' do
341
353
  allow(Rails).to receive(:version).and_return('4.2.0')
342
354
  sorcery_reload!(
343
- [
344
- :user_activation, :user_activation_mailer,
345
- :activation_needed_email_method_name
355
+ %i[
356
+ user_activation
357
+ user_activation_mailer
358
+ activation_needed_email_method_name
346
359
  ],
347
360
  user_activation_mailer: SorceryMailer,
348
361
  activation_needed_email_method_name: nil
@@ -355,9 +368,10 @@ shared_examples_for 'rails_3_core_model' do
355
368
  it 'use deliver if rails version < 4.2' do
356
369
  allow(Rails).to receive(:version).and_return('4.1.0')
357
370
  sorcery_reload!(
358
- [
359
- :user_activation, :user_activation_mailer,
360
- :activation_needed_email_method_name
371
+ %i[
372
+ user_activation
373
+ user_activation_mailer
374
+ activation_needed_email_method_name
361
375
  ],
362
376
  user_activation_mailer: SorceryMailer,
363
377
  activation_needed_email_method_name: nil
@@ -452,6 +466,14 @@ shared_examples_for 'rails_3_core_model' do
452
466
  expect(User.encrypt(@text)).to eq Sorcery::CryptoProviders::SHA512.encrypt(@text)
453
467
  end
454
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
+
455
477
  it 'salt is random for each user and saved in db' do
456
478
  sorcery_model_property_set(:salt_attribute_name, :salt)
457
479
 
@@ -481,6 +503,54 @@ shared_examples_for 'rails_3_core_model' do
481
503
 
482
504
  expect(user.crypted_password).to eq Sorcery::CryptoProviders::SHA512.encrypt('secret', user.salt)
483
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
484
554
  end
485
555
 
486
556
  describe 'ORM adapter' do
@@ -503,7 +573,7 @@ shared_examples_for 'rails_3_core_model' do
503
573
  end
504
574
 
505
575
  it 'find_by_username works as expected with multiple username attributes' do
506
- sorcery_model_property_set(:username_attribute_names, [:username, :email])
576
+ sorcery_model_property_set(:username_attribute_names, %i[username email])
507
577
 
508
578
  expect(User.sorcery_adapter.find_by_username('gizmo')).to eq user
509
579
  end
@@ -518,6 +588,21 @@ shared_examples_for 'external_user' do
518
588
  let(:user) { create_new_user }
519
589
  let(:external_user) { create_new_external_user :twitter }
520
590
 
591
+ before(:all) do
592
+ if SORCERY_ORM == :active_record
593
+ MigrationHelper.migrate("#{Rails.root}/db/migrate/external")
594
+ MigrationHelper.migrate("#{Rails.root}/db/migrate/activation")
595
+ end
596
+ sorcery_reload!
597
+ end
598
+
599
+ after(:all) do
600
+ if SORCERY_ORM == :active_record
601
+ MigrationHelper.rollback("#{Rails.root}/db/migrate/external")
602
+ MigrationHelper.rollback("#{Rails.root}/db/migrate/activation")
603
+ end
604
+ end
605
+
521
606
  before(:each) do
522
607
  User.sorcery_adapter.delete_all
523
608
  end
@@ -535,24 +620,12 @@ shared_examples_for 'external_user' do
535
620
  end
536
621
 
537
622
  describe '.create_from_provider' do
538
- before(:all) do
539
- if SORCERY_ORM == :active_record
540
- ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate/external")
541
- User.reset_column_information
542
- end
543
-
623
+ before(:each) do
544
624
  sorcery_reload!([:external])
545
- end
546
-
547
- after(:all) do
548
- if SORCERY_ORM == :active_record
549
- ActiveRecord::Migrator.rollback("#{Rails.root}/db/migrate/external")
550
- end
625
+ sorcery_model_property_set(:authentications_class, Authentication)
551
626
  end
552
627
 
553
628
  it 'supports nested attributes' do
554
- sorcery_model_property_set(:authentications_class, Authentication)
555
-
556
629
  expect do
557
630
  User.create_from_provider('facebook', '123', username: 'Noam Ben Ari')
558
631
  end.to change { User.count }.by(1)
@@ -570,33 +643,21 @@ shared_examples_for 'external_user' do
570
643
  it 'does not create user when block return false' do
571
644
  expect do
572
645
  User.create_from_provider('facebook', '123', username: 'Noam Ben Ari') { false }
573
- end.not_to change { User.count }
646
+ end.not_to(change { User.count })
574
647
  end
575
648
  end
576
649
  end
577
650
 
578
651
  describe 'activation' do
579
- before(:all) do
580
- if SORCERY_ORM == :active_record
581
- ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate/external")
582
- ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate/activation")
583
- end
584
-
585
- sorcery_reload!([:user_activation, :external], user_activation_mailer: ::SorceryMailer)
586
- end
587
-
588
- after(:all) do
589
- if SORCERY_ORM == :active_record
590
- ActiveRecord::Migrator.rollback("#{Rails.root}/db/migrate/external")
591
- ActiveRecord::Migrator.rollback("#{Rails.root}/db/migrate/activation")
592
- end
652
+ before(:each) do
653
+ sorcery_reload!(%i[user_activation external], user_activation_mailer: ::SorceryMailer)
593
654
  end
594
655
 
595
656
  after(:each) do
596
657
  User.sorcery_adapter.delete_all
597
658
  end
598
659
 
599
- [:facebook, :github, :google, :liveid, :slack].each do |provider|
660
+ %i[facebook github google liveid slack].each do |provider|
600
661
  it 'does not send activation email to external users' do
601
662
  old_size = ActionMailer::Base.deliveries.size
602
663
  create_new_external_user(provider)
@@ -53,7 +53,7 @@ describe 'Crypto Providers wrappers' do
53
53
 
54
54
  it 'matches password encrypted using salt and join token from upstream' do
55
55
  Sorcery::CryptoProviders::SHA1.join_token = 'test'
56
- expect(Sorcery::CryptoProviders::SHA1.encrypt(%w(password gq18WBnJYNh2arkC1kgH))).to eq '894b5bf1643b8d0e1b2eaddb22426be7036dab70'
56
+ expect(Sorcery::CryptoProviders::SHA1.encrypt(%w[password gq18WBnJYNh2arkC1kgH])).to eq '894b5bf1643b8d0e1b2eaddb22426be7036dab70'
57
57
  end
58
58
  end
59
59
 
@@ -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
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sorcery::Model::TemporaryToken do
4
+ describe '.generate_random_token' do
5
+ before do
6
+ sorcery_reload!
7
+ end
8
+
9
+ subject { Sorcery::Model::TemporaryToken.generate_random_token.length }
10
+
11
+ context 'token_randomness is 3' do
12
+ before do
13
+ sorcery_model_property_set(:token_randomness, 3)
14
+ end
15
+
16
+ it { is_expected.to eq 4 }
17
+ end
18
+
19
+ context 'token_randomness is 15' do
20
+ before do
21
+ sorcery_model_property_set(:token_randomness, 15)
22
+ end
23
+
24
+ it { is_expected.to eq 20 }
25
+ end
26
+ end
27
+ end
data/spec/spec.opts CHANGED
@@ -1,2 +1,2 @@
1
1
  --color
2
- --format documentation
2
+ --format documentation
data/spec/spec_helper.rb CHANGED
@@ -29,7 +29,7 @@ RSpec.configure do |config|
29
29
  config.include RSpec::Rails::ControllerExampleGroup, file_path: /controller(.)*_spec.rb$/
30
30
  config.mock_with :rspec
31
31
 
32
- config.use_transactional_fixtures = true
32
+ config.use_transactional_fixtures = false
33
33
 
34
34
  config.before(:suite) { setup_orm }
35
35
  config.after(:suite) { teardown_orm }
@@ -40,7 +40,7 @@ RSpec.configure do |config|
40
40
 
41
41
  if begin
42
42
  Module.const_defined?('::Rails::Controller::Testing')
43
- rescue
43
+ rescue StandardError
44
44
  false
45
45
  end
46
46
  config.include ::Rails::Controller::Testing::TestProcess, type: :controller
@@ -0,0 +1,29 @@
1
+ class MigrationHelper
2
+ class << self
3
+ def migrate(path)
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')
7
+ ActiveRecord::MigrationContext.new(path).migrate
8
+ else
9
+ ActiveRecord::Migrator.migrate(path)
10
+ end
11
+ end
12
+
13
+ def rollback(path)
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')
17
+ ActiveRecord::MigrationContext.new(path).rollback
18
+ else
19
+ ActiveRecord::Migrator.rollback(path)
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def schema_migration
26
+ ActiveRecord::Base.connection.schema_migration
27
+ end
28
+ end
29
+ 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 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,18 +1,33 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sorcery
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.0
4
+ version: 0.16.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Noam Ben Ari
8
8
  - Kir Shatrov
9
9
  - Grzegorz Witek
10
10
  - Chase Gilliam
11
+ - Josh Buker
11
12
  autorequire:
12
13
  bindir: bin
13
14
  cert_chain: []
14
- date: 2017-05-16 00:00:00.000000000 Z
15
+ date: 2021-02-16 00:00:00.000000000 Z
15
16
  dependencies:
17
+ - !ruby/object:Gem::Dependency
18
+ name: bcrypt
19
+ requirement: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - "~>"
22
+ - !ruby/object:Gem::Version
23
+ version: '3.1'
24
+ type: :runtime
25
+ prerelease: false
26
+ version_requirements: !ruby/object:Gem::Requirement
27
+ requirements:
28
+ - - "~>"
29
+ - !ruby/object:Gem::Version
30
+ version: '3.1'
16
31
  - !ruby/object:Gem::Dependency
17
32
  name: oauth
18
33
  requirement: !ruby/object:Gem::Requirement
@@ -54,35 +69,35 @@ dependencies:
54
69
  - !ruby/object:Gem::Version
55
70
  version: 0.8.0
56
71
  - !ruby/object:Gem::Dependency
57
- name: bcrypt
72
+ name: byebug
58
73
  requirement: !ruby/object:Gem::Requirement
59
74
  requirements:
60
75
  - - "~>"
61
76
  - !ruby/object:Gem::Version
62
- version: '3.1'
63
- type: :runtime
77
+ version: 10.0.0
78
+ type: :development
64
79
  prerelease: false
65
80
  version_requirements: !ruby/object:Gem::Requirement
66
81
  requirements:
67
82
  - - "~>"
68
83
  - !ruby/object:Gem::Version
69
- version: '3.1'
84
+ version: 10.0.0
70
85
  - !ruby/object:Gem::Dependency
71
- name: yard
86
+ name: rspec-rails
72
87
  requirement: !ruby/object:Gem::Requirement
73
88
  requirements:
74
89
  - - "~>"
75
90
  - !ruby/object:Gem::Version
76
- version: 0.6.0
91
+ version: 3.7.0
77
92
  type: :development
78
93
  prerelease: false
79
94
  version_requirements: !ruby/object:Gem::Requirement
80
95
  requirements:
81
96
  - - "~>"
82
97
  - !ruby/object:Gem::Version
83
- version: 0.6.0
98
+ version: 3.7.0
84
99
  - !ruby/object:Gem::Dependency
85
- name: timecop
100
+ name: rubocop
86
101
  requirement: !ruby/object:Gem::Requirement
87
102
  requirements:
88
103
  - - ">="
@@ -110,66 +125,93 @@ dependencies:
110
125
  - !ruby/object:Gem::Version
111
126
  version: 0.3.8
112
127
  - !ruby/object:Gem::Dependency
113
- name: rspec-rails
128
+ name: test-unit
114
129
  requirement: !ruby/object:Gem::Requirement
115
130
  requirements:
116
131
  - - "~>"
117
132
  - !ruby/object:Gem::Version
118
- version: 3.5.0
133
+ version: 3.2.0
119
134
  type: :development
120
135
  prerelease: false
121
136
  version_requirements: !ruby/object:Gem::Requirement
122
137
  requirements:
123
138
  - - "~>"
124
139
  - !ruby/object:Gem::Version
125
- version: 3.5.0
140
+ version: 3.2.0
126
141
  - !ruby/object:Gem::Dependency
127
- name: test-unit
142
+ name: timecop
143
+ requirement: !ruby/object:Gem::Requirement
144
+ requirements:
145
+ - - ">="
146
+ - !ruby/object:Gem::Version
147
+ version: '0'
148
+ type: :development
149
+ prerelease: false
150
+ version_requirements: !ruby/object:Gem::Requirement
151
+ requirements:
152
+ - - ">="
153
+ - !ruby/object:Gem::Version
154
+ version: '0'
155
+ - !ruby/object:Gem::Dependency
156
+ name: webmock
128
157
  requirement: !ruby/object:Gem::Requirement
129
158
  requirements:
130
159
  - - "~>"
131
160
  - !ruby/object:Gem::Version
132
- version: 3.1.0
161
+ version: 3.3.0
133
162
  type: :development
134
163
  prerelease: false
135
164
  version_requirements: !ruby/object:Gem::Requirement
136
165
  requirements:
137
166
  - - "~>"
138
167
  - !ruby/object:Gem::Version
139
- version: 3.1.0
168
+ version: 3.3.0
140
169
  - !ruby/object:Gem::Dependency
141
- name: byebug
170
+ name: yard
142
171
  requirement: !ruby/object:Gem::Requirement
143
172
  requirements:
144
173
  - - "~>"
145
174
  - !ruby/object:Gem::Version
146
- version: 9.0.0
175
+ version: 0.9.0
176
+ - - ">="
177
+ - !ruby/object:Gem::Version
178
+ version: 0.9.12
147
179
  type: :development
148
180
  prerelease: false
149
181
  version_requirements: !ruby/object:Gem::Requirement
150
182
  requirements:
151
183
  - - "~>"
152
184
  - !ruby/object:Gem::Version
153
- version: 9.0.0
185
+ version: 0.9.0
186
+ - - ">="
187
+ - !ruby/object:Gem::Version
188
+ version: 0.9.12
154
189
  description: Provides common authentication needs such as signing in/out, activating
155
190
  by email and resetting password.
156
- email: chase.gilliam@gmail.com
191
+ email:
192
+ - crypto@joshbuker.com
157
193
  executables: []
158
194
  extensions: []
159
195
  extra_rdoc_files: []
160
196
  files:
161
197
  - ".document"
198
+ - ".github/ISSUE_TEMPLATE.md"
199
+ - ".github/PULL_REQUEST_TEMPLATE.md"
200
+ - ".github/workflows/ruby.yml"
162
201
  - ".gitignore"
163
202
  - ".rspec"
203
+ - ".rubocop.yml"
204
+ - ".rubocop_todo.yml"
164
205
  - ".travis.yml"
165
206
  - CHANGELOG.md
207
+ - CODE_OF_CONDUCT.md
166
208
  - Gemfile
167
- - LICENSE.txt
209
+ - LICENSE.md
168
210
  - README.md
169
211
  - Rakefile
170
- - gemfiles/active_record-rails40.gemfile
171
- - gemfiles/active_record-rails41.gemfile
172
- - gemfiles/active_record-rails42.gemfile
212
+ - SECURITY.md
213
+ - gemfiles/rails_52.gemfile
214
+ - gemfiles/rails_60.gemfile
173
215
  - lib/generators/sorcery/USAGE
174
216
  - lib/generators/sorcery/helpers.rb
175
217
  - lib/generators/sorcery/install_generator.rb
@@ -178,6 +220,7 @@ files:
178
220
  - lib/generators/sorcery/templates/migration/brute_force_protection.rb
179
221
  - lib/generators/sorcery/templates/migration/core.rb
180
222
  - lib/generators/sorcery/templates/migration/external.rb
223
+ - lib/generators/sorcery/templates/migration/magic_login.rb
181
224
  - lib/generators/sorcery/templates/migration/remember_me.rb
182
225
  - lib/generators/sorcery/templates/migration/reset_password.rb
183
226
  - lib/generators/sorcery/templates/migration/user_activation.rb
@@ -206,6 +249,7 @@ files:
206
249
  - lib/sorcery/model/submodules/activity_logging.rb
207
250
  - lib/sorcery/model/submodules/brute_force_protection.rb
208
251
  - lib/sorcery/model/submodules/external.rb
252
+ - lib/sorcery/model/submodules/magic_login.rb
209
253
  - lib/sorcery/model/submodules/remember_me.rb
210
254
  - lib/sorcery/model/submodules/reset_password.rb
211
255
  - lib/sorcery/model/submodules/user_activation.rb
@@ -213,12 +257,17 @@ files:
213
257
  - lib/sorcery/protocols/certs/ca-bundle.crt
214
258
  - lib/sorcery/protocols/oauth.rb
215
259
  - lib/sorcery/protocols/oauth2.rb
260
+ - lib/sorcery/providers/auth0.rb
216
261
  - lib/sorcery/providers/base.rb
262
+ - lib/sorcery/providers/battlenet.rb
263
+ - lib/sorcery/providers/discord.rb
217
264
  - lib/sorcery/providers/facebook.rb
218
265
  - lib/sorcery/providers/github.rb
219
266
  - lib/sorcery/providers/google.rb
220
267
  - lib/sorcery/providers/heroku.rb
268
+ - lib/sorcery/providers/instagram.rb
221
269
  - lib/sorcery/providers/jira.rb
270
+ - lib/sorcery/providers/line.rb
222
271
  - lib/sorcery/providers/linkedin.rb
223
272
  - lib/sorcery/providers/liveid.rb
224
273
  - lib/sorcery/providers/microsoft.rb
@@ -233,11 +282,13 @@ files:
233
282
  - lib/sorcery/test_helpers/internal/rails.rb
234
283
  - lib/sorcery/test_helpers/rails/controller.rb
235
284
  - lib/sorcery/test_helpers/rails/integration.rb
285
+ - lib/sorcery/test_helpers/rails/request.rb
236
286
  - lib/sorcery/version.rb
237
287
  - sorcery.gemspec
238
288
  - spec/active_record/user_activation_spec.rb
239
289
  - spec/active_record/user_activity_logging_spec.rb
240
290
  - spec/active_record/user_brute_force_protection_spec.rb
291
+ - spec/active_record/user_magic_login_spec.rb
241
292
  - spec/active_record/user_oauth_spec.rb
242
293
  - spec/active_record/user_remember_me_spec.rb
243
294
  - spec/active_record/user_reset_password_spec.rb
@@ -251,9 +302,14 @@ files:
251
302
  - spec/controllers/controller_session_timeout_spec.rb
252
303
  - spec/controllers/controller_spec.rb
253
304
  - spec/orm/active_record.rb
305
+ - spec/providers/example_provider_spec.rb
306
+ - spec/providers/example_spec.rb
307
+ - spec/providers/vk_spec.rb
254
308
  - spec/rails_app/app/active_record/authentication.rb
255
309
  - spec/rails_app/app/active_record/user.rb
256
310
  - spec/rails_app/app/active_record/user_provider.rb
311
+ - spec/rails_app/app/assets/config/manifest.js
312
+ - spec/rails_app/app/controllers/application_controller.rb
257
313
  - spec/rails_app/app/controllers/sorcery_controller.rb
258
314
  - spec/rails_app/app/helpers/application_helper.rb
259
315
  - spec/rails_app/app/mailers/sorcery_mailer.rb
@@ -264,6 +320,8 @@ files:
264
320
  - spec/rails_app/app/views/sorcery_mailer/activation_needed_email.html.erb
265
321
  - spec/rails_app/app/views/sorcery_mailer/activation_success_email.html.erb
266
322
  - spec/rails_app/app/views/sorcery_mailer/activation_success_email.text.erb
323
+ - spec/rails_app/app/views/sorcery_mailer/magic_login_email.html.erb
324
+ - spec/rails_app/app/views/sorcery_mailer/magic_login_email.text.erb
267
325
  - spec/rails_app/app/views/sorcery_mailer/reset_password_email.html.erb
268
326
  - spec/rails_app/app/views/sorcery_mailer/reset_password_email.text.erb
269
327
  - spec/rails_app/app/views/sorcery_mailer/send_unlock_token_email.text.erb
@@ -277,15 +335,17 @@ files:
277
335
  - spec/rails_app/config/initializers/compatible_legacy_migration.rb
278
336
  - spec/rails_app/config/initializers/inflections.rb
279
337
  - spec/rails_app/config/initializers/mime_types.rb
280
- - spec/rails_app/config/initializers/secret_token.rb
281
338
  - spec/rails_app/config/initializers/session_store.rb
282
339
  - spec/rails_app/config/locales/en.yml
283
340
  - spec/rails_app/config/routes.rb
341
+ - spec/rails_app/config/secrets.yml
284
342
  - spec/rails_app/db/migrate/activation/20101224223622_add_activation_to_users.rb
285
343
  - spec/rails_app/db/migrate/activity_logging/20101224223624_add_activity_logging_to_users.rb
286
344
  - spec/rails_app/db/migrate/brute_force_protection/20101224223626_add_brute_force_protection_to_users.rb
287
345
  - spec/rails_app/db/migrate/core/20101224223620_create_users.rb
288
346
  - spec/rails_app/db/migrate/external/20101224223628_create_authentications_and_user_providers.rb
347
+ - spec/rails_app/db/migrate/invalidate_active_sessions/20180221093235_add_invalidate_active_sessions_before_to_users.rb
348
+ - spec/rails_app/db/migrate/magic_login/20170924151831_add_magic_login_to_users.rb
289
349
  - spec/rails_app/db/migrate/remember_me/20101224223623_add_remember_me_token_to_users.rb
290
350
  - spec/rails_app/db/migrate/reset_password/20101224223622_add_reset_password_to_users.rb
291
351
  - spec/rails_app/db/schema.rb
@@ -293,13 +353,18 @@ files:
293
353
  - spec/shared_examples/user_activation_shared_examples.rb
294
354
  - spec/shared_examples/user_activity_logging_shared_examples.rb
295
355
  - spec/shared_examples/user_brute_force_protection_shared_examples.rb
356
+ - spec/shared_examples/user_magic_login_shared_examples.rb
296
357
  - spec/shared_examples/user_oauth_shared_examples.rb
297
358
  - spec/shared_examples/user_remember_me_shared_examples.rb
298
359
  - spec/shared_examples/user_reset_password_shared_examples.rb
299
360
  - spec/shared_examples/user_shared_examples.rb
300
361
  - spec/sorcery_crypto_providers_spec.rb
362
+ - spec/sorcery_temporary_token_spec.rb
301
363
  - spec/spec.opts
302
364
  - spec/spec_helper.rb
365
+ - spec/support/migration_helper.rb
366
+ - spec/support/providers/example.rb
367
+ - spec/support/providers/example_provider.rb
303
368
  homepage: https://github.com/Sorcery/sorcery
304
369
  licenses:
305
370
  - MIT
@@ -314,17 +379,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
314
379
  requirements:
315
380
  - - ">="
316
381
  - !ruby/object:Gem::Version
317
- version: 2.0.0
382
+ version: 2.4.9
318
383
  required_rubygems_version: !ruby/object:Gem::Requirement
319
384
  requirements:
320
385
  - - ">="
321
386
  - !ruby/object:Gem::Version
322
387
  version: '0'
323
388
  requirements: []
324
- rubyforge_project:
325
- rubygems_version: 2.6.8
389
+ rubygems_version: 3.1.2
326
390
  signing_key:
327
391
  specification_version: 4
328
392
  summary: Magical authentication for Rails applications
329
393
  test_files: []
330
- has_rdoc: