I've been working with Rails, Active Addmin and cancancan. Everything is working fine except one thing. Recently I have added separate namespaces for my admin type users and clients.
Before that change, I redirected all authenticated users to the same active admin dashboard in such way (routes.rb):
devise_scope :user do
authenticated :user do
root :to => 'admin/dashboard#index', as: :authenticated_root
end
unauthenticated :user do
root :to => 'pages#index', as: :unauthenticated_root
end
end
Currently I need to somehow add additional condition that will be checking if authenticated user has role admin or client.
My idea was to make sth like that:
devise_scope :user do
authenticated :user do
if current_user.role?(:Architect) || current_user.role?(:Admin)
root :to => 'admin/dashboard#index', as: :authenticated_root
else
root :to => 'clients/dashboard#index', as: :authenticated_client
end
end
unauthenticated :user do
root :to => 'pages#index', as: :unauthenticated_root
end
end
But I am getting error: undefined local variable or method `current_user'
Does anybody know how I can check user's role in routes? Is there any better way to do that?
The root is a config file responsible for routes definition, you can't access any session variables in config files.
If you want to redirect user after sign in you can use after_sign_in_path_for method in Devise::SessionsController
class SessionsController < Devise::SessionsController
def after_sign_in_path_for(resource)
if resource.role?(:Architect) || resource.role?(:Admin)
authenticated_root_url
else
authenticated_client_url
end
end
end
In your route you need to indicate the custom sessions_controller
devise_for :user, :controllers => {:sessions => "sessions"}
Page Controller :
class PageController < ApplicationController
before_filter :check_route, :only => [:index]
def check_route
return unless user_signed_in?
if current_user.role?(:Architect) || current_user.role?(:Admin)
redirect_to :controller => 'admin/dashboard', :action => 'index'
else
redirect_to :controller => 'clients/dashboard', :action => 'index'
end
end
end
routes.rb:
root :to => 'pages#index', as: :unauthenticated_root
Related
First, see my routes :
Rails.application.routes.draw do
require 'sidekiq/web'
mount Sidekiq::Web => '/sidekiq'
devise_for :users, controllers: {
registrations: "registrations",
sessions: "sessions"
}
devise_scope :user do
authenticated :user do
root 'appointments#index', as: :authenticated_root
end
unauthenticated do
root 'sessions#new', as: :unauthenticated_root
end
match '/logout', :to => 'devise/sessions#destroy', via: :all
end
resources :appointments do
get :available_slots, on: :collection
resources :notes
resources :images, only: [:show]
end
#patch 'appointments/:id' => "appointments#update_status", as: :update_status
match 'appointments/:id/update_status' => "appointments#update_status", :via => :post
match 'appointments/:id/visited_patient_appointment' => "appointments#visited_patient_appointment", :via => :post
get 'archive' => "appointments#archive"
end
Now, how to redirect to appointments_path after user sign in? There is one devise method called after_sign_in_path_for(resource) which I override in Appointments Controller but still it is not working.
You trying to override in Appointments Controller which is wrong, it will be sessions_controller.rb or application_controller.rb
Try the following in the sessions_controller.rb or application_controller.rb
protected
def after_sign_in_path_for(resource)
stored_location_for(resource) || appointments_path
end
If not have stored_location then he will redirect to appointments_path
If you need to redirect all time to the same page like appointments_path then
protected
def after_sign_in_path_for(resource)
appointments_path
end
See the Devise wiki
I have installed devise and activeadmin gem. When I try to login via client then I get redirected to the right page but when I try to login via admin I get redirected to the client login page.
routes.rb
namespace :admin do
# get "/stats" => "stats#stats"
devise_scope :admin_user do
get '/stats/:scope' => "stats#stats", as: :admin_stats
end
end
devise_for :admin_users, ActiveAdmin::Devise.config
ActiveAdmin.routes(self)
namespace :client do
get 'dashboard' => 'dashboard#index', as: 'dashboard'
end
devise_for :users, class_name: 'FormUser', controllers: { omniauth_callbacks: 'omniauth_callbacks', registrations: 'registrations' }
devise_scope :user do
root to: 'devise/registrations#new'
end
application_controller.rb
def after_sign_in_path_for(resource_or_scope)
client_dashboard_path
end
def after_sign_out_path_for(resource_or_scope)
root_path
end
How can I fix this?
Here is a link to the test app enter link description here
Admin login enter link description here
def after_sign_in_path_for(resource_or_scope)
case resource_or_scope
when AdminUser
admin_dashboard_path
when User
client_dashboard_path
end
end
I have this in my routes file:
devise_for :users, :controllers => { :registrations => "users/registrations",
:sessions => "users/sessions",
:omniauth_callbacks => "users/omniauth_callbacks" }
devise_scope :user do
get 'sign_in', :to => 'users/sessions#new', :as => :new_user_session
get 'sign_out', :to => 'devise/sessions#destroy', :as => :destroy_user_session
end
and now I added:
resources :users
because I want an admin user to be able to see all the users.
In CanCan I have this:
class Ability
include CanCan::Ability
def initialize(user)
if user
if user.admin?
can :manage, :all
end
can [:read, :edit, :update], User, :id => user.id
end
can [:create], User
end
end
Is this secure enough? Should I also add a before_filter in the UserController to block calls to the newly created route? Something like this? Problem with this is that users can't change their own profile anymore...
before_filter :check_rights
private
def check_rights
unless current_user.admin
redirect_to root_path
end
end
Found the solution. The before_filter is completely correct.
I had added
resources :users
before the devise part, you need to put it behind that part then users can still alter their own profile but can't go to index for example.
After sign in or sign out with Devise, I'm redirected back to the parent app root_path rather than my engine's root path (or, as you can see below, where I tried to specify it to home_path).
Engine routes:
MyEngine::Engine.routes.draw do
devise_for :users, {
:class_name => "MyEngine::User",
:module => :devise
}
get '/' => 'home#index', as: :home
root :to => 'home#index'
end
Engine Application Controller:
module MyEngine
class ApplicationController < ActionController::Base
def after_sign_in_path_for(resource)
home_path
end
end
end
Thanks...
The problem was not having namespaced the sessions controller. Specifying the controller explicitly in the engine, and having it namespaced correctly fixed the issue.
Routes:
MyEngine::Engine.routes.draw do
devise_for :users, {
:class_name => "MyEngine::User",
:module => :devise,
:controllers => { :sessions => "my_engine/sessions" }
}
end
SessionsController in 'controllers/my_engine/sessions_controller':
module MyEngine
class SessionsController < ::Devise::SessionsController
end
end
Referenced the online documents for Devise but my override is still not working. Any one got any suggestions why not? It just goes to the root after sign in. Sign up works though.
Routes:
root :to => 'pages#index'
get "pages/index"
devise_for :users, :path => 'accounts', :controllers => { :registrations => "registrations" }
match 'profile' => 'profiles#show', :as => 'current_profile'
match 'profile/edit' => 'profiles#edit', :as => 'edit_current_profile'
put 'profile' => 'profiles#update'
resources :users do
resources :profiles
end
Registration Controller:
class RegistrationsController < Devise::RegistrationsController
protected
def after_sign_up_path_for(resource)
edit_current_profile_path
end
def after_sign_in_path_for(resource)
current_profile_path
end
end
def after_sign_in_path_for(resource)
current_profile_path
end
This goes in the application_controller, not the override class.