1
0
Fork 0
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:
Carlos A. da Silva 2009-09-18 10:20:45 -03:00
parent 37f6a04c16
commit 7f77b4ae40
9 changed files with 155 additions and 9 deletions

View file

@ -1,6 +1,7 @@
require 'devise/authenticable'
require 'devise/perishable_token'
require 'devise/confirmable'
require 'devise/recoverable'
require 'devise/notifier'

View file

@ -4,6 +4,10 @@ module Devise
def confirmation_instructions(record)
# TODO: configure email
end
def reset_password_instructions(record)
# TODO
end
end
end

View file

@ -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
View 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

View file

@ -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

View file

@ -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
View 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

View file

@ -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