lib/roda/plugins/rodauth/reset_password.rb
class Roda module RodaPlugins module Rodauth ResetPassword = Feature.define(:reset_password) do depends :login route 'reset-password' notice_flash "Your password has been reset" error_flash "There was an error resetting your password" view 'reset-password', 'Reset Password' additional_form_tags after button 'Reset Password' redirect auth_value_methods( :no_matching_reset_password_key_message, :reset_password_autologin?, :reset_password_email_sent_notice_message, :reset_password_email_sent_redirect, :reset_password_email_subject, :reset_password_id_column, :reset_password_key_column, :reset_password_key_param, :reset_password_request_additional_form_tags, :reset_password_request_button, :reset_password_table ) auth_methods( :account_from_reset_password_key, :after_reset_password_request, :create_reset_password_key, :create_reset_password_email, :remove_reset_password_key, :reset_password_email_body, :reset_password_email_link, :reset_password_key_insert_hash, :reset_password_key_value, :send_reset_password_email ) get_block do |r, auth| if key = r[auth.reset_password_key_param] if auth._account_from_reset_password_key(key) auth.reset_password_view else auth.set_redirect_error_flash auth.no_matching_reset_password_key_message r.redirect auth.require_login_redirect end end end post_block do |r, auth| if login = r[auth.login_param] if auth._account_from_login(login.to_s) && auth.open_account? auth.generate_reset_password_key_value auth.transaction do auth.create_reset_password_key auth.send_reset_password_email auth.after_reset_password_request end auth.set_notice_flash auth.reset_password_email_sent_notice_message r.redirect auth.reset_password_email_sent_redirect end elsif key = r[auth.reset_password_key_param] if auth._account_from_reset_password_key(key) if r[auth.password_param] == r[auth.password_confirm_param] if auth.password_meets_requirements?(r[auth.password_param].to_s) auth.transaction do auth.set_password(r[auth.password_param]) auth.remove_reset_password_key auth.after_reset_password end if auth.reset_password_autologin? auth.update_session end auth.set_notice_flash auth.reset_password_notice_flash r.redirect(auth.reset_password_redirect) else @password_error = auth.password_does_not_meet_requirements_message end else @password_error = auth.passwords_do_not_match_message end auth.set_error_flash auth.reset_password_error_flash auth.reset_password_view end end end def after_login_failure super scope.instance_variable_set(:@login_form_header, render("reset-password-request")) end def generate_reset_password_key_value @reset_password_key_value = random_key end def create_reset_password_key ds = db[reset_password_table].where(reset_password_id_column=>account_id_value) transaction do ds.where{deadline < Sequel::CURRENT_TIMESTAMP}.delete if ds.empty? ds.insert(reset_password_key_insert_hash) end end end def reset_password_key_insert_hash {reset_password_id_column=>account_id_value, reset_password_key_column=>reset_password_key_value} end def remove_reset_password_key db[reset_password_table].where(reset_password_id_column=>account_id_value).delete end def reset_password_email_sent_notice_message "An email has been sent to you with a link to reset the password for your account" end def no_matching_reset_password_key_message "invalid password reset key" end def _account_from_reset_password_key(key) @account = account_from_reset_password_key(key) end def account_from_reset_password_key(key) id, key = key.split('_', 2) id_column = reset_password_id_column rpds = db[reset_password_table]. select(id_column). where(id_column=>id, reset_password_key_column=>key) ds = account_model.where(account_id=>rpds) ds = ds.where(account_status_id=>account_open_status_value) unless skip_status_checks? ds.first end def after_reset_password_request nil end def reset_password_request_button 'Request Password Reset' end def reset_password_request_additional_form_tags nil end def reset_password_email_sent_redirect default_redirect end def reset_password_table :account_password_reset_keys end def reset_password_id_column :id end def reset_password_key_column :key end attr_reader :reset_password_key_value def create_reset_password_email create_email(reset_password_email_subject, reset_password_email_body) end def send_reset_password_email create_reset_password_email.deliver! end def reset_password_email_body render('reset-password-email') end def reset_password_email_link "#{request.base_url}#{prefix}/#{reset_password_route}?#{reset_password_key_param}=#{account_id_value}_#{reset_password_key_value}" end def reset_password_email_subject 'Reset Password' end def reset_password_key_param 'key' end def reset_password_autologin? false end def after_close_account super db[reset_password_table].where(reset_password_id_column=>account_id_value).delete end end end end end