devise 3.3.0 → 3.5.10

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of devise might be problematic. Click here for more details.

Files changed (138) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +29 -20
  3. data/CHANGELOG.md +219 -102
  4. data/CODE_OF_CONDUCT.md +22 -0
  5. data/CONTRIBUTING.md +2 -0
  6. data/Gemfile +3 -2
  7. data/Gemfile.lock +101 -80
  8. data/MIT-LICENSE +1 -1
  9. data/README.md +87 -43
  10. data/Rakefile +2 -1
  11. data/app/controllers/devise/confirmations_controller.rb +5 -1
  12. data/app/controllers/devise/omniauth_callbacks_controller.rb +4 -0
  13. data/app/controllers/devise/passwords_controller.rb +14 -4
  14. data/app/controllers/devise/registrations_controller.rb +10 -11
  15. data/app/controllers/devise/sessions_controller.rb +7 -2
  16. data/app/controllers/devise/unlocks_controller.rb +3 -0
  17. data/app/controllers/devise_controller.rb +44 -21
  18. data/app/mailers/devise/mailer.rb +4 -0
  19. data/app/views/devise/confirmations/new.html.erb +7 -3
  20. data/app/views/devise/mailer/password_change.html.erb +3 -0
  21. data/app/views/devise/passwords/edit.html.erb +14 -5
  22. data/app/views/devise/passwords/new.html.erb +7 -3
  23. data/app/views/devise/registrations/edit.html.erb +19 -9
  24. data/app/views/devise/registrations/new.html.erb +18 -7
  25. data/app/views/devise/sessions/new.html.erb +15 -6
  26. data/app/views/devise/shared/{_links.erb → _links.html.erb} +1 -1
  27. data/app/views/devise/unlocks/new.html.erb +7 -3
  28. data/config/locales/en.yml +4 -2
  29. data/devise.gemspec +2 -2
  30. data/gemfiles/Gemfile.rails-3.2-stable.lock +54 -48
  31. data/gemfiles/Gemfile.rails-4.0-stable +1 -0
  32. data/gemfiles/Gemfile.rails-4.0-stable.lock +63 -59
  33. data/gemfiles/{Gemfile.rails-head → Gemfile.rails-4.1-stable} +3 -5
  34. data/gemfiles/Gemfile.rails-4.1-stable.lock +171 -0
  35. data/gemfiles/Gemfile.rails-4.2-stable +30 -0
  36. data/gemfiles/Gemfile.rails-4.2-stable.lock +193 -0
  37. data/lib/devise/controllers/helpers.rb +12 -6
  38. data/lib/devise/controllers/rememberable.rb +9 -2
  39. data/lib/devise/controllers/sign_in_out.rb +2 -8
  40. data/lib/devise/controllers/store_location.rb +3 -1
  41. data/lib/devise/controllers/url_helpers.rb +7 -9
  42. data/lib/devise/encryptor.rb +22 -0
  43. data/lib/devise/failure_app.rb +56 -14
  44. data/lib/devise/hooks/timeoutable.rb +5 -7
  45. data/lib/devise/mapping.rb +2 -1
  46. data/lib/devise/models/authenticatable.rb +28 -28
  47. data/lib/devise/models/confirmable.rb +51 -17
  48. data/lib/devise/models/database_authenticatable.rb +17 -11
  49. data/lib/devise/models/lockable.rb +7 -3
  50. data/lib/devise/models/recoverable.rb +23 -15
  51. data/lib/devise/models/rememberable.rb +56 -22
  52. data/lib/devise/models/timeoutable.rb +0 -6
  53. data/lib/devise/models/trackable.rb +1 -2
  54. data/lib/devise/models/validatable.rb +3 -3
  55. data/lib/devise/models.rb +1 -1
  56. data/lib/devise/rails/routes.rb +33 -27
  57. data/lib/devise/rails.rb +1 -1
  58. data/lib/devise/strategies/authenticatable.rb +8 -6
  59. data/lib/devise/strategies/database_authenticatable.rb +2 -1
  60. data/lib/devise/strategies/rememberable.rb +13 -3
  61. data/lib/devise/test_helpers.rb +2 -2
  62. data/lib/devise/version.rb +1 -1
  63. data/lib/devise.rb +39 -37
  64. data/lib/generators/active_record/devise_generator.rb +2 -1
  65. data/lib/generators/active_record/templates/migration.rb +1 -1
  66. data/lib/generators/active_record/templates/migration_existing.rb +1 -1
  67. data/lib/generators/devise/controllers_generator.rb +44 -0
  68. data/lib/generators/devise/views_generator.rb +14 -3
  69. data/lib/generators/templates/controllers/README +14 -0
  70. data/lib/generators/templates/controllers/confirmations_controller.rb +28 -0
  71. data/lib/generators/templates/controllers/omniauth_callbacks_controller.rb +28 -0
  72. data/lib/generators/templates/controllers/passwords_controller.rb +32 -0
  73. data/lib/generators/templates/controllers/registrations_controller.rb +60 -0
  74. data/lib/generators/templates/controllers/sessions_controller.rb +25 -0
  75. data/lib/generators/templates/controllers/unlocks_controller.rb +28 -0
  76. data/lib/generators/templates/devise.rb +19 -13
  77. data/lib/generators/templates/markerb/confirmation_instructions.markerb +1 -1
  78. data/lib/generators/templates/markerb/password_change.markerb +3 -0
  79. data/lib/generators/templates/markerb/reset_password_instructions.markerb +1 -1
  80. data/lib/generators/templates/markerb/unlock_instructions.markerb +1 -1
  81. data/lib/generators/templates/simple_form_for/passwords/edit.html.erb +1 -1
  82. data/lib/generators/templates/simple_form_for/registrations/new.html.erb +1 -1
  83. data/lib/generators/templates/simple_form_for/sessions/new.html.erb +2 -2
  84. data/test/controllers/custom_registrations_controller_test.rb +6 -1
  85. data/test/controllers/helper_methods_test.rb +21 -0
  86. data/test/controllers/helpers_test.rb +5 -0
  87. data/test/controllers/inherited_controller_i18n_messages_test.rb +51 -0
  88. data/test/controllers/internal_helpers_test.rb +10 -4
  89. data/test/controllers/load_hooks_controller_test.rb +19 -0
  90. data/test/controllers/passwords_controller_test.rb +1 -1
  91. data/test/controllers/sessions_controller_test.rb +3 -3
  92. data/test/controllers/url_helpers_test.rb +6 -0
  93. data/test/devise_test.rb +3 -3
  94. data/test/failure_app_test.rb +47 -0
  95. data/test/generators/controllers_generator_test.rb +48 -0
  96. data/test/generators/views_generator_test.rb +8 -1
  97. data/test/helpers/devise_helper_test.rb +9 -12
  98. data/test/integration/authenticatable_test.rb +1 -1
  99. data/test/integration/database_authenticatable_test.rb +11 -0
  100. data/test/integration/http_authenticatable_test.rb +1 -1
  101. data/test/integration/omniauthable_test.rb +12 -10
  102. data/test/integration/recoverable_test.rb +13 -0
  103. data/test/integration/rememberable_test.rb +50 -3
  104. data/test/integration/timeoutable_test.rb +13 -18
  105. data/test/mailers/confirmation_instructions_test.rb +1 -1
  106. data/test/mapping_test.rb +7 -0
  107. data/test/models/authenticatable_test.rb +10 -0
  108. data/test/models/confirmable_test.rb +99 -42
  109. data/test/models/database_authenticatable_test.rb +20 -0
  110. data/test/models/lockable_test.rb +45 -17
  111. data/test/models/recoverable_test.rb +62 -7
  112. data/test/models/rememberable_test.rb +68 -97
  113. data/test/models/validatable_test.rb +5 -5
  114. data/test/models_test.rb +15 -6
  115. data/test/rails_app/app/active_record/user_without_email.rb +8 -0
  116. data/test/rails_app/app/controllers/admins_controller.rb +0 -5
  117. data/test/rails_app/app/controllers/custom/registrations_controller.rb +10 -0
  118. data/test/rails_app/app/mailers/users/from_proc_mailer.rb +3 -0
  119. data/test/rails_app/app/mailers/users/mailer.rb +0 -9
  120. data/test/rails_app/app/mailers/users/reply_to_mailer.rb +4 -0
  121. data/test/rails_app/app/mongoid/user_without_email.rb +33 -0
  122. data/test/rails_app/config/application.rb +1 -1
  123. data/test/rails_app/config/environments/production.rb +6 -2
  124. data/test/rails_app/config/environments/test.rb +7 -2
  125. data/test/rails_app/config/initializers/devise.rb +12 -15
  126. data/test/rails_app/config/routes.rb +6 -3
  127. data/test/rails_app/db/migrate/20100401102949_create_tables.rb +2 -2
  128. data/test/rails_app/lib/shared_user.rb +1 -1
  129. data/test/rails_app/lib/shared_user_without_email.rb +26 -0
  130. data/test/rails_test.rb +9 -0
  131. data/test/support/helpers.rb +13 -6
  132. data/test/support/integration.rb +2 -2
  133. data/test/test_helper.rb +5 -0
  134. data/test/test_helpers_test.rb +22 -7
  135. data/test/test_models.rb +2 -2
  136. data/test/time_helpers.rb +137 -0
  137. metadata +58 -8
  138. data/gemfiles/Gemfile.rails-head.lock +0 -190
@@ -42,7 +42,7 @@ class HttpAuthenticationTest < ActionDispatch::IntegrationTest
42
42
  sign_in_as_new_user_with_http("unknown")
43
43
  assert_equal 401, status
44
44
  assert_equal "application/xml; charset=utf-8", headers["Content-Type"]
45
- assert_match "<error>Invalid email address or password.</error>", response.body
45
+ assert_match "<error>Invalid email or password.</error>", response.body
46
46
  end
47
47
 
48
48
  test 'returns a custom response with www-authenticate and chosen realm' do
@@ -20,9 +20,11 @@ class OmniauthableIntegrationTest < ActionDispatch::IntegrationTest
20
20
  "credentials" => {"token" => 'plataformatec'},
21
21
  "extra" => {"user_hash" => FACEBOOK_INFO}
22
22
  }
23
+ OmniAuth.config.add_camelization 'facebook', 'FaceBook'
23
24
  end
24
25
 
25
26
  teardown do
27
+ OmniAuth.config.camelizations.delete('facebook')
26
28
  OmniAuth.config.test_mode = false
27
29
  end
28
30
 
@@ -40,7 +42,7 @@ class OmniauthableIntegrationTest < ActionDispatch::IntegrationTest
40
42
 
41
43
  test "can access omniauth.auth in the env hash" do
42
44
  visit "/users/sign_in"
43
- click_link "Sign in with Facebook"
45
+ click_link "Sign in with FaceBook"
44
46
 
45
47
  json = ActiveSupport::JSON.decode(response.body)
46
48
 
@@ -54,7 +56,7 @@ class OmniauthableIntegrationTest < ActionDispatch::IntegrationTest
54
56
  test "cleans up session on sign up" do
55
57
  assert_no_difference "User.count" do
56
58
  visit "/users/sign_in"
57
- click_link "Sign in with Facebook"
59
+ click_link "Sign in with FaceBook"
58
60
  end
59
61
 
60
62
  assert session["devise.facebook_data"]
@@ -75,7 +77,7 @@ class OmniauthableIntegrationTest < ActionDispatch::IntegrationTest
75
77
  test "cleans up session on cancel" do
76
78
  assert_no_difference "User.count" do
77
79
  visit "/users/sign_in"
78
- click_link "Sign in with Facebook"
80
+ click_link "Sign in with FaceBook"
79
81
  end
80
82
 
81
83
  assert session["devise.facebook_data"]
@@ -86,7 +88,7 @@ class OmniauthableIntegrationTest < ActionDispatch::IntegrationTest
86
88
  test "cleans up session on sign in" do
87
89
  assert_no_difference "User.count" do
88
90
  visit "/users/sign_in"
89
- click_link "Sign in with Facebook"
91
+ click_link "Sign in with FaceBook"
90
92
  end
91
93
 
92
94
  assert session["devise.facebook_data"]
@@ -96,13 +98,13 @@ class OmniauthableIntegrationTest < ActionDispatch::IntegrationTest
96
98
 
97
99
  test "sign in and send remember token if configured" do
98
100
  visit "/users/sign_in"
99
- click_link "Sign in with Facebook"
101
+ click_link "Sign in with FaceBook"
100
102
  assert_nil warden.cookies["remember_user_token"]
101
103
 
102
104
  stub_action!(:sign_in_facebook) do
103
105
  create_user
104
106
  visit "/users/sign_in"
105
- click_link "Sign in with Facebook"
107
+ click_link "Sign in with FaceBook"
106
108
  assert warden.authenticated?(:user)
107
109
  assert warden.cookies["remember_user_token"]
108
110
  end
@@ -118,16 +120,16 @@ class OmniauthableIntegrationTest < ActionDispatch::IntegrationTest
118
120
  OmniAuth.config.mock_auth[:facebook] = :access_denied
119
121
  visit "/users/auth/facebook/callback?error=access_denied"
120
122
  assert_current_url "/users/sign_in"
121
- assert_contain 'Could not authenticate you from Facebook because "Access denied".'
123
+ assert_contain 'Could not authenticate you from FaceBook because "Access denied".'
122
124
  end
123
125
 
124
- test "handles other exceptions from omniauth" do
126
+ test "handles other exceptions from OmniAuth" do
125
127
  OmniAuth.config.mock_auth[:facebook] = :invalid_credentials
126
128
 
127
129
  visit "/users/sign_in"
128
- click_link "Sign in with Facebook"
130
+ click_link "Sign in with FaceBook"
129
131
 
130
132
  assert_current_url "/users/sign_in"
131
- assert_contain 'Could not authenticate you from Facebook because "Invalid credentials".'
133
+ assert_contain 'Could not authenticate you from FaceBook because "Invalid credentials".'
132
134
  end
133
135
  end
@@ -197,6 +197,19 @@ class PasswordTest < ActionDispatch::IntegrationTest
197
197
  assert warden.authenticated?(:user)
198
198
  end
199
199
 
200
+ test 'does not sign in user automatically after changing its password if config.sign_in_after_reset_password is false' do
201
+ swap Devise, sign_in_after_reset_password: false do
202
+ create_user
203
+ request_forgot_password
204
+ reset_password
205
+
206
+ assert_contain 'Your password has been changed successfully.'
207
+ assert_not_contain 'You are now signed in.'
208
+ assert_equal new_user_session_path, @request.path
209
+ assert !warden.authenticated?(:user)
210
+ end
211
+ end
212
+
200
213
  test 'does not sign in user automatically after changing its password if it\'s locked and unlock strategy is :none or :time' do
201
214
  [:none, :time].each do |strategy|
202
215
  swap Devise, unlock_strategy: strategy do
@@ -1,10 +1,15 @@
1
1
  require 'test_helper'
2
2
 
3
3
  class RememberMeTest < ActionDispatch::IntegrationTest
4
+ if (Rails::VERSION::MAJOR < 4) || (Rails::VERSION::MAJOR >= 4 && Rails::VERSION::MINOR < 1)
5
+ require 'time_helpers'
6
+ include ActiveSupport::Testing::TimeHelpers
7
+ end
8
+
4
9
  def create_user_and_remember(add_to_token='')
5
10
  user = create_user
6
11
  user.remember_me!
7
- raw_cookie = User.serialize_into_cookie(user).tap { |a| a.last << add_to_token }
12
+ raw_cookie = User.serialize_into_cookie(user).tap { |a| a[1] << add_to_token }
8
13
  cookies['remember_user_token'] = generate_signed_cookie(raw_cookie)
9
14
  user
10
15
  end
@@ -92,7 +97,6 @@ class RememberMeTest < ActionDispatch::IntegrationTest
92
97
  assert_response :success
93
98
  assert warden.authenticated?(:user)
94
99
  assert warden.user(:user) == user
95
- assert_match /remember_user_token[^\n]*HttpOnly/, response.headers["Set-Cookie"], "Expected Set-Cookie header in response to set HttpOnly flag on remember_user_token cookie."
96
100
  end
97
101
 
98
102
  test 'remember the user before sign up and redirect them to their home' do
@@ -118,6 +122,40 @@ class RememberMeTest < ActionDispatch::IntegrationTest
118
122
  end
119
123
  end
120
124
 
125
+ test 'extends remember period when extend remember period config is true' do
126
+ swap Devise, extend_remember_period: true, remember_for: 1.year do
127
+ user = create_user_and_remember
128
+ old_remember_token = nil
129
+
130
+ travel_to 1.day.ago do
131
+ get root_path
132
+ old_remember_token = request.cookies['remember_user_token']
133
+ end
134
+
135
+ get root_path
136
+ current_remember_token = request.cookies['remember_user_token']
137
+
138
+ refute_equal old_remember_token, current_remember_token
139
+ end
140
+ end
141
+
142
+ test 'does not extend remember period when extend period config is false' do
143
+ swap Devise, extend_remember_period: false, remember_for: 1.year do
144
+ user = create_user_and_remember
145
+ old_remember_token = nil
146
+
147
+ travel_to 1.day.ago do
148
+ get root_path
149
+ old_remember_token = request.cookies['remember_user_token']
150
+ end
151
+
152
+ get root_path
153
+ current_remember_token = request.cookies['remember_user_token']
154
+
155
+ assert_equal old_remember_token, current_remember_token
156
+ end
157
+ end
158
+
121
159
  test 'do not remember other scopes' do
122
160
  create_user_and_remember
123
161
  get root_path
@@ -135,7 +173,7 @@ class RememberMeTest < ActionDispatch::IntegrationTest
135
173
 
136
174
  test 'do not remember with expired token' do
137
175
  create_user_and_remember
138
- swap Devise, remember_for: 0 do
176
+ swap Devise, remember_for: 0.days do
139
177
  get users_path
140
178
  assert_not warden.authenticated?(:user)
141
179
  assert_redirected_to new_user_session_path
@@ -164,4 +202,13 @@ class RememberMeTest < ActionDispatch::IntegrationTest
164
202
  get users_path
165
203
  assert_not warden.authenticated?(:user)
166
204
  end
205
+
206
+ test 'valid sign in calls after_remembered callback' do
207
+ user = create_user_and_remember
208
+
209
+ User.expects(:serialize_from_cookie).returns user
210
+ user.expects :after_remembered
211
+
212
+ get new_user_registration_path
213
+ end
167
214
  end
@@ -24,6 +24,18 @@ class SessionTimeoutTest < ActionDispatch::IntegrationTest
24
24
  assert_equal old_last_request, last_request_at
25
25
  end
26
26
 
27
+ test 'does not set last request at in user session after each request if timeoutable is disabled' do
28
+ sign_in_as_user
29
+ old_last_request = last_request_at
30
+ assert_not_nil last_request_at
31
+
32
+ new_time = 2.seconds.from_now
33
+ Time.stubs(:now).returns(new_time)
34
+
35
+ get users_path, {}, 'devise.skip_timeoutable' => true
36
+ assert_equal old_last_request, last_request_at
37
+ end
38
+
27
39
  test 'does not time out user session before default limit time' do
28
40
  sign_in_as_user
29
41
  assert_response :success
@@ -110,23 +122,6 @@ class SessionTimeoutTest < ActionDispatch::IntegrationTest
110
122
  assert_contain 'You are signed in'
111
123
  end
112
124
 
113
- test 'admin does not explode on time out' do
114
- admin = sign_in_as_admin
115
- get expire_admin_path(admin)
116
-
117
- Admin.send :define_method, :reset_authentication_token! do
118
- nil
119
- end
120
-
121
- begin
122
- get admins_path
123
- assert_redirected_to admins_path
124
- assert_not warden.authenticated?(:admin)
125
- ensure
126
- Admin.send(:remove_method, :reset_authentication_token!)
127
- end
128
- end
129
-
130
125
  test 'user configured timeout limit' do
131
126
  swap Devise, timeout_in: 8.minutes do
132
127
  user = sign_in_as_user
@@ -180,7 +175,7 @@ class SessionTimeoutTest < ActionDispatch::IntegrationTest
180
175
  assert warden.authenticated?(:user)
181
176
  end
182
177
 
183
- test 'does not crashes when the last_request_at is a String' do
178
+ test 'does not crash when the last_request_at is a String' do
184
179
  user = sign_in_as_user
185
180
 
186
181
  get edit_form_user_path(user, last_request_at: Time.now.utc.to_s)
@@ -86,7 +86,7 @@ class ConfirmationInstructionsTest < ActionMailer::TestCase
86
86
  host, port = ActionMailer::Base.default_url_options.values_at :host, :port
87
87
 
88
88
  if mail.body.encoded =~ %r{<a href=\"http://#{host}:#{port}/users/confirmation\?confirmation_token=([^"]+)">}
89
- assert_equal Devise.token_generator.digest(user.class, :confirmation_token, $1), user.confirmation_token
89
+ assert_equal $1, user.confirmation_token
90
90
  else
91
91
  flunk "expected confirmation url regex to match"
92
92
  end
data/test/mapping_test.rb CHANGED
@@ -62,6 +62,7 @@ class MappingTest < ActiveSupport::TestCase
62
62
  test 'find scope for a given object' do
63
63
  assert_equal :user, Devise::Mapping.find_scope!(User)
64
64
  assert_equal :user, Devise::Mapping.find_scope!(:user)
65
+ assert_equal :user, Devise::Mapping.find_scope!("user")
65
66
  assert_equal :user, Devise::Mapping.find_scope!(User.new)
66
67
  end
67
68
 
@@ -70,6 +71,12 @@ class MappingTest < ActiveSupport::TestCase
70
71
  assert_equal :user, Devise::Mapping.find_scope!(Class.new(User).new)
71
72
  end
72
73
 
74
+ test 'find scope uses devise_scope' do
75
+ user = User.new
76
+ def user.devise_scope; :special_scope; end
77
+ assert_equal :special_scope, Devise::Mapping.find_scope!(user)
78
+ end
79
+
73
80
  test 'find scope raises an error if cannot be found' do
74
81
  assert_raise RuntimeError do
75
82
  Devise::Mapping.find_scope!(String)
@@ -10,4 +10,14 @@ class AuthenticatableTest < ActiveSupport::TestCase
10
10
  assert_equal User.find_first_by_auth_conditions({ email: "example@example.com" }), user
11
11
  assert_nil User.find_first_by_auth_conditions({ email: "example@example.com" }, id: user.id.to_s.next)
12
12
  end
13
+
14
+ if defined?(ActionController::Parameters)
15
+ test 'does not passes an ActionController::Parameters to find_first_by_auth_conditions through find_or_initialize_with_errors' do
16
+ user = create_user(email: 'example@example.com')
17
+ attributes = ActionController::Parameters.new(email: 'example@example.com')
18
+
19
+ User.expects(:find_first_by_auth_conditions).with('email' => 'example@example.com').returns(user)
20
+ User.find_or_initialize_with_errors([:email], attributes)
21
+ end
22
+ end
13
23
  end
@@ -23,31 +23,24 @@ class ConfirmableTest < ActiveSupport::TestCase
23
23
  test 'should confirm a user by updating confirmed at' do
24
24
  user = create_user
25
25
  assert_nil user.confirmed_at
26
- assert user.confirm!
26
+ assert user.confirm
27
27
  assert_not_nil user.confirmed_at
28
28
  end
29
29
 
30
- test 'should clear confirmation token while confirming a user' do
31
- user = create_user
32
- assert_present user.confirmation_token
33
- user.confirm!
34
- assert_nil user.confirmation_token
35
- end
36
-
37
30
  test 'should verify whether a user is confirmed or not' do
38
31
  assert_not new_user.confirmed?
39
32
  user = create_user
40
33
  assert_not user.confirmed?
41
- user.confirm!
34
+ user.confirm
42
35
  assert user.confirmed?
43
36
  end
44
37
 
45
38
  test 'should not confirm a user already confirmed' do
46
39
  user = create_user
47
- assert user.confirm!
40
+ assert user.confirm
48
41
  assert_blank user.errors[:email]
49
42
 
50
- assert_not user.confirm!
43
+ assert_not user.confirm
51
44
  assert_equal "was already confirmed, please try signing in", user.errors[:email].join
52
45
  end
53
46
 
@@ -80,6 +73,16 @@ class ConfirmableTest < ActiveSupport::TestCase
80
73
  assert_equal "was already confirmed, please try signing in", confirmed_user.errors[:email].join
81
74
  end
82
75
 
76
+ test 'should show error when a token has already been used' do
77
+ user = create_user
78
+ raw = user.raw_confirmation_token
79
+ User.confirm_by_token(raw)
80
+ assert user.reload.confirmed?
81
+
82
+ confirmed_user = User.confirm_by_token(raw)
83
+ assert_equal "was already confirmed, please try signing in", confirmed_user.errors[:email].join
84
+ end
85
+
83
86
  test 'should send confirmation instructions by email' do
84
87
  assert_email_sent "mynewuser@example.com" do
85
88
  create_user email: "mynewuser@example.com"
@@ -111,7 +114,7 @@ class ConfirmableTest < ActiveSupport::TestCase
111
114
 
112
115
  assert_email_not_sent do
113
116
  user.save!
114
- assert !user.confirmed?
117
+ assert_not user.confirmed?
115
118
  end
116
119
  end
117
120
 
@@ -165,18 +168,19 @@ class ConfirmableTest < ActiveSupport::TestCase
165
168
 
166
169
  test 'should not reset confirmation status or token when updating email' do
167
170
  user = create_user
168
- user.confirm!
171
+ original_token = user.confirmation_token
172
+ user.confirm
169
173
  user.email = 'new_test@example.com'
170
174
  user.save!
171
175
 
172
176
  user.reload
173
177
  assert user.confirmed?
174
- assert_nil user.confirmation_token
178
+ assert_equal original_token, user.confirmation_token
175
179
  end
176
180
 
177
181
  test 'should not be able to send instructions if the user is already confirmed' do
178
182
  user = create_user
179
- user.confirm!
183
+ user.confirm
180
184
  assert_not user.resend_confirmation_instructions
181
185
  assert user.confirmed?
182
186
  assert_equal 'was already confirmed, please try signing in', user.errors[:email].join
@@ -211,7 +215,7 @@ class ConfirmableTest < ActiveSupport::TestCase
211
215
  assert_not user.confirmed?
212
216
  assert_not user.active_for_authentication?
213
217
 
214
- user.confirm!
218
+ user.confirm
215
219
  assert user.confirmed?
216
220
  assert user.active_for_authentication?
217
221
  end
@@ -219,15 +223,16 @@ class ConfirmableTest < ActiveSupport::TestCase
219
223
  test 'should not be active when confirm in is zero' do
220
224
  Devise.allow_unconfirmed_access_for = 0.days
221
225
  user = create_user
222
- user.confirmation_sent_at = Date.today
226
+ user.confirmation_sent_at = Time.zone.today
223
227
  assert_not user.active_for_authentication?
224
228
  end
225
229
 
226
230
  test 'should be active when we set allow_unconfirmed_access_for to nil' do
227
- Devise.allow_unconfirmed_access_for = nil
228
- user = create_user
229
- user.confirmation_sent_at = Date.today
230
- assert user.active_for_authentication?
231
+ swap Devise, allow_unconfirmed_access_for: nil do
232
+ user = create_user
233
+ user.confirmation_sent_at = Time.zone.today
234
+ assert user.active_for_authentication?
235
+ end
231
236
  end
232
237
 
233
238
  test 'should not be active without confirmation' do
@@ -245,6 +250,16 @@ class ConfirmableTest < ActiveSupport::TestCase
245
250
  assert user.reload.active_for_authentication?
246
251
  end
247
252
 
253
+ test 'should not break when a user tries to reset their password in the case where confirmation is not required and confirm_within is set' do
254
+ swap Devise, confirm_within: 3.days do
255
+ user = create_user
256
+ user.instance_eval { def confirmation_required?; false end }
257
+ user.confirmation_sent_at = nil
258
+ user.save
259
+ assert user.reload.confirm!
260
+ end
261
+ end
262
+
248
263
  test 'should find a user to send email instructions for the user confirm its email by authentication_keys' do
249
264
  swap Devise, authentication_keys: [:username, :email] do
250
265
  user = create_user
@@ -286,12 +301,23 @@ class ConfirmableTest < ActiveSupport::TestCase
286
301
  end
287
302
  end
288
303
 
289
- test 'always generate a new token on resend' do
304
+ test 'do not generate a new token on resend' do
290
305
  user = create_user
291
306
  old = user.confirmation_token
292
307
  user = User.find(user.id)
293
308
  user.resend_confirmation_instructions
294
- assert_not_equal user.confirmation_token, old
309
+ assert_equal user.confirmation_token, old
310
+ end
311
+
312
+ test 'generate a new token after first has expired' do
313
+ swap Devise, confirm_within: 3.days do
314
+ user = create_user
315
+ old = user.confirmation_token
316
+ user.update_attribute(:confirmation_sent_at, 4.days.ago)
317
+ user = User.find(user.id)
318
+ user.resend_confirmation_instructions
319
+ assert_not_equal user.confirmation_token, old
320
+ end
295
321
  end
296
322
 
297
323
  test 'should call after_confirmation if confirmed' do
@@ -300,43 +326,52 @@ class ConfirmableTest < ActiveSupport::TestCase
300
326
  self.username = self.username.to_s + 'updated'
301
327
  end
302
328
  old = user.username
303
- assert user.confirm!
329
+ assert user.confirm
304
330
  assert_not_equal user.username, old
305
331
  end
306
332
 
307
333
  test 'should not call after_confirmation if not confirmed' do
308
334
  user = create_user
309
- assert user.confirm!
335
+ assert user.confirm
310
336
  user.define_singleton_method :after_confirmation do
311
337
  self.username = self.username.to_s + 'updated'
312
338
  end
313
339
  old = user.username
314
- assert_not user.confirm!
340
+ assert_not user.confirm
315
341
  assert_equal user.username, old
316
342
  end
343
+
344
+ test 'should always perform validations upon confirm when ensure valid true' do
345
+ admin = create_admin
346
+ admin.stubs(:valid?).returns(false)
347
+ assert_not admin.confirm(ensure_valid: true)
348
+ end
317
349
  end
318
350
 
319
351
  class ReconfirmableTest < ActiveSupport::TestCase
320
352
  test 'should not worry about validations on confirm even with reconfirmable' do
321
353
  admin = create_admin
322
354
  admin.reset_password_token = "a"
323
- assert admin.confirm!
355
+ assert admin.confirm
324
356
  end
325
357
 
326
358
  test 'should generate confirmation token after changing email' do
327
359
  admin = create_admin
328
- assert admin.confirm!
329
- assert_nil admin.confirmation_token
360
+ assert admin.confirm
361
+ residual_token = admin.confirmation_token
330
362
  assert admin.update_attributes(email: 'new_test@example.com')
331
- assert_not_nil admin.confirmation_token
363
+ assert_not_equal residual_token, admin.confirmation_token
332
364
  end
333
365
 
334
- test 'should not generate confirmation token if skipping reconfirmation after changing email' do
366
+ test 'should not regenerate confirmation token or require reconfirmation if skipping reconfirmation after changing email' do
335
367
  admin = create_admin
336
- assert admin.confirm!
368
+ original_token = admin.confirmation_token
369
+ assert admin.confirm
337
370
  admin.skip_reconfirmation!
338
371
  assert admin.update_attributes(email: 'new_test@example.com')
339
- assert_nil admin.confirmation_token
372
+ assert admin.confirmed?
373
+ assert_not admin.pending_reconfirmation?
374
+ assert_equal original_token, admin.confirmation_token
340
375
  end
341
376
 
342
377
  test 'should skip sending reconfirmation email when email is changed and skip_confirmation_notification! is invoked' do
@@ -350,7 +385,7 @@ class ReconfirmableTest < ActiveSupport::TestCase
350
385
 
351
386
  test 'should regenerate confirmation token after changing email' do
352
387
  admin = create_admin
353
- assert admin.confirm!
388
+ assert admin.confirm
354
389
  assert admin.update_attributes(email: 'old_test@example.com')
355
390
  token = admin.confirmation_token
356
391
  assert admin.update_attributes(email: 'new_test@example.com')
@@ -359,7 +394,15 @@ class ReconfirmableTest < ActiveSupport::TestCase
359
394
 
360
395
  test 'should send confirmation instructions by email after changing email' do
361
396
  admin = create_admin
362
- assert admin.confirm!
397
+ assert admin.confirm
398
+ assert_email_sent "new_test@example.com" do
399
+ assert admin.update_attributes(email: 'new_test@example.com')
400
+ end
401
+ assert_match "new_test@example.com", ActionMailer::Base.deliveries.last.body.encoded
402
+ end
403
+
404
+ test 'should send confirmation instructions by email after changing email from nil' do
405
+ admin = create_admin(email: nil)
363
406
  assert_email_sent "new_test@example.com" do
364
407
  assert admin.update_attributes(email: 'new_test@example.com')
365
408
  end
@@ -368,7 +411,7 @@ class ReconfirmableTest < ActiveSupport::TestCase
368
411
 
369
412
  test 'should not send confirmation by email after changing password' do
370
413
  admin = create_admin
371
- assert admin.confirm!
414
+ assert admin.confirm
372
415
  assert_email_not_sent do
373
416
  assert admin.update_attributes(password: 'newpass', password_confirmation: 'newpass')
374
417
  end
@@ -376,7 +419,7 @@ class ReconfirmableTest < ActiveSupport::TestCase
376
419
 
377
420
  test 'should not send confirmation by email after changing to a blank email' do
378
421
  admin = create_admin
379
- assert admin.confirm!
422
+ assert admin.confirm
380
423
  assert_email_not_sent do
381
424
  admin.email = ''
382
425
  admin.save(validate: false)
@@ -385,23 +428,23 @@ class ReconfirmableTest < ActiveSupport::TestCase
385
428
 
386
429
  test 'should stay confirmed when email is changed' do
387
430
  admin = create_admin
388
- assert admin.confirm!
431
+ assert admin.confirm
389
432
  assert admin.update_attributes(email: 'new_test@example.com')
390
433
  assert admin.confirmed?
391
434
  end
392
435
 
393
436
  test 'should update email only when it is confirmed' do
394
437
  admin = create_admin
395
- assert admin.confirm!
438
+ assert admin.confirm
396
439
  assert admin.update_attributes(email: 'new_test@example.com')
397
440
  assert_not_equal 'new_test@example.com', admin.email
398
- assert admin.confirm!
441
+ assert admin.confirm
399
442
  assert_equal 'new_test@example.com', admin.email
400
443
  end
401
444
 
402
445
  test 'should not allow admin to get past confirmation email by resubmitting their new address' do
403
446
  admin = create_admin
404
- assert admin.confirm!
447
+ assert admin.confirm
405
448
  assert admin.update_attributes(email: 'new_test@example.com')
406
449
  assert_not_equal 'new_test@example.com', admin.email
407
450
  assert admin.update_attributes(email: 'new_test@example.com')
@@ -410,7 +453,7 @@ class ReconfirmableTest < ActiveSupport::TestCase
410
453
 
411
454
  test 'should find a admin by send confirmation instructions with unconfirmed_email' do
412
455
  admin = create_admin
413
- assert admin.confirm!
456
+ assert admin.confirm
414
457
  assert admin.update_attributes(email: 'new_test@example.com')
415
458
  confirmation_admin = Admin.send_confirmation_instructions(email: admin.unconfirmed_email)
416
459
  assert_equal confirmation_admin, admin
@@ -451,4 +494,18 @@ class ReconfirmableTest < ActiveSupport::TestCase
451
494
  :unconfirmed_email
452
495
  ]
453
496
  end
497
+
498
+ test 'should not require reconfirmation after creating a record' do
499
+ admin = create_admin
500
+ assert !admin.pending_reconfirmation?
501
+ end
502
+
503
+ test 'should not require reconfirmation after creating a record with #save called in callback' do
504
+ class Admin::WithSaveInCallback < Admin
505
+ after_create :save
506
+ end
507
+
508
+ admin = Admin::WithSaveInCallback.create(valid_attributes.except(:username))
509
+ assert !admin.pending_reconfirmation?
510
+ end
454
511
  end
@@ -3,6 +3,10 @@ require 'test_models'
3
3
  require 'digest/sha1'
4
4
 
5
5
  class DatabaseAuthenticatableTest < ActiveSupport::TestCase
6
+ def setup
7
+ setup_mailer
8
+ end
9
+
6
10
  test 'should downcase case insensitive keys when saving' do
7
11
  # case_insensitive_keys is set to :email by default.
8
12
  email = 'Foo@Bar.com'
@@ -225,6 +229,22 @@ class DatabaseAuthenticatableTest < ActiveSupport::TestCase
225
229
  assert_match "can't be blank", user.errors[:current_password].join
226
230
  end
227
231
 
232
+ test 'should not email on password change' do
233
+ user = create_user
234
+ assert_email_not_sent do
235
+ assert user.update_attributes(password: 'newpass', password_confirmation: 'newpass')
236
+ end
237
+ end
238
+
239
+ test 'should email on password change when configured' do
240
+ swap Devise, send_password_change_notification: true do
241
+ user = create_user
242
+ assert_email_sent user.email do
243
+ assert user.update_attributes(password: 'newpass', password_confirmation: 'newpass')
244
+ end
245
+ end
246
+ end
247
+
228
248
  test 'downcase_keys with validation' do
229
249
  User.create(email: "HEllO@example.com", password: "123456")
230
250
  user = User.create(email: "HEllO@example.com", password: "123456")