Метод обратного вызова перед действием перенаправляет несколько раз, заставляя пользователя менять пароль в rails

#javascript #ruby-on-rails #ruby #ruby-on-rails-6

Вопрос:

Сценарий требует, чтобы, когда пользователь входит в систему, если он не изменил пароль, он должен перенаправить на путь изменения пароля, который я попробовал следующими способами

 1)
    class ApplicationController < ActionController::Base
    before_action :check_password, if: :current_user
     def check_password 
      if current_user.present? amp;amp; 
         current_user.try(:created_at).try(:to_datetime) == 
         current_user.try(:password_changed_at).try(:to_datetime)
        redirect_to change_password_admin_user_path(current_user)
      end
     end
    end
2)    
class Admin::UsersController < ApplicationController
  skip_before_action :check_password, only: [:change_password, :update_password]
     
  def change_password
    @user = User.find(params[:id])
  end
    
  def update_password
   @user = User.find(params[:id])
   if @user.valid_password?(params[:old_password])
     if @user.update_attributes(password: params[:new_password], password_confirmation: params[:reenter_password])
      flash[:notice] = 'Password changed successfully, please login with new password'
      redirect_to new_user_session_path and return
    else
      flash[:alert] = @user.errors.full_messages.join(', ')
    end
  else
   flash[:alert] = "Old password you've entered is invalid"
  end
  redirect_to change_password_admin_user_path(@user.id)
 end
end
 
3)   
class Admin::SessionsController < Devise::SessionsController
 skip_before_action :check_password, only: :destroy
end
 

Я заставляю пользователя изменить пароль, но он выдает ошибку перенаправления несколько раз

Комментарии:

1. ты имеешь в виду DoubleRenderError ? куда указывает ошибка (класс/строка кода) ?

2. Это не ошибка. Это ожидаемое поведение, насколько я понимаю из вашей проблемы. Rails запускает before_action, видит, что ему нужно перенаправить, перенаправляет пользователя и сообщает вам в журналах, что он сделал перенаправление. Я не вижу, в чем проблема.

3. AbstractController::DoubleRenderError (Рендеринг и/или перенаправление вызывались несколько раз в этом действии. Пожалуйста, обратите внимание, что вы можете вызывать рендеринг ИЛИ перенаправление только один раз за действие. Также обратите внимание, что ни перенаправление, ни рендеринг не завершают выполнение действия, поэтому, если вы хотите завершить действие после перенаправления, вам нужно сделать что-то вроде «перенаправить на(…) и вернуться».):

4. почему у вас есть password_changed_at метод? В Devise этого нет

5.@gangothri если вы используете devise security gem, то вы можете использовать этот метод: github.com/devise-security/devise-security/blob/master/lib/…, чтобы очистить password_changed_at сразу после регистрации пользователя, чтобы devise hook github.com/devise-security/devise-security/blob/master/lib/… сделает все остальное, вам не нужно самостоятельно разбираться с этой логикой

Ответ №1:

согласно вашему комментарию, вы используете драгоценный камень devise-security, поэтому вы можете использовать метод need_change_password! (который будет очищен password_changed_at ) сразу после регистрации пользователя, так что пароль для подключения к устройству, который можно использовать, проверит и принудительно изменит пропуск нового пользователя, вам не нужно самостоятельно обрабатывать эту логику.

Комментарии:

1. current_user.need_password_changed! внутри действия check_password проблема решена

Ответ №2:

 1)
    class ApplicationController < ActionController::Base
    before_action :check_password, if: :current_user # this is why you're getting multiple redirect.
     def check_password 
      if current_user.present? amp;amp; 
         current_user.try(:created_at).try(:to_datetime) == 
         current_user.try(:password_changed_at).try(:to_datetime)
        redirect_to change_password_admin_user_path(current_user)
      end
     end
    end

 

Так что не используйте это так.

Как насчет переноса метода check_password на другой контроллер?

Экс.

 class DashboardController < ActionController::Base
  def dashboard
    if current_user.present? amp;amp; 
      current_user.try(:created_at).try(:to_datetime) == 
      current_user.try(:password_changed_at).try(:to_datetime)
      redirect_to change_password_admin_user_path(current_user)
    end
  end
end

 

Кроме того, не показывайте никакого меню, если он не сменил пароль.

Комментарии:

1. @gangothri удалил строку «before_action :check_password, if: :current_user» из ApplicationController?