class PasswordResetsController < ApplicationController RESET_TOKEN_EXPIRY = 1.hour def new # Show request password reset form end def create @user = User.find_by(email: params[:email]&.downcase&.strip) if @user&.invitation_accepted_at.present? @user.update!( reset_password_token: SecureRandom.urlsafe_base64(32), reset_password_sent_at: Time.current ) PasswordResetMailer.reset(@user).deliver_later else @user.invite_by! InvitationMailer.invite(@user).deliver_later end redirect_to login_path, notice: "If that email address is in our system, you will receive password reset instructions." end def edit @user = User.find_by(reset_password_token: params[:token]) if @user.nil? redirect_to login_path, alert: "Invalid password reset link." elsif password_reset_expired?(@user) redirect_to new_password_reset_path, alert: "Password reset link has expired. Please request a new one." end end def update @user = User.find_by(reset_password_token: params[:token]) if @user.nil? redirect_to login_path, alert: "Invalid password reset link." return end if password_reset_expired?(@user) redirect_to new_password_reset_path, alert: "Password reset link has expired. Please request a new one." return end if params[:password].blank? flash.now[:alert] = "Password cannot be blank." render :edit, status: :unprocessable_entity return end if params[:password] != params[:password_confirmation] flash.now[:alert] = "Password confirmation doesn't match." render :edit, status: :unprocessable_entity return end @user.password = params[:password] @user.password_confirmation = params[:password_confirmation] @user.reset_password_token = nil @user.reset_password_sent_at = nil if @user.save session[:user_id] = @user.id redirect_to root_path, notice: "Your password has been reset successfully." else flash.now[:alert] = @user.errors.full_messages.join(", ") render :edit, status: :unprocessable_entity end end private def password_reset_expired?(user) user.reset_password_sent_at < RESET_TOKEN_EXPIRY.ago end end