Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/reset_password.rdoc
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ reset_password_email_subject :: The subject to use for the reset password reques
reset_password_error_flash :: The flash error to show after resetting a password.
reset_password_explanatory_text :: The text to display above the button to request a password reset.
reset_password_id_column :: The id column in the +reset_password_table+, should be a foreign key referencing the accounts table.
reset_password_implicitly_verifies? :: Whether resetting a password for an unverified account implicitly verifies the account, false by default.
reset_password_key_column :: The reset password key/token column in the +reset_password_table+.
reset_password_key_param :: The parameter name to use for the reset password key.
reset_password_notice_flash :: The flash notice to show after resetting a password.
Expand Down
19 changes: 17 additions & 2 deletions lib/rodauth/features/reset_password.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ module Rodauth
auth_value_method :reset_password_deadline_interval, {:days=>1}.freeze
auth_value_method :reset_password_key_param, 'key'
auth_value_method :reset_password_autologin?, false
auth_value_method :reset_password_implicitly_verifies?, false
auth_value_method :reset_password_table, :account_password_reset_keys
auth_value_method :reset_password_id_column, :id
auth_value_method :reset_password_key_column, :key
Expand Down Expand Up @@ -174,7 +175,7 @@ def create_reset_password_key
end

def reset_password_request_for_unverified_account
throw_error_reason(:unverified_account, unopen_account_error_status, login_param, unverified_account_message)
throw_error_reason(:unverified_account, unopen_account_error_status, login_param, unverified_account_message) unless reset_password_implicitly_verifies?
end

def remove_reset_password_key
Expand Down Expand Up @@ -231,6 +232,14 @@ def after_login_failure
super
end

def after_reset_password
super if defined?(super)
if reset_password_implicitly_verifies? && !open_account?
verify_account
remove_verify_account_key
Comment on lines +238 to +239
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main issue here is you can set reset_password_implicitly_verifies? to true without loading the verify_account feature, in which case you end up with a NoMethodError here. It's possible to check that, but I think it's simpler to add a new feature that depends on both reset_password and verify_account, and has these changes (as you mentioned when submitting).

end
end

def generate_reset_password_key_value
@reset_password_key_value = random_key
end
Expand All @@ -254,7 +263,13 @@ def password_reset_ds(id=account_id)
end

def _account_from_reset_password_key(token)
account_from_key(token, account_open_status_value){|id| get_password_reset_key(id)}
account_from_key(token, reset_password_account_status_value){|id| get_password_reset_key(id)}
end

def reset_password_account_status_value
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can keep this method inside the reset_password feature (and the call inside _account_from_reset_password_key) and have it return account_open_status_value, and extend it in the reset_password_verifies_accounts feature to do [super, account_unverified_status_value].flatten.

statuses = [account_open_status_value]
statuses << account_unverified_status_value if reset_password_implicitly_verifies?
statuses
end
end
end
31 changes: 31 additions & 0 deletions spec/reset_password_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,37 @@
page.current_path.must_equal '/reset-password-request'
end

it "should support implicit verification when resetting passwords for unverified accounts" do
rodauth do
enable :login, :reset_password, :verify_account
reset_password_implicitly_verifies? true
reset_password_autologin? true
end
roda do |r|
r.rodauth
r.root{view :content=>rodauth.logged_in? ? "Logged In" : "Not Logged"}
end

DB[:accounts].update(:status_id=>1)
DB[:account_verification_keys].insert(:id=>DB[:accounts].get(:id), :key=>'test')

visit '/reset-password-request'
fill_in 'Login', :with=>'foo@example.com'
click_button 'Request Password Reset'
page.find('#notice_flash').text.must_equal "An email has been sent to you with a link to reset the password for your account"

link = email_link(/(\/reset-password\?key=.+)$/)
visit link
fill_in 'Password', :with=>'0123456'
fill_in 'Confirm Password', :with=>'0123456'
click_button 'Reset Password'
page.find('#notice_flash').text.must_equal "Your password has been reset"
page.body.must_include("Logged In")

DB[:accounts].get(:status_id).must_equal 2
DB[:account_verification_keys].count.must_equal 0
end

[true, false].each do |before|
it "should clear reset password token when closing account, when loading reset_password #{before ? "before" : "after"}" do
rodauth do
Expand Down