2009-09-18 10:20:45 -03:00
|
|
|
module Devise
|
2009-10-09 08:30:25 -03:00
|
|
|
module Models
|
2009-10-09 09:27:44 -03:00
|
|
|
|
2013-03-21 18:49:19 -06:00
|
|
|
# Recoverable takes care of resetting the user password and send reset instructions.
|
2010-07-15 13:01:31 +02:00
|
|
|
#
|
2010-12-29 16:06:55 +08:00
|
|
|
# ==Options
|
|
|
|
#
|
|
|
|
# Recoverable adds the following options to devise_for:
|
|
|
|
#
|
|
|
|
# * +reset_password_keys+: the keys you want to use when recovering the password for an account
|
|
|
|
#
|
2010-07-15 13:01:31 +02:00
|
|
|
# == Examples
|
2009-10-09 09:27:44 -03:00
|
|
|
#
|
|
|
|
# # resets the user password and save the record, true if valid passwords are given, otherwise false
|
|
|
|
# User.find(1).reset_password!('password123', 'password123')
|
2009-11-24 13:56:54 -02:00
|
|
|
#
|
2009-10-09 09:27:44 -03:00
|
|
|
# # only resets the user password, without saving the record
|
|
|
|
# user = User.find(1)
|
|
|
|
# user.reset_password('password123', 'password123')
|
2009-11-24 13:56:54 -02:00
|
|
|
#
|
2009-10-09 09:27:44 -03:00
|
|
|
# # creates a new token and send it with instructions about how to reset the password
|
|
|
|
# User.find(1).send_reset_password_instructions
|
2010-07-15 13:01:31 +02:00
|
|
|
#
|
2009-10-09 08:30:25 -03:00
|
|
|
module Recoverable
|
2010-02-17 12:35:38 +01:00
|
|
|
extend ActiveSupport::Concern
|
2009-09-18 10:20:45 -03:00
|
|
|
|
2012-02-20 09:14:06 -02:00
|
|
|
def self.required_fields(klass)
|
|
|
|
[:reset_password_sent_at, :reset_password_token]
|
|
|
|
end
|
|
|
|
|
2009-10-15 17:36:44 -03:00
|
|
|
# Update password saving the record and clearing token. Returns true if
|
|
|
|
# the passwords are valid and the record was saved, false otherwise.
|
2009-10-09 08:30:25 -03:00
|
|
|
def reset_password!(new_password, new_password_confirmation)
|
2009-12-15 00:30:28 +01:00
|
|
|
self.password = new_password
|
|
|
|
self.password_confirmation = new_password_confirmation
|
2011-12-04 23:58:19 +01:00
|
|
|
|
2011-07-29 14:26:19 -07:00
|
|
|
if valid?
|
|
|
|
clear_reset_password_token
|
2011-08-02 12:08:38 -07:00
|
|
|
after_password_reset
|
2011-07-29 14:26:19 -07:00
|
|
|
end
|
|
|
|
|
2009-10-15 17:36:44 -03:00
|
|
|
save
|
2009-09-18 10:20:45 -03:00
|
|
|
end
|
2009-09-18 10:47:12 -03:00
|
|
|
|
2013-08-05 18:56:07 +02:00
|
|
|
# Resets reset password token and send reset password instructions by email.
|
|
|
|
# Returns the token sent in the e-mail.
|
2009-10-09 08:30:25 -03:00
|
|
|
def send_reset_password_instructions
|
2014-05-05 13:41:08 +05:30
|
|
|
token = set_reset_password_token
|
2014-05-06 01:23:55 +05:30
|
|
|
send_reset_password_instructions_notification(token)
|
2013-08-05 18:56:07 +02:00
|
|
|
|
2014-05-05 13:41:08 +05:30
|
|
|
token
|
2009-10-09 08:30:25 -03:00
|
|
|
end
|
2013-08-05 18:56:07 +02:00
|
|
|
|
2011-01-24 23:48:44 +08:00
|
|
|
# Checks if the reset password token sent is within the limit time.
|
|
|
|
# We do this by calculating if the difference between today and the
|
|
|
|
# sending date does not exceed the confirm in time configured.
|
2011-04-29 11:26:12 -07:00
|
|
|
# Returns true if the resource is not responding to reset_password_sent_at at all.
|
2011-01-24 23:48:44 +08:00
|
|
|
# reset_password_within is a model configuration, must always be an integer value.
|
|
|
|
#
|
|
|
|
# Example:
|
|
|
|
#
|
|
|
|
# # reset_password_within = 1.day and reset_password_sent_at = today
|
|
|
|
# reset_password_period_valid? # returns true
|
|
|
|
#
|
|
|
|
# # reset_password_within = 5.days and reset_password_sent_at = 4.days.ago
|
|
|
|
# reset_password_period_valid? # returns true
|
|
|
|
#
|
|
|
|
# # reset_password_within = 5.days and reset_password_sent_at = 5.days.ago
|
|
|
|
# reset_password_period_valid? # returns false
|
|
|
|
#
|
|
|
|
# # reset_password_within = 0.days
|
|
|
|
# reset_password_period_valid? # will always return false
|
|
|
|
#
|
|
|
|
def reset_password_period_valid?
|
2011-04-21 13:56:10 +02:00
|
|
|
reset_password_sent_at && reset_password_sent_at.utc >= self.class.reset_password_within.ago
|
2011-01-24 23:48:44 +08:00
|
|
|
end
|
|
|
|
|
2009-10-18 09:14:52 -02:00
|
|
|
protected
|
|
|
|
|
|
|
|
# Removes reset_password token
|
|
|
|
def clear_reset_password_token
|
|
|
|
self.reset_password_token = nil
|
2011-12-04 23:58:19 +01:00
|
|
|
self.reset_password_sent_at = nil
|
2009-10-18 09:14:52 -02:00
|
|
|
end
|
|
|
|
|
2011-08-02 12:08:38 -07:00
|
|
|
def after_password_reset
|
|
|
|
end
|
|
|
|
|
2014-05-05 13:41:08 +05:30
|
|
|
def set_reset_password_token
|
|
|
|
raw, enc = Devise.token_generator.generate(self.class, :reset_password_token)
|
|
|
|
|
|
|
|
self.reset_password_token = enc
|
2014-05-06 01:23:55 +05:30
|
|
|
self.reset_password_sent_at = Time.now.utc
|
2014-05-05 13:41:08 +05:30
|
|
|
self.save(validate: false)
|
|
|
|
raw
|
|
|
|
end
|
|
|
|
|
2014-05-06 01:23:55 +05:30
|
|
|
def send_reset_password_instructions_notification(token)
|
2014-05-05 13:41:08 +05:30
|
|
|
send_devise_notification(:reset_password_instructions, token, {})
|
|
|
|
end
|
|
|
|
|
2009-10-09 08:30:25 -03:00
|
|
|
module ClassMethods
|
2014-03-31 14:51:13 +01:00
|
|
|
# Attempt to find a user by password reset token. If a user is found, return it
|
|
|
|
# If a user is not found, return nil
|
|
|
|
def with_reset_password_token(token)
|
|
|
|
reset_password_token = Devise.token_generator.digest(self, :reset_password_token, token)
|
2014-03-31 15:24:55 +01:00
|
|
|
to_adapter.find_first(reset_password_token: reset_password_token)
|
2014-03-31 14:51:13 +01:00
|
|
|
end
|
|
|
|
|
2012-12-02 00:24:09 +05:30
|
|
|
# Attempt to find a user by its email. If a record is found, send new
|
2012-11-29 17:15:15 +05:30
|
|
|
# password instructions to it. If user is not found, returns a new user
|
2009-10-09 08:30:25 -03:00
|
|
|
# with an email not found error.
|
2012-11-29 17:15:15 +05:30
|
|
|
# Attributes must contain the user's email
|
2009-10-10 16:20:23 -03:00
|
|
|
def send_reset_password_instructions(attributes={})
|
2010-12-28 23:00:23 +01:00
|
|
|
recoverable = find_or_initialize_with_errors(reset_password_keys, attributes, :not_found)
|
2010-03-28 13:26:07 -07:00
|
|
|
recoverable.send_reset_password_instructions if recoverable.persisted?
|
2009-10-09 08:30:25 -03:00
|
|
|
recoverable
|
|
|
|
end
|
|
|
|
|
2011-08-16 22:06:13 +02:00
|
|
|
# Attempt to find a user by its reset_password_token to reset its
|
2011-01-24 23:48:44 +08:00
|
|
|
# password. If a user is found and token is still valid, reset its password and automatically
|
2009-10-18 09:14:52 -02:00
|
|
|
# try saving the record. If not user is found, returns a new user
|
2009-10-18 10:16:30 -02:00
|
|
|
# containing an error in reset_password_token attribute.
|
2009-10-18 09:14:52 -02:00
|
|
|
# Attributes must contain reset_password_token, password and confirmation
|
2010-03-10 16:13:54 +01:00
|
|
|
def reset_password_by_token(attributes={})
|
2013-08-06 11:55:13 +02:00
|
|
|
original_token = attributes[:reset_password_token]
|
2013-08-05 18:56:07 +02:00
|
|
|
reset_password_token = Devise.token_generator.digest(self, :reset_password_token, original_token)
|
|
|
|
|
|
|
|
recoverable = find_or_initialize_with_error_by(:reset_password_token, reset_password_token)
|
|
|
|
|
2011-01-24 23:48:44 +08:00
|
|
|
if recoverable.persisted?
|
|
|
|
if recoverable.reset_password_period_valid?
|
2011-11-05 16:53:27 +01:00
|
|
|
recoverable.reset_password!(attributes[:password], attributes[:password_confirmation])
|
2011-01-24 23:48:44 +08:00
|
|
|
else
|
2011-04-21 19:17:21 +02:00
|
|
|
recoverable.errors.add(:reset_password_token, :expired)
|
2011-01-24 23:48:44 +08:00
|
|
|
end
|
|
|
|
end
|
2013-08-06 11:55:13 +02:00
|
|
|
|
|
|
|
recoverable.reset_password_token = original_token
|
2009-10-09 08:30:25 -03:00
|
|
|
recoverable
|
|
|
|
end
|
2010-12-29 16:06:55 +08:00
|
|
|
|
2011-03-30 15:35:38 +02:00
|
|
|
Devise::Models.config(self, :reset_password_keys, :reset_password_within)
|
2009-09-18 10:47:12 -03:00
|
|
|
end
|
2009-09-18 10:20:45 -03:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|