sorcery 0.11.0 → 0.15.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.
Files changed (106) hide show
  1. checksums.yaml +5 -5
  2. data/.github/ISSUE_TEMPLATE.md +20 -0
  3. data/.rubocop.yml +55 -0
  4. data/.rubocop_todo.yml +145 -0
  5. data/.travis.yml +3 -52
  6. data/CHANGELOG.md +69 -0
  7. data/Gemfile +3 -3
  8. data/{LICENSE.txt → LICENSE.md} +1 -1
  9. data/README.md +34 -7
  10. data/lib/generators/sorcery/USAGE +1 -1
  11. data/lib/generators/sorcery/install_generator.rb +21 -21
  12. data/lib/generators/sorcery/templates/initializer.rb +164 -69
  13. data/lib/generators/sorcery/templates/migration/activity_logging.rb +4 -4
  14. data/lib/generators/sorcery/templates/migration/brute_force_protection.rb +3 -3
  15. data/lib/generators/sorcery/templates/migration/core.rb +2 -2
  16. data/lib/generators/sorcery/templates/migration/external.rb +3 -3
  17. data/lib/generators/sorcery/templates/migration/magic_login.rb +9 -0
  18. data/lib/generators/sorcery/templates/migration/remember_me.rb +2 -2
  19. data/lib/generators/sorcery/templates/migration/reset_password.rb +4 -3
  20. data/lib/generators/sorcery/templates/migration/user_activation.rb +3 -3
  21. data/lib/sorcery.rb +2 -0
  22. data/lib/sorcery/adapters/active_record_adapter.rb +3 -2
  23. data/lib/sorcery/adapters/mongoid_adapter.rb +23 -11
  24. data/lib/sorcery/controller.rb +26 -15
  25. data/lib/sorcery/controller/config.rb +2 -0
  26. data/lib/sorcery/controller/submodules/activity_logging.rb +14 -3
  27. data/lib/sorcery/controller/submodules/brute_force_protection.rb +7 -3
  28. data/lib/sorcery/controller/submodules/external.rb +48 -33
  29. data/lib/sorcery/controller/submodules/http_basic_auth.rb +5 -1
  30. data/lib/sorcery/controller/submodules/remember_me.rb +9 -10
  31. data/lib/sorcery/controller/submodules/session_timeout.rb +32 -6
  32. data/lib/sorcery/crypto_providers/aes256.rb +2 -1
  33. data/lib/sorcery/crypto_providers/bcrypt.rb +8 -2
  34. data/lib/sorcery/engine.rb +16 -3
  35. data/lib/sorcery/model.rb +14 -10
  36. data/lib/sorcery/model/config.rb +12 -4
  37. data/lib/sorcery/model/submodules/brute_force_protection.rb +6 -7
  38. data/lib/sorcery/model/submodules/external.rb +19 -3
  39. data/lib/sorcery/model/submodules/magic_login.rb +130 -0
  40. data/lib/sorcery/model/submodules/reset_password.rb +25 -2
  41. data/lib/sorcery/model/submodules/user_activation.rb +1 -1
  42. data/lib/sorcery/model/temporary_token.rb +3 -1
  43. data/lib/sorcery/protocols/oauth.rb +1 -0
  44. data/lib/sorcery/providers/auth0.rb +46 -0
  45. data/lib/sorcery/providers/discord.rb +52 -0
  46. data/lib/sorcery/providers/heroku.rb +1 -0
  47. data/lib/sorcery/providers/instagram.rb +73 -0
  48. data/lib/sorcery/providers/line.rb +47 -0
  49. data/lib/sorcery/providers/linkedin.rb +45 -36
  50. data/lib/sorcery/providers/vk.rb +5 -4
  51. data/lib/sorcery/providers/wechat.rb +8 -6
  52. data/lib/sorcery/test_helpers/internal.rb +5 -4
  53. data/lib/sorcery/test_helpers/internal/rails.rb +11 -11
  54. data/lib/sorcery/test_helpers/rails/request.rb +20 -0
  55. data/lib/sorcery/version.rb +1 -1
  56. data/sorcery.gemspec +28 -11
  57. data/spec/active_record/user_activation_spec.rb +2 -2
  58. data/spec/active_record/user_activity_logging_spec.rb +2 -2
  59. data/spec/active_record/user_brute_force_protection_spec.rb +2 -2
  60. data/spec/active_record/user_magic_login_spec.rb +15 -0
  61. data/spec/active_record/user_oauth_spec.rb +2 -2
  62. data/spec/active_record/user_remember_me_spec.rb +2 -2
  63. data/spec/active_record/user_reset_password_spec.rb +2 -2
  64. data/spec/active_record/user_spec.rb +0 -10
  65. data/spec/controllers/controller_http_basic_auth_spec.rb +1 -1
  66. data/spec/controllers/controller_oauth2_spec.rb +212 -123
  67. data/spec/controllers/controller_oauth_spec.rb +7 -7
  68. data/spec/controllers/controller_remember_me_spec.rb +16 -8
  69. data/spec/controllers/controller_session_timeout_spec.rb +90 -3
  70. data/spec/controllers/controller_spec.rb +13 -3
  71. data/spec/orm/active_record.rb +2 -2
  72. data/spec/providers/example_provider_spec.rb +17 -0
  73. data/spec/providers/example_spec.rb +17 -0
  74. data/spec/providers/vk_spec.rb +42 -0
  75. data/spec/rails_app/app/assets/config/manifest.js +1 -0
  76. data/spec/rails_app/app/controllers/sorcery_controller.rb +131 -32
  77. data/spec/rails_app/app/mailers/sorcery_mailer.rb +7 -0
  78. data/spec/rails_app/app/views/sorcery_mailer/magic_login_email.html.erb +13 -0
  79. data/spec/rails_app/app/views/sorcery_mailer/magic_login_email.text.erb +6 -0
  80. data/spec/rails_app/config/application.rb +8 -3
  81. data/spec/rails_app/config/boot.rb +1 -1
  82. data/spec/rails_app/config/environment.rb +1 -1
  83. data/spec/rails_app/config/routes.rb +14 -0
  84. data/spec/rails_app/config/secrets.yml +4 -0
  85. data/spec/rails_app/db/migrate/activity_logging/20101224223624_add_activity_logging_to_users.rb +2 -2
  86. data/spec/rails_app/db/migrate/invalidate_active_sessions/20180221093235_add_invalidate_active_sessions_before_to_users.rb +9 -0
  87. data/spec/rails_app/db/migrate/magic_login/20170924151831_add_magic_login_to_users.rb +17 -0
  88. data/spec/rails_app/db/migrate/reset_password/20101224223622_add_reset_password_to_users.rb +2 -0
  89. data/spec/rails_app/db/schema.rb +7 -9
  90. data/spec/shared_examples/user_magic_login_shared_examples.rb +150 -0
  91. data/spec/shared_examples/user_oauth_shared_examples.rb +1 -1
  92. data/spec/shared_examples/user_remember_me_shared_examples.rb +1 -1
  93. data/spec/shared_examples/user_reset_password_shared_examples.rb +37 -5
  94. data/spec/shared_examples/user_shared_examples.rb +104 -43
  95. data/spec/sorcery_crypto_providers_spec.rb +61 -1
  96. data/spec/sorcery_temporary_token_spec.rb +27 -0
  97. data/spec/spec.opts +1 -1
  98. data/spec/spec_helper.rb +2 -2
  99. data/spec/support/migration_helper.rb +19 -0
  100. data/spec/support/providers/example.rb +11 -0
  101. data/spec/support/providers/example_provider.rb +11 -0
  102. metadata +89 -33
  103. data/gemfiles/active_record-rails40.gemfile +0 -7
  104. data/gemfiles/active_record-rails41.gemfile +0 -7
  105. data/gemfiles/active_record-rails42.gemfile +0 -7
  106. data/spec/rails_app/config/initializers/secret_token.rb +0 -7
@@ -28,4 +28,11 @@ class SorceryMailer < ActionMailer::Base
28
28
  mail(to: user.email,
29
29
  subject: 'Your account has been locked due to many wrong logins')
30
30
  end
31
+
32
+ def magic_login_email(user)
33
+ @user = user
34
+ @url = 'http://example.com/login'
35
+ mail(to: user.email,
36
+ subject: 'Magic Login')
37
+ end
31
38
  end
@@ -0,0 +1,13 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
5
+ </head>
6
+ <body>
7
+ <h1>Hello, <%= @user.username %></h1>
8
+ <p>
9
+ To login without a password, just follow this link: <%= @url %>.
10
+ </p>
11
+ <p>Have a great day!</p>
12
+ </body>
13
+ </html>
@@ -0,0 +1,6 @@
1
+ Hello, <%= @user.username %>
2
+ ===============================================
3
+
4
+ To login without a password, just follow this link: <%= @url %>.
5
+
6
+ Have a great day!
@@ -1,4 +1,4 @@
1
- require File.expand_path('../boot', __FILE__)
1
+ require File.expand_path('boot', __dir__)
2
2
 
3
3
  require 'action_controller/railtie'
4
4
  require 'action_mailer/railtie'
@@ -6,16 +6,19 @@ require 'rails/test_unit/railtie'
6
6
 
7
7
  Bundler.require :default, SORCERY_ORM
8
8
 
9
+ # rubocop:disable Lint/HandleExceptions
9
10
  begin
10
11
  require "#{SORCERY_ORM}/railtie"
11
12
  rescue LoadError
13
+ # TODO: Log this issue or change require scheme.
12
14
  end
15
+ # rubocop:enable Lint/HandleExceptions
13
16
 
14
17
  require 'sorcery'
15
18
 
16
19
  module AppRoot
17
20
  class Application < Rails::Application
18
- config.autoload_paths.reject! { |p| p =~ /\/app\/(\w+)$/ && !%w(controllers helpers mailers views).include?(Regexp.last_match(1)) }
21
+ config.autoload_paths.reject! { |p| p =~ %r{/\/app\/(\w+)$/} && !%w[controllers helpers mailers views].include?(Regexp.last_match(1)) }
19
22
  config.autoload_paths += ["#{config.root}/app/#{SORCERY_ORM}"]
20
23
 
21
24
  # Settings in config/environments/* take precedence over those specified here.
@@ -50,7 +53,9 @@ module AppRoot
50
53
  config.filter_parameters += [:password]
51
54
 
52
55
  config.action_mailer.delivery_method = :test
53
-
54
56
  config.active_support.deprecation = :stderr
57
+ if Rails.version >= '5.1.0' && config.active_record.sqlite3.present?
58
+ config.active_record.sqlite3.represent_boolean_as_integer = true
59
+ end
55
60
  end
56
61
  end
@@ -1,4 +1,4 @@
1
1
  # Set up gems listed in the Gemfile.
2
- ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../../../Gemfile', __FILE__)
2
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../../Gemfile', __dir__)
3
3
 
4
4
  require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
@@ -1,5 +1,5 @@
1
1
  # Load the rails application
2
- require File.expand_path('../application', __FILE__)
2
+ require File.expand_path('application', __dir__)
3
3
 
4
4
  # Initialize the rails application
5
5
  AppRoot::Application.initialize!
@@ -11,7 +11,9 @@ 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
16
+ get :test_invalidate_active_session
15
17
  get :test_should_be_logged_in
16
18
  get :test_create_from_provider
17
19
  get :test_add_second_provider
@@ -29,6 +31,10 @@ AppRoot::Application.routes.draw do
29
31
  get :test_login_from_jira
30
32
  get :test_login_from_salesforce
31
33
  get :test_login_from_slack
34
+ get :test_login_from_instagram
35
+ get :test_login_from_auth0
36
+ get :test_login_from_line
37
+ get :test_login_from_discord
32
38
  get :login_at_test
33
39
  get :login_at_test_twitter
34
40
  get :login_at_test_facebook
@@ -42,6 +48,10 @@ AppRoot::Application.routes.draw do
42
48
  get :login_at_test_jira
43
49
  get :login_at_test_salesforce
44
50
  get :login_at_test_slack
51
+ get :login_at_test_instagram
52
+ get :login_at_test_auth0
53
+ get :login_at_test_line
54
+ get :login_at_test_discord
45
55
  get :test_return_to_with_external
46
56
  get :test_return_to_with_external_twitter
47
57
  get :test_return_to_with_external_facebook
@@ -55,6 +65,10 @@ AppRoot::Application.routes.draw do
55
65
  get :test_return_to_with_external_jira
56
66
  get :test_return_to_with_external_salesforce
57
67
  get :test_return_to_with_external_slack
68
+ get :test_return_to_with_external_instagram
69
+ get :test_return_to_with_external_auth0
70
+ get :test_return_to_with_external_line
71
+ get :test_return_to_with_external_discord
58
72
  get :test_http_basic_auth
59
73
  get :some_action_making_a_non_persisted_change_to_the_user
60
74
  post :test_login_with_remember
@@ -0,0 +1,4 @@
1
+ # secrets.yml
2
+
3
+ test:
4
+ secret_key_base: 'a9789f869a0d0ac2f2b683d6e9410c530696b178bca28a7971f4a652b14ff2da89f2cf4dcbf0355f6bc41f81731aa8e46085674d1acc1980436f61cdba76ff5d'
@@ -5,11 +5,11 @@ class AddActivityLoggingToUsers < ActiveRecord::CompatibleLegacyMigration.migrat
5
5
  add_column :users, :last_activity_at, :datetime, default: nil
6
6
  add_column :users, :last_login_from_ip_address, :string, default: nil
7
7
 
8
- add_index :users, [:last_logout_at, :last_activity_at]
8
+ add_index :users, %i[last_logout_at last_activity_at]
9
9
  end
10
10
 
11
11
  def self.down
12
- remove_index :users, [:last_logout_at, :last_activity_at]
12
+ remove_index :users, %i[last_logout_at last_activity_at]
13
13
 
14
14
  remove_column :users, :last_activity_at
15
15
  remove_column :users, :last_logout_at
@@ -0,0 +1,9 @@
1
+ class AddInvalidateSessionsBeforeToUsers < ActiveRecord::CompatibleLegacyMigration.migration_class
2
+ def self.up
3
+ add_column :users, :invalidate_sessions_before, :datetime, default: nil
4
+ end
5
+
6
+ def self.down
7
+ remove_column :users, :invalidate_sessions_before
8
+ end
9
+ end
@@ -0,0 +1,17 @@
1
+ class AddMagicLoginToUsers < ActiveRecord::CompatibleLegacyMigration.migration_class
2
+ def self.up
3
+ add_column :users, :magic_login_token, :string, default: nil
4
+ add_column :users, :magic_login_token_expires_at, :datetime, default: nil
5
+ add_column :users, :magic_login_email_sent_at, :datetime, default: nil
6
+
7
+ add_index :users, :magic_login_token
8
+ end
9
+
10
+ def self.down
11
+ remove_index :users, :magic_login_token
12
+
13
+ remove_column :users, :magic_login_token
14
+ remove_column :users, :magic_login_token_expires_at
15
+ remove_column :users, :magic_login_email_sent_at
16
+ end
17
+ end
@@ -3,11 +3,13 @@ class AddResetPasswordToUsers < ActiveRecord::CompatibleLegacyMigration.migratio
3
3
  add_column :users, :reset_password_token, :string, default: nil
4
4
  add_column :users, :reset_password_token_expires_at, :datetime, default: nil
5
5
  add_column :users, :reset_password_email_sent_at, :datetime, default: nil
6
+ add_column :users, :access_count_to_reset_password_page, :integer, default: 0
6
7
  end
7
8
 
8
9
  def self.down
9
10
  remove_column :users, :reset_password_email_sent_at
10
11
  remove_column :users, :reset_password_token_expires_at
11
12
  remove_column :users, :reset_password_token
13
+ remove_column :users, :access_count_to_reset_password_page
12
14
  end
13
15
  end
@@ -10,14 +10,12 @@
10
10
  #
11
11
  # It's strongly recommended to check this file into your version control system.
12
12
 
13
- ActiveRecord::Schema.define(:version => 20101224223620) do
14
-
15
- create_table "users", :force => true do |t|
16
- t.string "username"
17
- t.string "email"
18
- t.string "crypted_password"
19
- t.datetime "created_at"
20
- t.datetime "updated_at"
13
+ ActiveRecord::Schema.define(version: 20_101_224_223_620) do
14
+ create_table 'users', force: true do |t|
15
+ t.string 'username'
16
+ t.string 'email'
17
+ t.string 'crypted_password'
18
+ t.datetime 'created_at'
19
+ t.datetime 'updated_at'
21
20
  end
22
-
23
21
  end
@@ -0,0 +1,150 @@
1
+ shared_examples_for 'magic_login_model' do
2
+ let(:user) { create_new_user }
3
+ before(:each) do
4
+ User.sorcery_adapter.delete_all
5
+ end
6
+
7
+ context 'loaded plugin configuration' do
8
+ let(:config) { User.sorcery_config }
9
+
10
+ before(:all) do
11
+ sorcery_reload!([:magic_login])
12
+ end
13
+
14
+ after(:each) do
15
+ User.sorcery_config.reset!
16
+ end
17
+
18
+ describe 'enables configuration options' do
19
+ it do
20
+ sorcery_model_property_set(:magic_login_token_attribute_name, :test_magic_login_token)
21
+ expect(config.magic_login_token_attribute_name).to eq :test_magic_login_token
22
+ end
23
+
24
+ it do
25
+ sorcery_model_property_set(:magic_login_token_expires_at_attribute_name, :test_magic_login_token_expires_at)
26
+ expect(config.magic_login_token_expires_at_attribute_name).to eq :test_magic_login_token_expires_at
27
+ end
28
+
29
+ it do
30
+ sorcery_model_property_set(:magic_login_email_sent_at_attribute_name, :test_magic_login_email_sent_at)
31
+ expect(config.magic_login_email_sent_at_attribute_name).to eq :test_magic_login_email_sent_at
32
+ end
33
+
34
+ it do
35
+ TestMailerClass = Class.new # need a mailer class to test
36
+ sorcery_model_property_set(:magic_login_mailer_class, TestMailerClass)
37
+ expect(config.magic_login_mailer_class).to eq TestMailerClass
38
+ end
39
+
40
+ it do
41
+ sorcery_model_property_set(:magic_login_mailer_disabled, false)
42
+ expect(config.magic_login_mailer_disabled).to eq false
43
+ end
44
+
45
+ it do
46
+ sorcery_model_property_set(:magic_login_email_method_name, :test_magic_login_email)
47
+ expect(config.magic_login_email_method_name).to eq :test_magic_login_email
48
+ end
49
+
50
+ it do
51
+ sorcery_model_property_set(:magic_login_expiration_period, 100_000_000)
52
+ expect(config.magic_login_expiration_period).to eq 100_000_000
53
+ end
54
+
55
+ it do
56
+ sorcery_model_property_set(:magic_login_time_between_emails, 100_000_000)
57
+ expect(config.magic_login_time_between_emails).to eq 100_000_000
58
+ end
59
+ end
60
+
61
+ describe '#generate_magic_login_token!' do
62
+ context 'magic_login_token is nil' do
63
+ it "magic_login_token_expires_at and magic_login_email_sent_at aren't nil " do
64
+ user.generate_magic_login_token!
65
+ expect(user.magic_login_token_expires_at).not_to be_nil
66
+ expect(user.magic_login_email_sent_at).not_to be_nil
67
+ end
68
+
69
+ it 'magic_login_token is different from the one before' do
70
+ token_before = user.magic_login_token
71
+ user.generate_magic_login_token!
72
+ expect(user.magic_login_token).not_to eq token_before
73
+ end
74
+ end
75
+
76
+ context 'magic_login_token is not nil' do
77
+ it 'changes `user.magic_login_token`' do
78
+ token_before = user.magic_login_token
79
+ user.generate_magic_login_token!
80
+ expect(user.magic_login_token).not_to eq token_before
81
+ end
82
+ end
83
+ end
84
+
85
+ describe '#deliver_magic_login_instructions!' do
86
+ context 'success' do
87
+ before do
88
+ sorcery_model_property_set(:magic_login_time_between_emails, 30 * 60)
89
+ sorcery_model_property_set(:magic_login_mailer_disabled, false)
90
+ Timecop.travel(10.days.ago) do
91
+ user.send(:"#{config.magic_login_email_sent_at_attribute_name}=", DateTime.now)
92
+ end
93
+ sorcery_model_property_set(:magic_login_mailer_class, ::SorceryMailer)
94
+ end
95
+
96
+ it do
97
+ user.deliver_magic_login_instructions!
98
+ expect(ActionMailer::Base.deliveries.size).to eq 1
99
+ end
100
+
101
+ it do
102
+ expect(user.deliver_magic_login_instructions!).to eq true
103
+ end
104
+ end
105
+
106
+ context 'failure' do
107
+ context 'magic_login_time_between_emails is nil' do
108
+ it 'returns false' do
109
+ sorcery_model_property_set(:magic_login_time_between_emails, nil)
110
+ expect(user.deliver_magic_login_instructions!).to eq false
111
+ end
112
+ end
113
+
114
+ context 'magic_login_email_sent_at is nil' do
115
+ it 'returns false' do
116
+ user.send(:"#{config.magic_login_email_sent_at_attribute_name}=", nil)
117
+ expect(user.deliver_magic_login_instructions!).to eq false
118
+ end
119
+ end
120
+
121
+ context 'now is before magic_login_email_sent_at plus the interval' do
122
+ it 'returns false' do
123
+ user.send(:"#{config.magic_login_email_sent_at_attribute_name}=", DateTime.now)
124
+ sorcery_model_property_set(:magic_login_time_between_emails, 30 * 60)
125
+ expect(user.deliver_magic_login_instructions!).to eq false
126
+ end
127
+ end
128
+
129
+ context 'magic_login_mailer_disabled is true' do
130
+ it 'returns false' do
131
+ sorcery_model_property_set(:magic_login_mailer_disabled, true)
132
+ expect(user.deliver_magic_login_instructions!).to eq false
133
+ end
134
+ end
135
+ end
136
+ end
137
+
138
+ describe '#clear_magic_login_token!' do
139
+ it 'makes magic_login_token_attribute_name and magic_login_token_expires_at_attribute_name nil' do
140
+ user.magic_login_token = 'test_token'
141
+ user.magic_login_token_expires_at = Time.now
142
+
143
+ user.clear_magic_login_token!
144
+
145
+ expect(user.magic_login_token).to eq nil
146
+ expect(user.magic_login_token_expires_at).to eq nil
147
+ end
148
+ end
149
+ end
150
+ end
@@ -27,7 +27,7 @@ shared_examples_for 'rails_3_oauth_model' do
27
27
 
28
28
  it "'load_from_provider' returns nil if user doesn't exist" do
29
29
  external_user
30
- expect(User.load_from_provider(:twitter, 980342)).to be_nil
30
+ expect(User.load_from_provider(:twitter, 980_342)).to be_nil
31
31
  end
32
32
  end
33
33
  end
@@ -42,7 +42,7 @@ shared_examples_for 'rails_3_remember_me_model' do
42
42
  user.remember_me!
43
43
  end
44
44
 
45
- expect(user.remember_me_token_expires_at.utc.to_s).to eq (ts + 2 * 60 * 60 * 24).utc.to_s
45
+ expect(user.remember_me_token_expires_at.utc.to_s).to eq((ts + 2 * 60 * 60 * 24).utc.to_s)
46
46
  end
47
47
 
48
48
  context 'when not persisting globally' do
@@ -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
@@ -214,6 +216,22 @@ shared_examples_for 'rails_3_reset_password_model' do
214
216
  expect(user.reset_password_token).not_to eq old_password_code
215
217
  end
216
218
 
219
+ describe '#increment_password_reset_page_access_counter' do
220
+ it 'increments reset_password_page_access_count_attribute_name' do
221
+ expected_count = user.access_count_to_reset_password_page + 1
222
+ user.increment_password_reset_page_access_counter
223
+ expect(user.access_count_to_reset_password_page).to eq expected_count
224
+ end
225
+ end
226
+
227
+ describe '#reset_password_reset_page_access_counter' do
228
+ it 'reset reset_password_page_access_count_attribute_name into 0' do
229
+ user.update(access_count_to_reset_password_page: 10)
230
+ user.reset_password_reset_page_access_counter
231
+ expect(user.access_count_to_reset_password_page).to eq 0
232
+ end
233
+ end
234
+
217
235
  context 'mailer is enabled' do
218
236
  it 'sends an email on reset' do
219
237
  old_size = ActionMailer::Base.deliveries.size
@@ -229,7 +247,7 @@ shared_examples_for 'rails_3_reset_password_model' do
229
247
  end
230
248
 
231
249
  it 'does not send an email if time between emails has not passed since last email' do
232
- sorcery_model_property_set(:reset_password_time_between_emails, 10000)
250
+ sorcery_model_property_set(:reset_password_time_between_emails, 10_000)
233
251
  old_size = ActionMailer::Base.deliveries.size
234
252
  user.deliver_reset_password_instructions!
235
253
 
@@ -273,7 +291,7 @@ shared_examples_for 'rails_3_reset_password_model' do
273
291
  end
274
292
 
275
293
  it 'does not send an email if time between emails has not passed since last email' do
276
- sorcery_model_property_set(:reset_password_time_between_emails, 10000)
294
+ sorcery_model_property_set(:reset_password_time_between_emails, 10_000)
277
295
  old_size = ActionMailer::Base.deliveries.size
278
296
  user.deliver_reset_password_instructions!
279
297
 
@@ -298,19 +316,33 @@ shared_examples_for 'rails_3_reset_password_model' do
298
316
  end
299
317
  end
300
318
 
301
- 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
302
320
  user.deliver_reset_password_instructions!
303
321
 
304
322
  expect(user.reset_password_token).not_to be_nil
323
+ expect(user).to_not receive(:save)
324
+ expect(user).to receive(:save!)
305
325
 
306
326
  user.change_password!('blabulsdf')
307
- user.save!
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)
308
340
 
309
341
  expect(user.reset_password_token).to be_nil
310
342
  end
311
343
 
312
344
  it 'returns false if time between emails has not passed since last email' do
313
- sorcery_model_property_set(:reset_password_time_between_emails, 10000)
345
+ sorcery_model_property_set(:reset_password_time_between_emails, 10_000)
314
346
  user.deliver_reset_password_instructions!
315
347
 
316
348
  expect(user.deliver_reset_password_instructions!).to be false