mirror of
https://github.com/heartcombo/devise.git
synced 2022-11-09 12:18:31 -05:00
Creating recoverable module, reseting passwords and sending reset instructions. Some minor refactorings.
This commit is contained in:
parent
37f6a04c16
commit
7f77b4ae40
9 changed files with 155 additions and 9 deletions
|
@ -1,6 +1,7 @@
|
|||
require 'devise/authenticable'
|
||||
require 'devise/perishable_token'
|
||||
require 'devise/confirmable'
|
||||
require 'devise/recoverable'
|
||||
|
||||
require 'devise/notifier'
|
||||
|
||||
|
|
|
@ -4,6 +4,10 @@ module Devise
|
|||
def confirmation_instructions(record)
|
||||
# TODO: configure email
|
||||
end
|
||||
|
||||
def reset_password_instructions(record)
|
||||
# TODO
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -5,17 +5,21 @@ module Devise
|
|||
base.class_eval do
|
||||
# extend ClassMethods
|
||||
|
||||
before_create :generate_perishable_token
|
||||
before_create :reset_perishable_token
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
# Generates a new random token for confirmation, based on actual Time and salt
|
||||
#
|
||||
def reset_perishable_token
|
||||
self.perishable_token = secure_digest(Time.now.utc, random_string, password)
|
||||
end
|
||||
|
||||
# Generates a new random token for confirmation, based on actual Time and salt
|
||||
#
|
||||
def generate_perishable_token
|
||||
self.perishable_token = secure_digest(Time.now.utc, random_string, password)
|
||||
end
|
||||
# Resets the perishable token with and save the record without validating
|
||||
#
|
||||
def reset_perishable_token!
|
||||
reset_perishable_token and save(false)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
48
lib/devise/recoverable.rb
Normal file
48
lib/devise/recoverable.rb
Normal file
|
@ -0,0 +1,48 @@
|
|||
module Devise
|
||||
module Recoverable
|
||||
|
||||
def self.included(base)
|
||||
base.class_eval do
|
||||
extend ClassMethods
|
||||
end
|
||||
end
|
||||
|
||||
# Update password
|
||||
#
|
||||
def reset_password(new_password, new_password_confirmation)
|
||||
self.password = new_password
|
||||
self.password_confirmation = new_password_confirmation
|
||||
end
|
||||
|
||||
# Update password saving the record
|
||||
#
|
||||
def reset_password!(new_password, new_password_confirmation)
|
||||
reset_password(new_password, new_password_confirmation) and save
|
||||
end
|
||||
|
||||
# Resets perishable token and send reset password instructions by email
|
||||
#
|
||||
def send_reset_password_instructions
|
||||
reset_perishable_token!
|
||||
::Devise::Notifier.deliver_reset_password_instructions(self)
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
|
||||
# Attempt to find a user by it's email. If a record is found, send new
|
||||
# password instructions to it. If not user is found, returns a new user
|
||||
# with an email not found error.
|
||||
#
|
||||
def find_and_send_reset_password_instructions(email)
|
||||
recoverable = find_or_initialize_by_email(email)
|
||||
unless recoverable.new_record?
|
||||
recoverable.send_reset_password_instructions
|
||||
else
|
||||
recoverable.errors.add(:email, :not_found, :default => 'not found')
|
||||
end
|
||||
recoverable
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -47,6 +47,10 @@ class ConfirmableTest < ActiveSupport::TestCase
|
|||
test 'should return a new user with errors if no user exists while trying to confirm' do
|
||||
confirmed_user = User.find_and_confirm('invalid_perishable_token')
|
||||
assert confirmed_user.new_record?
|
||||
end
|
||||
|
||||
test 'should return errors for a new user when trying to confirm' do
|
||||
confirmed_user = User.find_and_confirm('invalid_perishable_token')
|
||||
assert_not_nil confirmed_user.errors[:perishable_token]
|
||||
assert_equal "invalid confirmation", confirmed_user.errors[:perishable_token]
|
||||
end
|
||||
|
@ -74,13 +78,13 @@ class ConfirmableTest < ActiveSupport::TestCase
|
|||
end
|
||||
|
||||
test 'should send confirmation instructions by email' do
|
||||
assert_difference 'ActionMailer::Base.deliveries.size' do
|
||||
assert_email_sent do
|
||||
create_user
|
||||
end
|
||||
end
|
||||
|
||||
test 'should not send confirmation when trying to save an invalid user' do
|
||||
assert_no_difference 'ActionMailer::Base.deliveries.size' do
|
||||
assert_email_not_sent do
|
||||
user = new_user
|
||||
user.stubs(:valid?).returns(false)
|
||||
user.save
|
||||
|
|
|
@ -15,6 +15,27 @@ class PerishableTokenTest < ActiveSupport::TestCase
|
|||
assert_not_nil create_user.perishable_token
|
||||
end
|
||||
|
||||
test 'should reset perisable token each time' do
|
||||
user = new_user
|
||||
3.times do
|
||||
token = user.perishable_token
|
||||
user.reset_perishable_token
|
||||
assert_not_equal token, user.perishable_token
|
||||
end
|
||||
end
|
||||
|
||||
test 'should reset perishable token and save the record' do
|
||||
user = new_user
|
||||
user.reset_perishable_token!
|
||||
assert !user.new_record?
|
||||
end
|
||||
|
||||
test 'should save without validations when reseting perisable token' do
|
||||
user = new_user
|
||||
user.expects(:valid?).never
|
||||
user.reset_perishable_token!
|
||||
end
|
||||
|
||||
test 'should never generate the same perishable token for different users' do
|
||||
perishable_tokens = []
|
||||
10.times do
|
||||
|
|
56
test/recoverable_test.rb
Normal file
56
test/recoverable_test.rb
Normal file
|
@ -0,0 +1,56 @@
|
|||
require 'test_helper'
|
||||
|
||||
class RecoverableTest < ActiveSupport::TestCase
|
||||
|
||||
def setup
|
||||
User.send :include, ::Devise::Recoverable unless User.included_modules.include?(::Devise::Recoverable)
|
||||
@user = create_user
|
||||
setup_mailer
|
||||
end
|
||||
|
||||
test 'should reset password and password confirmation from params' do
|
||||
@user.reset_password('56789', '98765')
|
||||
assert_equal '56789', @user.password
|
||||
assert_equal '98765', @user.password_confirmation
|
||||
end
|
||||
|
||||
test 'should reset password and save the record' do
|
||||
assert @user.reset_password!('56789', '56789')
|
||||
end
|
||||
|
||||
test 'should not reset password with invalid data' do
|
||||
@user.stubs(:valid?).returns(false)
|
||||
assert_not @user.reset_password!('56789', '98765')
|
||||
end
|
||||
|
||||
test 'should find a user to send instructions by email' do
|
||||
reset_password_user = User.find_and_send_reset_password_instructions(@user.email)
|
||||
assert_not_nil reset_password_user
|
||||
assert_equal reset_password_user, @user
|
||||
end
|
||||
|
||||
test 'should return a new user if no email was found' do
|
||||
reset_password_user = User.find_and_send_reset_password_instructions("invalid@email.com")
|
||||
assert_not_nil reset_password_user
|
||||
assert reset_password_user.new_record?
|
||||
end
|
||||
|
||||
test 'should add error to new user email if no email was found' do
|
||||
reset_password_user = User.find_and_send_reset_password_instructions("invalid@email.com")
|
||||
assert reset_password_user.errors[:email]
|
||||
assert_equal 'not found', reset_password_user.errors[:email]
|
||||
end
|
||||
|
||||
test 'should reset perishable token before send the reset instrunctions email' do
|
||||
token = @user.perishable_token
|
||||
reset_password_user = User.find_and_send_reset_password_instructions(@user.email)
|
||||
assert_not_equal token, @user.reload.perishable_token
|
||||
end
|
||||
|
||||
test 'should send email instructions to the user' do
|
||||
assert_email_sent do
|
||||
User.find_and_send_reset_password_instructions(@user.email)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -42,6 +42,14 @@ class ActiveSupport::TestCase
|
|||
end
|
||||
alias :assert_present :assert_not_blank
|
||||
|
||||
def assert_email_sent(&block)
|
||||
assert_difference('ActionMailer::Base.deliveries.size') { yield }
|
||||
end
|
||||
|
||||
def assert_email_not_sent(&block)
|
||||
assert_no_difference('ActionMailer::Base.deliveries.size') { yield }
|
||||
end
|
||||
|
||||
def setup_mailer
|
||||
ActionMailer::Base.deliveries = []
|
||||
end
|
||||
|
|
Loading…
Add table
Reference in a new issue