Rails Devise - Different redirect paths on signup - ruby-on-rails

I'm using devise for users but I have two types of users (customers and suppliers), and need different redirect routes based on which path they follow. EG: If a customer signs (/signup) up it will redirect them to their dashboard. If a supplier signs up(/suppliers/registrations/user), it needs to direct them to the next form where they start describing their business(/suppliers/registrations/business). How do you manage this?
UPDATE
I've update my devise registrations controller to include the following (I've excluded all of the commented out stuff)
users/registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
protected
def after_sign_up_path_for(resource)
if resource.supplier == true
redirect_to supplier_business_path
elsif resource.supplier == false
redirect_to user_projects_path(current_user)
end
end
end
But it keeps taking me to the root regardless.

after_sign_in_path_for should just return the path but not perform a redirect, try changing your method like this:
protected
def after_sign_up_path_for(resource)
if resource.supplier == true
# also add specific url = '/suppliers/registrations/user'
supplier_business_path
elsif resource.supplier == false
user_projects_path(current_user)
end
end
also refer this link:
https://github.com/plataformatec/devise/wiki/How-To:-Redirect-to-a-specific-page-on-successful-sign-up-(registration)

Use devise after_sign_in_path_for method in aplication controller. For eg
def after_sign_in_path_for(resource)
if resource.role == "customer"
redirect_to customer_dashboard_path
elsif resource.role == "supplier"
redirect_to supplier_dashboard_path
end
end

Related

Override the Devise redirect path, using params?

I have followed the guide How To: Override confirmations so users can pick their own passwords as part of confirmation activation. I all works smooth.
My mailer ends up sending a confirmation link a la:
"https://example.com/users/confirmation?confirmation_token=foo"
After the user has chosen his new password ensures that the user is redirected to the standard after_sign_in_path_for:
def do_confirm
#confirmable.confirm
set_flash_message :notice, :confirmed
sign_in_and_redirect(resource_name, #confirmable)
end
But what if I want to redirect the user to an individual page, specifically tailored for this user? Like e.g.:
"https://example.com/users/confirmation?confirmation_token=foo&redirect_to=#{CGI.parse('custom_path')}"
How would I set this up?
As Tom says in the above comment, you want to override the after_sign_in_path_for method.
There is a page on devise's GitHub wiki that explains this in more detail and gives a code example (if you use OAuth it will look a little different):
class ApplicationController < ActionController::Base
protect_from_forgery
protected
def after_sign_in_path_for(resource)
sign_in_url = new_user_session_url
if request.referer == sign_in_url
super
else
stored_location_for(resource) || request.referer || root_path
end
end
end

ActiveAdmin Redirect if not an admin

I would like to create a simple redirect for admin:false Users who are willing to go to /admin pages. I am using ActiveAdmin and a single User model with a admin:bool flag. I tried the following:
in my AA init file
config.authentication_method = :authenticate_admin_user!
in my App controller
def authenticate_admin_user!
redirect_to root_path unless current_user.try(:is_admin?)
end
And nothing happens.
I also tried creating a custom method like this in a new ActiveAdmin::AuthorizationAdapter but could not figure out how to use it
def authorized?(action, subject = nil)
user.admin?
end
Try this. In my case active admin provide current_admin_user not current_user
def authenticate_admin_user!
redirect_to root_path unless current_admin_user.try(:is_admin?)
end

Rails + Devise: How to override redirect for the before_filter "authenticate_user!"

I am on Rails 3 and the latest version of Devise, and I have a before filter in my AdminController to authenticate_user! I need to store a session variable for the request.referrer before it redirects so that I can send it back to the /admin page when they try to go on it. Where would I overwrite authenticate_user!?
What I want to do is this, but I don't know where to define it:
def authenticate_user!
session[:return_to] = request.request_uri
super
end
You don't actually need to do that, devise will respect an after_sign_in_path for this exact purpose.
In your application controller:
before_filter :set_return_path
def after_sign_in_path_for(resource)
session["user_return_to"] || root_url
end
def set_return_path
unless devise_controller? || request.xhr? || !request.get?
session["user_return_to"] = request.url
end
end
From the devise helper:
# The default url to be used after signing in. This is used by all Devise
# controllers and you can overwrite it in your ApplicationController to
# provide a custom hook for a custom resource.
# def after_sign_in_path_for(resource_or_scope)
An alternative to Matt's answer, which doesn't require the return page to be recorded upon every page view:
In application_controller.rb:
# Only remembers the page immediately before we
# redirect them for auth, instead of every page view
def authenticate_user!
session["user_return_to"] = request.fullpath
super
end
# Deletes the return path as soon as it's used, so
# they aren't accidentally redirected back again
# next time they login
def after_sign_in_path_for(resource)
session.delete("user_return_to") || root_path
end

Identifying the user after sign out for after_sign_out_path_for method in Devise

For after sign in path, you can do the following:
def after_sign_in_path_for(resource)
if resource.class == User
if resource.sign_in_count < 2
'/dashboard'
else
'/dashboard/home'
end
elsif resource.class == AdminUser
I18n.locale = "en"
'/admin/dashboard'
else
I18n.locale = "en"
'/'
end
end
But, how can I check if my user is a User or an AdminUser after sign_out?
def after_sign_out_path_for(resource_or_scope)
if resource_or_scope == AdminUser
This does not work. Is there any way to check it?
Note: Although I have done a monkey patch and defined new root for admin and my problem is solved, but I want to know if there is any way to implement using after_sign_out_path_for method of Devise?
Devise gives you the current_user after you sign in which is the logged in user. There is nothing like whether the user is admin or the general user.
So its not that you can use for.
You can use other ways to get what you want.
The one is Cancan which works well with Devise, you can define user roles.
With Cancan, you can define a column in your users table, say role, with values for each user like admin or general user. So then there will be Ability.rb file for Cancan and there you can define your logic.
You can use conditions -
if user.role? :admin
#admin related logic
elsif user.role? :general
#general user related logic
end
This will work here.
def after_sign_out_path_for(resource_or_scope)
if resource_or_scope == :user
redirect_to ... # users path
elsif resource_or_scope == :admin
redirect_to .... # admins path
end
end
Devise will call the method after_sign_out_path_for with the symbol of the class name as the parameter, hence we can check the condition based on that symbol.
In your user model you could do something like this if you have a column for specifying the user role.
def admin?
role == "admin"
end
then all you do is
def after_sign_out_path_for(user)
if user.admin?

devise overrule devise SessionController broke login

I have extended the devise controller for sessions. To add some extra functionality when a user logs in. Now upon login, IF no username or password are entered I get error :
SessionsController#create
Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id
I searched last week for up to 2 hours how to fix this anyone can help me out on this one? Would be highly appreciated
How to correctly add my custom functionality but still preserve the Devise create action?
class SessionsController < Devise::SessionsController
def create
#user = User.where(:id => current_user.id).first
#moderated = Asset.where(:attachable_id => current_user.id, :moderated => true).first
if #user.sign_in_count.to_i == 1
def after_sign_in_path_for(resource)
"/welcome/basics"
end
else
if #moderated.nil?
unless #user.has_photo?
def after_sign_in_path_for(resource)
"/home/no_photo"
end
end
else
def after_sign_in_path_for(resource)
"/home/moderated"
end
end
end
end
end
If your additional functionality consists of redirecting the user to a different page at his first login i would suggest defining after_sign_in_path_for in the application controller as suggested by the wiki.
class ApplicationController < ActionController::Base
private
def after_sign_in_path_for(resource)
if current_user.sign_in_count == 1
"/welcome/basics"
else
"/other/path"
end
end
end
Please note that this only works if User is the only resource that can sign into your application. Otherwise you would have to differentiate in this method as well via the resource parameter.

Resources