Перенаправить пользователя после входа в систему, только если он находится в корневом каталоге

У меня есть приложение root_path в моем приложении Rails, которое не защищено пользователем, т.е. это простая страница портала с формой входа.

После входа пользователя в систему я хотел бы перейти к dashboard_path.

Я сделал это:

def signed_in_root_path(scope_or_resource)
  dashboard_path
end

Это, по-видимому, следует использовать, когда пользователь заходит, и я не хочу, чтобы он переходил к root_path, сохраняя при этом возвращение на предыдущую страницу, если он пытается попасть в ограниченную зону, и это либо тайм-аут или не вошел в систему.

то есть:.

limited_page → login → limited_page_but_logged_in

Я не хочу изменять это поведение, и поэтому я не использовал after_sign_in_path, но хочу перенаправить его, если он находится на root_path, или любой маршрут, который не требует аутентификации пользователя.

Моя проблема в том, что это не работает. После входа в систему я перенаправляется обратно на root_path, что, по моему мнению, связано с тем, что after_sign_in_path запускается раньше.

Есть ли способ сделать это? Спасибо!

Изменить: это работает во второй раз, когда я вхожу в систему, то есть я перехожу к root_path, вхожу в систему, получает сообщение со вспышкой о том, что я вошел в систему, и снова введите имя пользователя и пароль в форме на root_path. Я успешно перенаправлен на dashboard_path. Тем не менее, не совсем то, что я хочу.

Ответ 1

Просто мысль

Вы можете определить два корневых URL-адреса для подписанного в url, который будет указывать на панель управления, а второй для не подписанных пользователей, который укажет на страницу входа

определить другой корневой URL, основанный на некоторых ограничениях в routes.rb

корневой URL для зарегистрированных пользователей

constraints(AuthenticatedUser) do 
  root :to => "dashboard"
end

корневой URL для не подписанных пользователей

root :to=>"users/signin"

затем создайте класс AuthenticatedUser в lib/authenticated_user.rb

class AuthenticatedUser
  def self.matches?(request)
    user_signed_in?
  end
end

теперь, если пользователь подписал в root_url, он укажет на панель управления, иначе он укажет на страницу с подписью

Кроме того, вы можете создать два корня, используя (еще не проверял его)

root :to => "dashboard", :constraints => {user_signed_in?}
root :to => "users/signin"

больше ограничений http://edgeguides.rubyonrails.org/routing.html#request-based-constraints

Примечание

Приоритет URL-адреса основан на порядке создания,  сначала созданные → ресурсы с наивысшим приоритетом

Ответ 2

Похоже, вы слишком усложняете проблему. Если вы переходите на переопределяющие переменные маршрутизации, это просто приводит к головным болям по линии. Я бы рекомендовал использовать фильтр before, чтобы потребовать логин и использовать параметр except или пропустить, что перед фильтром для целевой страницы, если вы используете отдельный контроллер. В качестве примера:

class ApplicationController < ActionController::Base

  before_filter :require_login, :except => :root

  def root
    # Homepage
  end

  protected

  def require_login
    redirect_to login_path and return unless logged_in?
  end

end

(Убедитесь, что вы определили logged_in?)

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

class HomepageController < ApplicationController

  skip_before_filter :require_login
  before_filter :route

  protected

  def route
    redirect_to dashboard_path and return if logged_in?
  end

end

Что касается правильной маршрутизации после входа в систему, это будет связано с тем, что вы делаете, когда создаете свою сессию. Независимо от того, эта настройка должна поймать всех, кто вошел в систему, чтобы попасть на главную страницу, и перенаправить их на свою панель управления, и любой, кто пытается попасть в ограниченный контент (Anything помимо root) и перенаправить их в login_path

Ответ 3

Вы можете переопределить метод after_sign_in_path_for, не теряя желаемого поведения.

 def after_sign_in_path_for(resource_or_scope)
   stored_location_for(resource_or_scope) || dashboard_path
 end

Я бы также поставил условие в действие root_path, которое перенаправляет, если current_user существует.

RootController.rb

def index
  if current_user
     redirect_to dashboard_path
  else
    super #or whatever
  end
end

Вы также можете использовать файл before_filter, если хотите добавить перенаправление ко многим незащищенным действиям.

Ответ 4

Я использую Omniauth, и этот метод работал хорошо для меня. Если вы работаете с другой стратегией, я уверен, что вы можете ее изменить.

После того, как они войдут в систему, просто перенаправьте их на root_path, и они перенесут их в dashboard_path или все другие настройки по умолчанию, указанные вами в файле маршрутов ниже.

Настройте методы помощника и обратного вызова в контроллере приложений:

# application_controller.rb
class ApplicationController < ActionController::Base
  protect_from_forgery
  helper_method :current_user

  private

  def current_user
    @current_user ||= User.find(session[:user_id]) if session[:user_id]
  end

  def authenticate_user!
    unless current_user
      redirect_to root_url
    end
  end
end

Поместите before_filter в ограниченном контроллере, чтобы поймать неавторизованных людей:

# dashboard_controller.rb
class DashboardController < ActionController::Base
  before_filter :authenticate_user!

  def index
  end

  # rest of controller here

end

Добавьте эти два элемента в маршрут. Первый не будет выполнен, если условие не выполнено. Если это так, то верхний имеет приоритет, и все вызовы root_url перейдут на панель управления

# routes.rb
YourAppName::Application.routes.draw do
  root :to => 'dashboard#index', :conditions => lambda{ |req| !req.session["user_id"].blank? }
  root :to => 'static_page#index'

  # the rest of your routes

end

Ответ 5

Я думаю, что вы решение сложнее, чем необходимо. Почему бы вам просто не сделать что-то простое в этом действии, чтобы форма входа была отправлена:

def login
  // logic to check whether login credentials authorize user to sign in
  // say 'user_signed_in?' is boolean to determine whether user has successfully signed in
  redirect_to(user_signed_in? ? dashboard_path : root_path)
end

Ответ 6

Форма входа находится на всех страницах (верхняя/боковая панель) или у вас есть страница входа в систему?

Если есть на всех страницах, вы можете использовать request.referrer, чтобы узнать, откуда пришел пользователь.

Ответ 7

Вы можете контролировать это с помощью параметра before_filter на вашем контроллере приложений.

Ответ 8

Я не уверен, что вы используете after_filter или before_filter где-то для своих переадресаций, но вы можете использовать skip_filter в своем контроллере входа. Затем добавьте свое настраиваемое перенаправление в качестве фильтра внутри этого контроллера.

Пропустить before_filter в Rails