devise 4.1.1 → 4.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/CHANGELOG.md +224 -4
- data/MIT-LICENSE +2 -1
- data/README.md +275 -90
- data/app/controllers/devise/confirmations_controller.rb +2 -0
- data/app/controllers/devise/omniauth_callbacks_controller.rb +7 -5
- data/app/controllers/devise/passwords_controller.rb +3 -0
- data/app/controllers/devise/registrations_controller.rb +34 -13
- data/app/controllers/devise/sessions_controller.rb +3 -1
- data/app/controllers/devise/unlocks_controller.rb +2 -0
- data/app/controllers/devise_controller.rb +5 -3
- data/app/helpers/devise_helper.rb +23 -18
- data/app/mailers/devise/mailer.rb +10 -4
- data/app/views/devise/confirmations/new.html.erb +2 -2
- data/app/views/devise/mailer/email_changed.html.erb +7 -0
- data/app/views/devise/passwords/edit.html.erb +3 -3
- data/app/views/devise/passwords/new.html.erb +2 -2
- data/app/views/devise/registrations/edit.html.erb +9 -5
- data/app/views/devise/registrations/new.html.erb +4 -4
- data/app/views/devise/sessions/new.html.erb +4 -4
- data/app/views/devise/shared/_error_messages.html.erb +15 -0
- data/app/views/devise/shared/_links.html.erb +8 -8
- data/app/views/devise/unlocks/new.html.erb +2 -2
- data/config/locales/en.yml +5 -2
- data/lib/devise.rb +39 -17
- data/lib/devise/controllers/helpers.rb +22 -9
- data/lib/devise/controllers/rememberable.rb +3 -1
- data/lib/devise/controllers/scoped_views.rb +2 -0
- data/lib/devise/controllers/sign_in_out.rb +39 -14
- data/lib/devise/controllers/store_location.rb +25 -7
- data/lib/devise/controllers/url_helpers.rb +3 -1
- data/lib/devise/delegator.rb +2 -0
- data/lib/devise/encryptor.rb +2 -0
- data/lib/devise/failure_app.rb +63 -33
- data/lib/devise/hooks/activatable.rb +2 -0
- data/lib/devise/hooks/csrf_cleaner.rb +2 -0
- data/lib/devise/hooks/forgetable.rb +2 -0
- data/lib/devise/hooks/lockable.rb +4 -2
- data/lib/devise/hooks/proxy.rb +3 -1
- data/lib/devise/hooks/rememberable.rb +2 -0
- data/lib/devise/hooks/timeoutable.rb +4 -2
- data/lib/devise/hooks/trackable.rb +2 -0
- data/lib/devise/mailers/helpers.rb +6 -3
- data/lib/devise/mapping.rb +3 -1
- data/lib/devise/models.rb +3 -1
- data/lib/devise/models/authenticatable.rb +63 -37
- data/lib/devise/models/confirmable.rb +79 -22
- data/lib/devise/models/database_authenticatable.rb +86 -17
- data/lib/devise/models/lockable.rb +17 -3
- data/lib/devise/models/omniauthable.rb +2 -0
- data/lib/devise/models/recoverable.rb +32 -20
- data/lib/devise/models/registerable.rb +4 -0
- data/lib/devise/models/rememberable.rb +5 -3
- data/lib/devise/models/timeoutable.rb +2 -0
- data/lib/devise/models/trackable.rb +15 -1
- data/lib/devise/models/validatable.rb +10 -3
- data/lib/devise/modules.rb +2 -0
- data/lib/devise/omniauth.rb +4 -5
- data/lib/devise/omniauth/config.rb +2 -0
- data/lib/devise/omniauth/url_helpers.rb +2 -51
- data/lib/devise/orm/active_record.rb +5 -1
- data/lib/devise/orm/mongoid.rb +6 -2
- data/lib/devise/parameter_filter.rb +4 -0
- data/lib/devise/parameter_sanitizer.rb +15 -56
- data/lib/devise/rails.rb +6 -6
- data/lib/devise/rails/deprecated_constant_accessor.rb +39 -0
- data/lib/devise/rails/routes.rb +9 -7
- data/lib/devise/rails/warden_compat.rb +2 -0
- data/lib/devise/secret_key_finder.rb +27 -0
- data/lib/devise/strategies/authenticatable.rb +3 -1
- data/lib/devise/strategies/base.rb +2 -0
- data/lib/devise/strategies/database_authenticatable.rb +8 -1
- data/lib/devise/strategies/rememberable.rb +2 -0
- data/lib/devise/test/controller_helpers.rb +167 -0
- data/lib/devise/test/integration_helpers.rb +63 -0
- data/lib/devise/test_helpers.rb +7 -129
- data/lib/devise/time_inflector.rb +2 -0
- data/lib/devise/token_generator.rb +2 -0
- data/lib/devise/version.rb +3 -1
- data/lib/generators/active_record/devise_generator.rb +40 -12
- data/lib/generators/active_record/templates/migration.rb +3 -1
- data/lib/generators/active_record/templates/migration_existing.rb +2 -0
- data/lib/generators/devise/controllers_generator.rb +3 -1
- data/lib/generators/devise/devise_generator.rb +5 -3
- data/lib/generators/devise/install_generator.rb +3 -5
- data/lib/generators/devise/orm_helpers.rb +9 -3
- data/lib/generators/devise/views_generator.rb +8 -9
- data/lib/generators/mongoid/devise_generator.rb +7 -5
- data/lib/generators/templates/README +9 -8
- data/lib/generators/templates/controllers/confirmations_controller.rb +2 -0
- data/lib/generators/templates/controllers/omniauth_callbacks_controller.rb +3 -1
- data/lib/generators/templates/controllers/passwords_controller.rb +2 -0
- data/lib/generators/templates/controllers/registrations_controller.rb +4 -2
- data/lib/generators/templates/controllers/sessions_controller.rb +3 -1
- data/lib/generators/templates/controllers/unlocks_controller.rb +2 -0
- data/lib/generators/templates/devise.rb +49 -6
- data/lib/generators/templates/markerb/email_changed.markerb +7 -0
- data/lib/generators/templates/markerb/password_change.markerb +2 -2
- data/lib/generators/templates/simple_form_for/confirmations/new.html.erb +5 -1
- data/lib/generators/templates/simple_form_for/passwords/edit.html.erb +10 -2
- data/lib/generators/templates/simple_form_for/passwords/new.html.erb +4 -1
- data/lib/generators/templates/simple_form_for/registrations/edit.html.erb +11 -3
- data/lib/generators/templates/simple_form_for/registrations/new.html.erb +11 -3
- data/lib/generators/templates/simple_form_for/sessions/new.html.erb +7 -2
- data/lib/generators/templates/simple_form_for/unlocks/new.html.erb +4 -1
- metadata +16 -297
- data/.gitignore +0 -10
- data/.travis.yml +0 -44
- data/.yardopts +0 -9
- data/CODE_OF_CONDUCT.md +0 -22
- data/CONTRIBUTING.md +0 -16
- data/Gemfile +0 -30
- data/Gemfile.lock +0 -182
- data/Rakefile +0 -36
- data/bin/test +0 -13
- data/devise.gemspec +0 -26
- data/devise.png +0 -0
- data/gemfiles/Gemfile.rails-4.1-stable +0 -30
- data/gemfiles/Gemfile.rails-4.1-stable.lock +0 -170
- data/gemfiles/Gemfile.rails-4.2-stable +0 -30
- data/gemfiles/Gemfile.rails-4.2-stable.lock +0 -192
- data/gemfiles/Gemfile.rails-5.0-beta +0 -37
- data/gemfiles/Gemfile.rails-5.0-beta.lock +0 -199
- data/test/controllers/custom_registrations_controller_test.rb +0 -40
- data/test/controllers/custom_strategy_test.rb +0 -64
- data/test/controllers/helper_methods_test.rb +0 -22
- data/test/controllers/helpers_test.rb +0 -316
- data/test/controllers/inherited_controller_i18n_messages_test.rb +0 -51
- data/test/controllers/internal_helpers_test.rb +0 -127
- data/test/controllers/load_hooks_controller_test.rb +0 -19
- data/test/controllers/passwords_controller_test.rb +0 -32
- data/test/controllers/sessions_controller_test.rb +0 -106
- data/test/controllers/url_helpers_test.rb +0 -65
- data/test/delegator_test.rb +0 -19
- data/test/devise_test.rb +0 -107
- data/test/failure_app_test.rb +0 -320
- data/test/generators/active_record_generator_test.rb +0 -83
- data/test/generators/controllers_generator_test.rb +0 -48
- data/test/generators/devise_generator_test.rb +0 -39
- data/test/generators/install_generator_test.rb +0 -24
- data/test/generators/mongoid_generator_test.rb +0 -23
- data/test/generators/views_generator_test.rb +0 -103
- data/test/helpers/devise_helper_test.rb +0 -49
- data/test/integration/authenticatable_test.rb +0 -698
- data/test/integration/confirmable_test.rb +0 -324
- data/test/integration/database_authenticatable_test.rb +0 -95
- data/test/integration/http_authenticatable_test.rb +0 -106
- data/test/integration/lockable_test.rb +0 -240
- data/test/integration/omniauthable_test.rb +0 -135
- data/test/integration/recoverable_test.rb +0 -347
- data/test/integration/registerable_test.rb +0 -357
- data/test/integration/rememberable_test.rb +0 -211
- data/test/integration/timeoutable_test.rb +0 -184
- data/test/integration/trackable_test.rb +0 -92
- data/test/mailers/confirmation_instructions_test.rb +0 -115
- data/test/mailers/reset_password_instructions_test.rb +0 -96
- data/test/mailers/unlock_instructions_test.rb +0 -91
- data/test/mapping_test.rb +0 -134
- data/test/models/authenticatable_test.rb +0 -23
- data/test/models/confirmable_test.rb +0 -511
- data/test/models/database_authenticatable_test.rb +0 -269
- data/test/models/lockable_test.rb +0 -350
- data/test/models/omniauthable_test.rb +0 -7
- data/test/models/recoverable_test.rb +0 -251
- data/test/models/registerable_test.rb +0 -7
- data/test/models/rememberable_test.rb +0 -169
- data/test/models/serializable_test.rb +0 -49
- data/test/models/timeoutable_test.rb +0 -51
- data/test/models/trackable_test.rb +0 -41
- data/test/models/validatable_test.rb +0 -119
- data/test/models_test.rb +0 -153
- data/test/omniauth/config_test.rb +0 -57
- data/test/omniauth/url_helpers_test.rb +0 -51
- data/test/orm/active_record.rb +0 -17
- data/test/orm/mongoid.rb +0 -13
- data/test/parameter_sanitizer_test.rb +0 -131
- data/test/rails_app/Rakefile +0 -6
- data/test/rails_app/app/active_record/admin.rb +0 -6
- data/test/rails_app/app/active_record/shim.rb +0 -2
- data/test/rails_app/app/active_record/user.rb +0 -7
- data/test/rails_app/app/active_record/user_on_engine.rb +0 -7
- data/test/rails_app/app/active_record/user_on_main_app.rb +0 -7
- data/test/rails_app/app/active_record/user_without_email.rb +0 -8
- data/test/rails_app/app/controllers/admins/sessions_controller.rb +0 -6
- data/test/rails_app/app/controllers/admins_controller.rb +0 -6
- data/test/rails_app/app/controllers/application_controller.rb +0 -11
- data/test/rails_app/app/controllers/application_with_fake_engine.rb +0 -30
- data/test/rails_app/app/controllers/custom/registrations_controller.rb +0 -31
- data/test/rails_app/app/controllers/home_controller.rb +0 -29
- data/test/rails_app/app/controllers/publisher/registrations_controller.rb +0 -2
- data/test/rails_app/app/controllers/publisher/sessions_controller.rb +0 -2
- data/test/rails_app/app/controllers/users/omniauth_callbacks_controller.rb +0 -14
- data/test/rails_app/app/controllers/users_controller.rb +0 -31
- data/test/rails_app/app/helpers/application_helper.rb +0 -3
- data/test/rails_app/app/mailers/users/from_proc_mailer.rb +0 -3
- data/test/rails_app/app/mailers/users/mailer.rb +0 -3
- data/test/rails_app/app/mailers/users/reply_to_mailer.rb +0 -4
- data/test/rails_app/app/mongoid/admin.rb +0 -29
- data/test/rails_app/app/mongoid/shim.rb +0 -23
- data/test/rails_app/app/mongoid/user.rb +0 -39
- data/test/rails_app/app/mongoid/user_on_engine.rb +0 -39
- data/test/rails_app/app/mongoid/user_on_main_app.rb +0 -39
- data/test/rails_app/app/mongoid/user_without_email.rb +0 -33
- data/test/rails_app/app/views/admins/index.html.erb +0 -1
- data/test/rails_app/app/views/admins/sessions/new.html.erb +0 -2
- data/test/rails_app/app/views/home/admin_dashboard.html.erb +0 -1
- data/test/rails_app/app/views/home/index.html.erb +0 -1
- data/test/rails_app/app/views/home/join.html.erb +0 -1
- data/test/rails_app/app/views/home/private.html.erb +0 -1
- data/test/rails_app/app/views/home/user_dashboard.html.erb +0 -1
- data/test/rails_app/app/views/layouts/application.html.erb +0 -24
- data/test/rails_app/app/views/users/edit_form.html.erb +0 -1
- data/test/rails_app/app/views/users/index.html.erb +0 -1
- data/test/rails_app/app/views/users/mailer/confirmation_instructions.erb +0 -1
- data/test/rails_app/app/views/users/sessions/new.html.erb +0 -1
- data/test/rails_app/bin/bundle +0 -3
- data/test/rails_app/bin/rails +0 -4
- data/test/rails_app/bin/rake +0 -4
- data/test/rails_app/config.ru +0 -4
- data/test/rails_app/config/application.rb +0 -44
- data/test/rails_app/config/boot.rb +0 -14
- data/test/rails_app/config/database.yml +0 -18
- data/test/rails_app/config/environment.rb +0 -5
- data/test/rails_app/config/environments/development.rb +0 -30
- data/test/rails_app/config/environments/production.rb +0 -84
- data/test/rails_app/config/environments/test.rb +0 -46
- data/test/rails_app/config/initializers/backtrace_silencers.rb +0 -7
- data/test/rails_app/config/initializers/devise.rb +0 -180
- data/test/rails_app/config/initializers/inflections.rb +0 -2
- data/test/rails_app/config/initializers/secret_token.rb +0 -3
- data/test/rails_app/config/initializers/session_store.rb +0 -1
- data/test/rails_app/config/routes.rb +0 -126
- data/test/rails_app/db/migrate/20100401102949_create_tables.rb +0 -71
- data/test/rails_app/db/schema.rb +0 -55
- data/test/rails_app/lib/shared_admin.rb +0 -17
- data/test/rails_app/lib/shared_user.rb +0 -30
- data/test/rails_app/lib/shared_user_without_email.rb +0 -26
- data/test/rails_app/lib/shared_user_without_omniauth.rb +0 -13
- data/test/rails_app/public/404.html +0 -26
- data/test/rails_app/public/422.html +0 -26
- data/test/rails_app/public/500.html +0 -26
- data/test/rails_app/public/favicon.ico +0 -0
- data/test/rails_test.rb +0 -9
- data/test/routes_test.rb +0 -279
- data/test/support/action_controller/record_identifier.rb +0 -10
- data/test/support/assertions.rb +0 -39
- data/test/support/helpers.rb +0 -77
- data/test/support/http_method_compatibility.rb +0 -51
- data/test/support/integration.rb +0 -92
- data/test/support/locale/en.yml +0 -8
- data/test/support/mongoid.yml +0 -6
- data/test/support/webrat/integrations/rails.rb +0 -33
- data/test/test_helper.rb +0 -34
- data/test/test_helpers_test.rb +0 -178
- data/test/test_models.rb +0 -33
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Devise
|
|
2
4
|
module Models
|
|
3
5
|
# Confirmable is responsible to verify if an account is already confirmed to
|
|
@@ -26,7 +28,9 @@ module Devise
|
|
|
26
28
|
# initial account confirmation) to be applied. Requires additional unconfirmed_email
|
|
27
29
|
# db field to be set up (t.reconfirmable in migrations). Until confirmed, new email is
|
|
28
30
|
# stored in unconfirmed email column, and copied to email column on successful
|
|
29
|
-
# confirmation.
|
|
31
|
+
# confirmation. Also, when used in conjunction with `send_email_changed_notification`,
|
|
32
|
+
# the notification is sent to the original email when the change is requested,
|
|
33
|
+
# not when the unconfirmed email is confirmed.
|
|
30
34
|
# * +confirm_within+: the time before a sent confirmation token becomes invalid.
|
|
31
35
|
# You can use this to force the user to confirm within a set period of time.
|
|
32
36
|
# Confirmable will not generate a new token if a repeat confirmation is requested
|
|
@@ -43,8 +47,8 @@ module Devise
|
|
|
43
47
|
|
|
44
48
|
included do
|
|
45
49
|
before_create :generate_confirmation_token, if: :confirmation_required?
|
|
46
|
-
after_create :
|
|
47
|
-
if
|
|
50
|
+
after_create :skip_reconfirmation_in_callback!, if: :send_confirmation_notification?
|
|
51
|
+
if defined?(ActiveRecord) && self < ActiveRecord::Base # ActiveRecord
|
|
48
52
|
after_commit :send_on_create_confirmation_instructions, on: :create, if: :send_confirmation_notification?
|
|
49
53
|
after_commit :send_reconfirmation_instructions, on: :update, if: :reconfirmation_required?
|
|
50
54
|
else # Mongoid
|
|
@@ -56,6 +60,7 @@ module Devise
|
|
|
56
60
|
|
|
57
61
|
def initialize(*args, &block)
|
|
58
62
|
@bypass_confirmation_postpone = false
|
|
63
|
+
@skip_reconfirmation_in_callback = false
|
|
59
64
|
@reconfirmation_required = false
|
|
60
65
|
@skip_confirmation_notification = false
|
|
61
66
|
@raw_confirmation_token = nil
|
|
@@ -71,7 +76,7 @@ module Devise
|
|
|
71
76
|
# Confirm a user by setting it's confirmed_at to actual time. If the user
|
|
72
77
|
# is already confirmed, add an error to email field. If the user is invalid
|
|
73
78
|
# add errors
|
|
74
|
-
def confirm(args={})
|
|
79
|
+
def confirm(args = {})
|
|
75
80
|
pending_any_confirmation do
|
|
76
81
|
if confirmation_period_expired?
|
|
77
82
|
self.errors.add(:email, :confirmation_period_expired,
|
|
@@ -97,11 +102,6 @@ module Devise
|
|
|
97
102
|
end
|
|
98
103
|
end
|
|
99
104
|
|
|
100
|
-
def confirm!(args={})
|
|
101
|
-
ActiveSupport::Deprecation.warn "confirm! is deprecated in favor of confirm"
|
|
102
|
-
confirm(args)
|
|
103
|
-
end
|
|
104
|
-
|
|
105
105
|
# Verifies whether a user is confirmed or not
|
|
106
106
|
def confirmed?
|
|
107
107
|
!!confirmed_at
|
|
@@ -170,6 +170,12 @@ module Devise
|
|
|
170
170
|
|
|
171
171
|
protected
|
|
172
172
|
|
|
173
|
+
# To not require reconfirmation after creating with #save called in a
|
|
174
|
+
# callback call skip_create_confirmation!
|
|
175
|
+
def skip_reconfirmation_in_callback!
|
|
176
|
+
@skip_reconfirmation_in_callback = true
|
|
177
|
+
end
|
|
178
|
+
|
|
173
179
|
# A callback method used to deliver confirmation
|
|
174
180
|
# instructions on creation. This can be overridden
|
|
175
181
|
# in models to map to a nice sign up e-mail.
|
|
@@ -205,7 +211,10 @@ module Devise
|
|
|
205
211
|
# confirmation_period_valid? # will always return true
|
|
206
212
|
#
|
|
207
213
|
def confirmation_period_valid?
|
|
208
|
-
|
|
214
|
+
return true if self.class.allow_unconfirmed_access_for.nil?
|
|
215
|
+
return false if self.class.allow_unconfirmed_access_for == 0.days
|
|
216
|
+
|
|
217
|
+
confirmation_sent_at && confirmation_sent_at.utc >= self.class.allow_unconfirmed_access_for.ago
|
|
209
218
|
end
|
|
210
219
|
|
|
211
220
|
# Checks if the user confirmation happens before the token becomes invalid
|
|
@@ -221,7 +230,7 @@ module Devise
|
|
|
221
230
|
# confirmation_period_expired? # will always return false
|
|
222
231
|
#
|
|
223
232
|
def confirmation_period_expired?
|
|
224
|
-
self.class.confirm_within && self.confirmation_sent_at && (Time.now > self.confirmation_sent_at + self.class.confirm_within)
|
|
233
|
+
self.class.confirm_within && self.confirmation_sent_at && (Time.now.utc > self.confirmation_sent_at.utc + self.class.confirm_within)
|
|
225
234
|
end
|
|
226
235
|
|
|
227
236
|
# Checks whether the record requires any confirmation.
|
|
@@ -249,18 +258,44 @@ module Devise
|
|
|
249
258
|
generate_confirmation_token && save(validate: false)
|
|
250
259
|
end
|
|
251
260
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
261
|
+
if Devise.activerecord51?
|
|
262
|
+
def postpone_email_change_until_confirmation_and_regenerate_confirmation_token
|
|
263
|
+
@reconfirmation_required = true
|
|
264
|
+
self.unconfirmed_email = self.email
|
|
265
|
+
self.email = self.email_in_database
|
|
266
|
+
self.confirmation_token = nil
|
|
267
|
+
generate_confirmation_token
|
|
268
|
+
end
|
|
269
|
+
else
|
|
270
|
+
def postpone_email_change_until_confirmation_and_regenerate_confirmation_token
|
|
271
|
+
@reconfirmation_required = true
|
|
272
|
+
self.unconfirmed_email = self.email
|
|
273
|
+
self.email = self.email_was
|
|
274
|
+
self.confirmation_token = nil
|
|
275
|
+
generate_confirmation_token
|
|
276
|
+
end
|
|
258
277
|
end
|
|
259
278
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
279
|
+
if Devise.activerecord51?
|
|
280
|
+
def postpone_email_change?
|
|
281
|
+
postpone = self.class.reconfirmable &&
|
|
282
|
+
will_save_change_to_email? &&
|
|
283
|
+
!@bypass_confirmation_postpone &&
|
|
284
|
+
self.email.present? &&
|
|
285
|
+
(!@skip_reconfirmation_in_callback || !self.email_in_database.nil?)
|
|
286
|
+
@bypass_confirmation_postpone = false
|
|
287
|
+
postpone
|
|
288
|
+
end
|
|
289
|
+
else
|
|
290
|
+
def postpone_email_change?
|
|
291
|
+
postpone = self.class.reconfirmable &&
|
|
292
|
+
email_changed? &&
|
|
293
|
+
!@bypass_confirmation_postpone &&
|
|
294
|
+
self.email.present? &&
|
|
295
|
+
(!@skip_reconfirmation_in_callback || !self.email_was.nil?)
|
|
296
|
+
@bypass_confirmation_postpone = false
|
|
297
|
+
postpone
|
|
298
|
+
end
|
|
264
299
|
end
|
|
265
300
|
|
|
266
301
|
def reconfirmation_required?
|
|
@@ -271,6 +306,16 @@ module Devise
|
|
|
271
306
|
confirmation_required? && !@skip_confirmation_notification && self.email.present?
|
|
272
307
|
end
|
|
273
308
|
|
|
309
|
+
# With reconfirmable, notify the original email when the user first
|
|
310
|
+
# requests the email change, instead of when the change is confirmed.
|
|
311
|
+
def send_email_changed_notification?
|
|
312
|
+
if self.class.reconfirmable
|
|
313
|
+
self.class.send_email_changed_notification && reconfirmation_required?
|
|
314
|
+
else
|
|
315
|
+
super
|
|
316
|
+
end
|
|
317
|
+
end
|
|
318
|
+
|
|
274
319
|
# A callback initiated after successfully confirming. This can be
|
|
275
320
|
# used to insert your own logic that is only run after the user successfully
|
|
276
321
|
# confirms.
|
|
@@ -289,7 +334,7 @@ module Devise
|
|
|
289
334
|
# confirmation instructions to it. If not, try searching for a user by unconfirmed_email
|
|
290
335
|
# field. If no user is found, returns a new user with an email not found error.
|
|
291
336
|
# Options must contain the user email
|
|
292
|
-
def send_confirmation_instructions(attributes={})
|
|
337
|
+
def send_confirmation_instructions(attributes = {})
|
|
293
338
|
confirmable = find_by_unconfirmed_email_with_errors(attributes) if reconfirmable
|
|
294
339
|
unless confirmable.try(:persisted?)
|
|
295
340
|
confirmable = find_or_initialize_with_errors(confirmation_keys, attributes, :not_found)
|
|
@@ -303,7 +348,19 @@ module Devise
|
|
|
303
348
|
# If the user is already confirmed, create an error for the user
|
|
304
349
|
# Options must have the confirmation_token
|
|
305
350
|
def confirm_by_token(confirmation_token)
|
|
351
|
+
# When the `confirmation_token` parameter is blank, if there are any users with a blank
|
|
352
|
+
# `confirmation_token` in the database, the first one would be confirmed here.
|
|
353
|
+
# The error is being manually added here to ensure no users are confirmed by mistake.
|
|
354
|
+
# This was done in the model for convenience, since validation errors are automatically
|
|
355
|
+
# displayed in the view.
|
|
356
|
+
if confirmation_token.blank?
|
|
357
|
+
confirmable = new
|
|
358
|
+
confirmable.errors.add(:confirmation_token, :blank)
|
|
359
|
+
return confirmable
|
|
360
|
+
end
|
|
361
|
+
|
|
306
362
|
confirmable = find_first_by_auth_conditions(confirmation_token: confirmation_token)
|
|
363
|
+
|
|
307
364
|
unless confirmable
|
|
308
365
|
confirmation_digest = Devise.token_generator.digest(self, :confirmation_token, confirmation_token)
|
|
309
366
|
confirmable = find_or_initialize_with_error_by(:confirmation_token, confirmation_digest)
|
|
@@ -1,24 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'devise/strategies/database_authenticatable'
|
|
2
4
|
|
|
3
5
|
module Devise
|
|
4
|
-
def self.bcrypt(klass, password)
|
|
5
|
-
ActiveSupport::Deprecation.warn "Devise.bcrypt is deprecated; use Devise::Encryptor.digest instead"
|
|
6
|
-
Devise::Encryptor.digest(klass, password)
|
|
7
|
-
end
|
|
8
|
-
|
|
9
6
|
module Models
|
|
10
7
|
# Authenticatable Module, responsible for hashing the password and
|
|
11
8
|
# validating the authenticity of a user while signing in.
|
|
12
9
|
#
|
|
10
|
+
# This module defines a `password=` method. This method will hash the argument
|
|
11
|
+
# and store it in the `encrypted_password` column, bypassing any pre-existing
|
|
12
|
+
# `password` column if it exists.
|
|
13
|
+
#
|
|
13
14
|
# == Options
|
|
14
15
|
#
|
|
15
16
|
# DatabaseAuthenticatable adds the following options to devise_for:
|
|
16
17
|
#
|
|
17
18
|
# * +pepper+: a random string used to provide a more secure hash. Use
|
|
18
|
-
# `
|
|
19
|
+
# `rails secret` to generate new keys.
|
|
19
20
|
#
|
|
20
21
|
# * +stretches+: the cost given to bcrypt.
|
|
21
22
|
#
|
|
23
|
+
# * +send_email_changed_notification+: notify original email when it changes.
|
|
24
|
+
#
|
|
25
|
+
# * +send_password_change_notification+: notify email when password changes.
|
|
26
|
+
#
|
|
22
27
|
# == Examples
|
|
23
28
|
#
|
|
24
29
|
# User.find(1).valid_password?('password123') # returns true/false
|
|
@@ -27,12 +32,29 @@ module Devise
|
|
|
27
32
|
extend ActiveSupport::Concern
|
|
28
33
|
|
|
29
34
|
included do
|
|
35
|
+
after_update :send_email_changed_notification, if: :send_email_changed_notification?
|
|
30
36
|
after_update :send_password_change_notification, if: :send_password_change_notification?
|
|
31
37
|
|
|
32
38
|
attr_reader :password, :current_password
|
|
33
39
|
attr_accessor :password_confirmation
|
|
34
40
|
end
|
|
35
41
|
|
|
42
|
+
def initialize(*args, &block)
|
|
43
|
+
@skip_email_changed_notification = false
|
|
44
|
+
@skip_password_change_notification = false
|
|
45
|
+
super
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Skips sending the email changed notification after_update
|
|
49
|
+
def skip_email_changed_notification!
|
|
50
|
+
@skip_email_changed_notification = true
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Skips sending the password change notification after_update
|
|
54
|
+
def skip_password_change_notification!
|
|
55
|
+
@skip_password_change_notification = true
|
|
56
|
+
end
|
|
57
|
+
|
|
36
58
|
def self.required_fields(klass)
|
|
37
59
|
[:encrypted_password] + klass.authentication_keys
|
|
38
60
|
end
|
|
@@ -63,6 +85,15 @@ module Devise
|
|
|
63
85
|
# their password). In case the password field is rejected, the confirmation
|
|
64
86
|
# is also rejected as long as it is also blank.
|
|
65
87
|
def update_with_password(params, *options)
|
|
88
|
+
if options.present?
|
|
89
|
+
ActiveSupport::Deprecation.warn <<-DEPRECATION.strip_heredoc
|
|
90
|
+
[Devise] The second argument of `DatabaseAuthenticatable#update_with_password`
|
|
91
|
+
(`options`) is deprecated and it will be removed in the next major version.
|
|
92
|
+
It was added to support a feature deprecated in Rails 4, so you can safely remove it
|
|
93
|
+
from your code.
|
|
94
|
+
DEPRECATION
|
|
95
|
+
end
|
|
96
|
+
|
|
66
97
|
current_password = params.delete(:current_password)
|
|
67
98
|
|
|
68
99
|
if params[:password].blank?
|
|
@@ -71,11 +102,11 @@ module Devise
|
|
|
71
102
|
end
|
|
72
103
|
|
|
73
104
|
result = if valid_password?(current_password)
|
|
74
|
-
|
|
105
|
+
update(params, *options)
|
|
75
106
|
else
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
107
|
+
assign_attributes(params, *options)
|
|
108
|
+
valid?
|
|
109
|
+
errors.add(:current_password, current_password.blank? ? :blank : :invalid)
|
|
79
110
|
false
|
|
80
111
|
end
|
|
81
112
|
|
|
@@ -96,10 +127,19 @@ module Devise
|
|
|
96
127
|
# end
|
|
97
128
|
#
|
|
98
129
|
def update_without_password(params, *options)
|
|
130
|
+
if options.present?
|
|
131
|
+
ActiveSupport::Deprecation.warn <<-DEPRECATION.strip_heredoc
|
|
132
|
+
[Devise] The second argument of `DatabaseAuthenticatable#update_without_password`
|
|
133
|
+
(`options`) is deprecated and it will be removed in the next major version.
|
|
134
|
+
It was added to support a feature deprecated in Rails 4, so you can safely remove it
|
|
135
|
+
from your code.
|
|
136
|
+
DEPRECATION
|
|
137
|
+
end
|
|
138
|
+
|
|
99
139
|
params.delete(:password)
|
|
100
140
|
params.delete(:password_confirmation)
|
|
101
141
|
|
|
102
|
-
result =
|
|
142
|
+
result = update(params, *options)
|
|
103
143
|
clean_up_passwords
|
|
104
144
|
result
|
|
105
145
|
end
|
|
@@ -111,8 +151,8 @@ module Devise
|
|
|
111
151
|
result = if valid_password?(current_password)
|
|
112
152
|
destroy
|
|
113
153
|
else
|
|
114
|
-
|
|
115
|
-
|
|
154
|
+
valid?
|
|
155
|
+
errors.add(:current_password, current_password.blank? ? :blank : :invalid)
|
|
116
156
|
false
|
|
117
157
|
end
|
|
118
158
|
|
|
@@ -137,6 +177,19 @@ module Devise
|
|
|
137
177
|
encrypted_password[0,29] if encrypted_password
|
|
138
178
|
end
|
|
139
179
|
|
|
180
|
+
if Devise.activerecord51?
|
|
181
|
+
# Send notification to user when email changes.
|
|
182
|
+
def send_email_changed_notification
|
|
183
|
+
send_devise_notification(:email_changed, to: email_before_last_save)
|
|
184
|
+
end
|
|
185
|
+
else
|
|
186
|
+
# Send notification to user when email changes.
|
|
187
|
+
def send_email_changed_notification
|
|
188
|
+
send_devise_notification(:email_changed, to: email_was)
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
# Send notification to user when password changes.
|
|
140
193
|
def send_password_change_notification
|
|
141
194
|
send_devise_notification(:password_change)
|
|
142
195
|
end
|
|
@@ -146,18 +199,34 @@ module Devise
|
|
|
146
199
|
# Hashes the password using bcrypt. Custom hash functions should override
|
|
147
200
|
# this method to apply their own algorithm.
|
|
148
201
|
#
|
|
149
|
-
# See https://github.com/
|
|
202
|
+
# See https://github.com/heartcombo/devise-encryptable for examples
|
|
150
203
|
# of other hashing engines.
|
|
151
204
|
def password_digest(password)
|
|
152
205
|
Devise::Encryptor.digest(self.class, password)
|
|
153
206
|
end
|
|
154
207
|
|
|
155
|
-
|
|
156
|
-
|
|
208
|
+
if Devise.activerecord51?
|
|
209
|
+
def send_email_changed_notification?
|
|
210
|
+
self.class.send_email_changed_notification && saved_change_to_email? && !@skip_email_changed_notification
|
|
211
|
+
end
|
|
212
|
+
else
|
|
213
|
+
def send_email_changed_notification?
|
|
214
|
+
self.class.send_email_changed_notification && email_changed? && !@skip_email_changed_notification
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
if Devise.activerecord51?
|
|
219
|
+
def send_password_change_notification?
|
|
220
|
+
self.class.send_password_change_notification && saved_change_to_encrypted_password? && !@skip_password_change_notification
|
|
221
|
+
end
|
|
222
|
+
else
|
|
223
|
+
def send_password_change_notification?
|
|
224
|
+
self.class.send_password_change_notification && encrypted_password_changed? && !@skip_password_change_notification
|
|
225
|
+
end
|
|
157
226
|
end
|
|
158
227
|
|
|
159
228
|
module ClassMethods
|
|
160
|
-
Devise::Models.config(self, :pepper, :stretches, :send_password_change_notification)
|
|
229
|
+
Devise::Models.config(self, :pepper, :stretches, :send_email_changed_notification, :send_password_change_notification)
|
|
161
230
|
|
|
162
231
|
# We assume this method already gets the sanitized values from the
|
|
163
232
|
# DatabaseAuthenticatable strategy. If you are using this method on
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require "devise/hooks/lockable"
|
|
2
4
|
|
|
3
5
|
module Devise
|
|
@@ -55,6 +57,14 @@ module Devise
|
|
|
55
57
|
save(validate: false)
|
|
56
58
|
end
|
|
57
59
|
|
|
60
|
+
# Resets failed attempts counter to 0.
|
|
61
|
+
def reset_failed_attempts!
|
|
62
|
+
if respond_to?(:failed_attempts) && !failed_attempts.to_i.zero?
|
|
63
|
+
self.failed_attempts = 0
|
|
64
|
+
save(validate: false)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
58
68
|
# Verifies whether a user is locked or not.
|
|
59
69
|
def access_locked?
|
|
60
70
|
!!locked_at && !lock_expired?
|
|
@@ -99,8 +109,7 @@ module Devise
|
|
|
99
109
|
if super && !access_locked?
|
|
100
110
|
true
|
|
101
111
|
else
|
|
102
|
-
|
|
103
|
-
self.failed_attempts += 1
|
|
112
|
+
increment_failed_attempts
|
|
104
113
|
if attempts_exceeded?
|
|
105
114
|
lock_access! unless access_locked?
|
|
106
115
|
else
|
|
@@ -110,6 +119,11 @@ module Devise
|
|
|
110
119
|
end
|
|
111
120
|
end
|
|
112
121
|
|
|
122
|
+
def increment_failed_attempts
|
|
123
|
+
self.class.increment_counter(:failed_attempts, id)
|
|
124
|
+
reload
|
|
125
|
+
end
|
|
126
|
+
|
|
113
127
|
def unauthenticated_message
|
|
114
128
|
# If set to paranoid mode, do not show the locked message because it
|
|
115
129
|
# leaks the existence of an account.
|
|
@@ -162,7 +176,7 @@ module Devise
|
|
|
162
176
|
# unlock instructions to it. If not user is found, returns a new user
|
|
163
177
|
# with an email not found error.
|
|
164
178
|
# Options must contain the user's unlock keys
|
|
165
|
-
def send_unlock_instructions(attributes={})
|
|
179
|
+
def send_unlock_instructions(attributes = {})
|
|
166
180
|
lockable = find_or_initialize_with_errors(unlock_keys, attributes, :not_found)
|
|
167
181
|
lockable.resend_unlock_instructions if lockable.persisted?
|
|
168
182
|
lockable
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Devise
|
|
2
4
|
module Models
|
|
3
5
|
|
|
@@ -27,30 +29,20 @@ module Devise
|
|
|
27
29
|
end
|
|
28
30
|
|
|
29
31
|
included do
|
|
30
|
-
before_update
|
|
31
|
-
if (respond_to?(:email_changed?) && email_changed?) || encrypted_password_changed?
|
|
32
|
-
clear_reset_password_token
|
|
33
|
-
end
|
|
34
|
-
end
|
|
32
|
+
before_update :clear_reset_password_token, if: :clear_reset_password_token?
|
|
35
33
|
end
|
|
36
34
|
|
|
37
35
|
# Update password saving the record and clearing token. Returns true if
|
|
38
36
|
# the passwords are valid and the record was saved, false otherwise.
|
|
39
37
|
def reset_password(new_password, new_password_confirmation)
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
38
|
+
if new_password.present?
|
|
39
|
+
self.password = new_password
|
|
40
|
+
self.password_confirmation = new_password_confirmation
|
|
41
|
+
save
|
|
42
|
+
else
|
|
43
|
+
errors.add(:password, :blank)
|
|
44
|
+
false
|
|
46
45
|
end
|
|
47
|
-
|
|
48
|
-
save
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
def reset_password!(new_password, new_password_confirmation)
|
|
52
|
-
ActiveSupport::Deprecation.warn "reset_password! is deprecated in favor of reset_password"
|
|
53
|
-
reset_password(new_password, new_password_confirmation)
|
|
54
46
|
end
|
|
55
47
|
|
|
56
48
|
# Resets reset password token and send reset password instructions by email.
|
|
@@ -107,6 +99,26 @@ module Devise
|
|
|
107
99
|
send_devise_notification(:reset_password_instructions, token, {})
|
|
108
100
|
end
|
|
109
101
|
|
|
102
|
+
if Devise.activerecord51?
|
|
103
|
+
def clear_reset_password_token?
|
|
104
|
+
encrypted_password_changed = respond_to?(:will_save_change_to_encrypted_password?) && will_save_change_to_encrypted_password?
|
|
105
|
+
authentication_keys_changed = self.class.authentication_keys.any? do |attribute|
|
|
106
|
+
respond_to?("will_save_change_to_#{attribute}?") && send("will_save_change_to_#{attribute}?")
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
authentication_keys_changed || encrypted_password_changed
|
|
110
|
+
end
|
|
111
|
+
else
|
|
112
|
+
def clear_reset_password_token?
|
|
113
|
+
encrypted_password_changed = respond_to?(:encrypted_password_changed?) && encrypted_password_changed?
|
|
114
|
+
authentication_keys_changed = self.class.authentication_keys.any? do |attribute|
|
|
115
|
+
respond_to?("#{attribute}_changed?") && send("#{attribute}_changed?")
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
authentication_keys_changed || encrypted_password_changed
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
110
122
|
module ClassMethods
|
|
111
123
|
# Attempt to find a user by password reset token. If a user is found, return it
|
|
112
124
|
# If a user is not found, return nil
|
|
@@ -119,7 +131,7 @@ module Devise
|
|
|
119
131
|
# password instructions to it. If user is not found, returns a new user
|
|
120
132
|
# with an email not found error.
|
|
121
133
|
# Attributes must contain the user's email
|
|
122
|
-
def send_reset_password_instructions(attributes={})
|
|
134
|
+
def send_reset_password_instructions(attributes = {})
|
|
123
135
|
recoverable = find_or_initialize_with_errors(reset_password_keys, attributes, :not_found)
|
|
124
136
|
recoverable.send_reset_password_instructions if recoverable.persisted?
|
|
125
137
|
recoverable
|
|
@@ -130,7 +142,7 @@ module Devise
|
|
|
130
142
|
# try saving the record. If not user is found, returns a new user
|
|
131
143
|
# containing an error in reset_password_token attribute.
|
|
132
144
|
# Attributes must contain reset_password_token, password and confirmation
|
|
133
|
-
def reset_password_by_token(attributes={})
|
|
145
|
+
def reset_password_by_token(attributes = {})
|
|
134
146
|
original_token = attributes[:reset_password_token]
|
|
135
147
|
reset_password_token = Devise.token_generator.digest(self, :reset_password_token, original_token)
|
|
136
148
|
|