Подтвердить что ты не робот

Как я могу перенаправить исходный (домашний) путь пользователя на основе их роли с помощью Devise?

Я работаю над приложением для управления проектами, и в приложении у меня project_managers и клиенты. Я использую Devise и CanCan для аутентификации/авторизации.

В какой момент после входа я должен перенаправить пользователя на свой собственный контроллер/макет/представления? Есть ли способ проверить current_user.role в routes.rb и установить корень (или перенаправить) в зависимости от того, являются ли они менеджером проекта или клиентом? Это изменение, которое я могу внести в Devise где-нибудь?

Заранее благодарим за помощь! --Mark

4b9b3361

Ответ 1

Ваш файл routes.rb не будет знать, какую роль у пользователя есть, поэтому вы не сможете использовать его для назначения определенных корневых маршрутов.

Что вы можете сделать, так это настроить контроллер (например, passthrough_controller.rb), который, в свою очередь, может прочитать роль и перенаправить. Что-то вроде этого:

# passthrough_controller.rb
class PassthroughController < ApplicationController
  def index
    path = case current_user.role
      when 'project_manager'
        some_path
      when 'client'
        some_other_path
      else
        # If you want to raise an exception or have a default root for users without roles
    end

    redirect_to path     
  end
end

# routes.rb
root :to => 'passthrough#index'

Таким образом, у всех пользователей будет одна точка входа, которая, в свою очередь, перенаправляет их на соответствующий контроллер/действие в зависимости от их роли.

Ответ 2

Самое простое решение - использовать lambda:

root :to => 'project_managers#index', :constraints => lambda { |request| request.env['warden'].user.role == 'project_manager' }
root :to => 'clients#index'

Ответ 3

Еще одна опция - передать proc методу authenticated, подобному этому (я использую в этом примере преобразование):

authenticated :user, ->(u) { u.has_role?(:manager) } do
  root to: "managers#index", as: :manager_root
end

authenticated :user, ->(u) { u.has_role?(:employee) } do
  root to: "employees#index", as: :employee_root
end

root to: "landing_page#index"

Обратите внимание, что в Rails 4 вам нужно указать уникальное имя для каждого корневого маршрута, подробнее см. эту проблему.

Ответ 4

Я делаю это в приложении Rails 3, которое использует Warden. Поскольку Devise построен поверх Warden, я думаю, что это сработает для вас, но обязательно поэкспериментируйте с ним немного, прежде чем полагаться на него.

class ProjectManagerChecker
  def self.matches?(request)
    request.env['warden'].user.role == 'project_manager'
  end
end

# routes.rb
get  '/' => 'project_managers#index', :constraints => ProjectManagerChecker
get  '/' => 'clients#index'

Если роль пользователя - "project_manager", будет использоваться ProjectManagersController - если это не будет использоваться ClientsController. Если они вообще не вошли в систему, env['warden'].user будет равно нулю, и вы получите сообщение об ошибке, так что вы, вероятно, захотите обойти это, но это поможет вам начать.