I'm using Devise authentication gem with Rails.
How to display the message from devise.en.yml:
send_instructions: 'You will receive an email with instructions about how to reset your password in a few minutes'
after password recovery e-mail has been sent, instead of being redirected to site's root?
Update:
I've found an interesting piece of code in devise_controller.rb:
def successfully_sent?(resource)
notice = if Devise.paranoid
resource.errors.clear
:send_paranoid_instructions
elsif resource.errors.empty?
:send_instructions
end
if notice
set_flash_message :notice, notice if is_navigational_format?
true
end
end
Setting breakpoints shows that the right lines are being called, :send_instructions is assigned to notice , set_flash_message is called, but I cannot see the result of all this because I am immediately redirected to root path.
Look at the source code for devise's PasswordsController: https://github.com/plataformatec/devise/blob/master/app/controllers/devise/passwords_controller.rb#L42
You'll have to create a PasswordsController in your app that inherits from Devise::PasswordsController, implement only the after_sending_reset_password_instructions_path_for(resource_name) method and when setting the routes tell devise to use your controller
class PasswordsController < Devise::PasswordsController
protected
def after_sending_reset_password_instructions_path_for(resource_name)
#return your path
end
end
in routes
devise_for :users, :controllers => { :passwords => "passwords" }
Related
I'm building an authentication using Devise.
Creating users works, but after the creation the user is automatically logged-in and becomes redirected to the root-page.
I have created an own RegistrationController and overwritten the after_sign_up_path method:
class RegistrationsController < Devise::RegistrationsController
def after_sign_up_path_for(resource)
"/users/sign_in"
end
end
But it doesn't work.
What have I done wrong, respectively what have I missed.
I have read various other StackOverflow question already. Until now nothing has worked.
Here's my routes.rb too:
Rails.application.routes.draw do
resources :comments
resources :posts
devise_for :users, controllers: { registrations: "registrations" }
root "posts#index"
end
It seems like after you sign up successfully devise automatically log in and you cannot get login page if you still log in, correct me if I'm wrong
This is the default sign up method that ships with the RegistrationsController
# Signs in a user on sign up. You can overwrite this method in your own
# RegistrationsController.
def sign_up(resource_name, resource)
sign_in(resource_name, resource)
end
You can override it in your code.
Thanks to Nick M's answer I could solve the problem the following way:
First make sure your "routes.rb"-file has a line like here ...
Rails.application.routes.draw do
devise_for :users, :controllers => {:registrations => "registrations"}
...
end
Then create a "registrations_controller.rb"-file and add there this:
class RegistrationsController < Devise::RegistrationsController
protected
def sign_up(resource_name, resource)
sign_out :user
end
end
Doing it that way results in being redirected to the Login-form automatically, after creating a user. Exactly the behaviour I liked to accomplish.
"#sign_out(resource_or_scope = nil) ⇒ Object
Sign out a given user or scope. This helper is useful for signing out a user after deleting accounts. Returns true if there was a logout and false if there is no user logged in on the referred scope
sign_out :user # sign_out(scope)
sign_out #user # sign_out(resource)"
Source
Using Devise Gem in my project and does anybody know how to redirect user to specific url only if user signed in with token?
You can do this by creating a your own SessionsController which you can find on git
like this:
# POST /resource/sign_in
class SessionsController < Devise::SessionsController
def create
self.resource = warden.authenticate!(auth_options)
set_flash_message(:notice, :signed_in) if is_navigational_format?
sign_in(resource_name, resource)
#here you can enter your specific token code
# I guess you would do it with something like:
# if session[:token] = XYZ
# respond with ...
# else
# respond_with resource, :location => after_sign_in_path_for(resource)
# end
end
end
for using this controller you also have to change your config/routes.rb
devise_for :users, :controllers => {:sessions => "sessions"}
hope it helps you :)
If i am getting your question right so you are asking that how to redirect user after he/she sign's in.
So i ve tried this in my project
Here is the code
def after_sign_in_path_for(resource)
# Use the route you want here (i have given the url like this: '/show')
end
Hope i am taking the right meaning of the question.!! :)
How can I create an after-confirmation redirect in Devise?
Before I added the confirmation module the custom after_sign_up_path worked fine for the first time login/signup but now when I click the confirmation link in the email it redirects to the path I set for the after-login path (user profile).
My goal is to create a form wizard and "getting started" page to collect additional information. The obvious caveat being that this redirect will only happen one time, upon confirmation.
I tried some other solutions that have been posted on Stack Overflow but none of them seem to work any longer.
A less intrusive way of achieving this might be just overriding the after_confirmation_path_for method of Devise::ConfirmationsController.
Create a new confirmations_controller.rb in app/controllers directory:
class ConfirmationsController < Devise::ConfirmationsController
private
def after_confirmation_path_for(resource_name, resource)
your_new_after_confirmation_path
end
end
In config/routes.rb, add this line so that Devise will use your custom ConfirmationsController. This assumes Devise operates on users table (you may edit to match yours).
devise_for :users, controllers: { confirmations: 'confirmations' }
Restart the web server, and you should have it.
Essentially, you want to change around line 25 of Devise's ConfirmationsController.
This means you need to override the show action modifying the "happy path" of that if statement in the show action to your heart's content:
class ConfirmationsController < Devise::ConfirmationsController
def new
super
end
def create
super
end
def show
self.resource = resource_class.confirm_by_token(params[:confirmation_token])
if resource.errors.empty?
set_flash_message(:notice, :confirmed) if is_navigational_format?
sign_in(resource_name, resource)
respond_with_navigational(resource){ redirect_to confirmation_getting_started_path }
else
respond_with_navigational(resource.errors, :status => :unprocessable_entity){ render_with_scope :new }
end
end
end
And a scoped route for it (I put the view and action in the registrations controller but you can change it to whatever):
devise_for :users, controllers: { confirmations: 'confirmations' }
devise_scope :user do
get '/confirmation-getting-started' => 'registrations#getting_started', as: 'confirmation_getting_started'
end
The default show action is referring to the protected after_confirmation_path_for method, so as another option, you could just modify what that method returns.
Have you checked the Devise wiki? It explains how to do this, with the after_signup_path_for being the path to define in your case.
From the wiki:
Make a new controller "registrations_controller.rb" and customize the appropriate method:
class RegistrationsController < Devise::RegistrationsController
protected
def after_sign_up_path_for(resource)
'/an/example/path'
end
end
Then add a route to use it:
Modify config/routes.rb to use the new controller
devise_for :users, :controllers => { :registrations => "registrations" }
The solution given by #Lee Smith is working perfectly but I wish to add a little addition: We don't need to add the new and create actions while overriding the Devise confirmations controller for this case:
class ConfirmationsController < Devise::ConfirmationsController
def show
self.resource = resource_class.confirm_by_token(params[:confirmation_token])
if resource.errors.empty?
set_flash_message(:notice, :confirmed) if is_navigational_format?
sign_in(resource_name, resource)
respond_with_navigational(resource){ redirect_to your_desired_redirect_path }
else
respond_with_navigational(resource.errors, status: :unprocessable_entity){ render_with_scope :new }
end
end
end
Then in the route file, just add routing for the confirmations controller.
devise_for :users, controllers: { confirmations: "confirmations" }
I just went through all of this and none of the other answers worked (2015-04-09 with devise 3.4.1).
After signup, I wanted the user to be redirected to the login page with a message about a confirmation email. To get that working, here's what I had to do:
class RegistrationsController < Devise::RegistrationsController
protected
# This is the method that is needed to control the after_sign_up_path
# when using confirmable.
def after_inactive_sign_up_path_for(resource)
new_user_session_path
end
end
I just found this comment which would have sent me exactly where I needed to be much sooner.
Here is the reference to the after_inactive_sign_up_path_for that
mentions Niels: Devise wiki – marrossa Nov 13 '12 at 3:38
The confirmation_path also must be configured while working with refinerycms integrated in a rails app
Devise authentication gem in Rails.
How to prevent automatic logging in after password change by "forgot password" link?
Ideally it would be nice to display the page with message "New password has been saved".
You will need to override Devise's passwords_controller which you can see the default methods for here. First, create your own controller which will inherit from the Devise controller:
class User::PasswordsController < Devise::PasswordsController
Once you have your controller ready, add in all of the other methods that you do not want to override, and simply call super inside of them. This will be the new, edit, and create methods. Also don't forget to add the protected after_sending_reset_password_instructions_path_for(resource_name) method.
The method that you are concerned with overriding is the update action.
def update
self.resource = resource_class.reset_password_by_token(resource_params)
if resource.errors.empty?
flash_message = resource.active_for_authentication? ? :updated : :updated_not_active
set_flash_message(:notice, "Your flash message here")
redirect_to new_user_session_path
else
respond_with resource
end
end
All we change here is to remove the line to sign in the user with a redirect to the sign in page, and then set our custom flash message.
Lastly, you have to tell devise to use your new controller, so in routes.rb change devise_for :users to:
devise_for :users, :controllers => { :passwords => 'users/passwords' }
And that should do it.
Here's an update based on 3.1.1 of devise
class Users::PasswordsController < Devise::PasswordsController
def new
super
end
def edit
super
end
def create
super
end
#override this so user isn't signed in after resetting password
def update
self.resource = resource_class.reset_password_by_token(resource_params)
if resource.errors.empty?
resource.unlock_access! if unlockable?(resource)
flash_message = resource.active_for_authentication? ? :updated : :updated_not_active
set_flash_message(:notice, flash_message) if is_navigational_format?
respond_with resource, :location => after_resetting_password_path_for(resource)
else
respond_with resource
end
end
protected
def after_resetting_password_path_for(resource)
new_session_path(resource)
end
end
As of Devise 3.5.0, this behaviour can be controlled with a setting, which can be found in config/initializers/devise.rb:
# When set to false, does not sign a user in automatically after their password is
# reset. Defaults to true, so a user is signed in automatically after a reset.
config.sign_in_after_reset_password = false
The flash message shown will be Your password has been changed successfully., but can be adjusted in config/locales/devise.en.yml:
en:
devise:
passwords:
updated_not_active: New password has been saved
The above said answer is correct but the thing is it varies according to the devise version. I followed the above said and i could not get it working and after some time i found that i am using devise version which does not support resource_params method, then i tried different for that version and got it working.
With the Confirmable module enabled, Devise will not allow an unconfirmed user to sign in after a predefined period of time has elapsed. Instead the user is redirected back to the sign in page with the flash message "You have to confirm your account before continuing".
This is an undesirable interaction model, as a flash notice does not provide adequate space to properly explain to the user why access has been denied, what "confirm your account" means, provide a link to resend the confirmation, and instructions on how to check your spam folder and so on.
Is there a way I can change this behaviour to redirect to a specific URL instead?
Sorry at first I thought you meant after Sign Up not Sign In. So the down below works for how to direct users after Sign Up and what you need to do for Sign In is to create a custom Devise::FailureApp
See the wiki page: https://github.com/plataformatec/devise/wiki/How-To:-Redirect-to-a-specific-page-when-the-user-can-not-be-authenticated
Then within your custom FailureApp overwrite redirect_url method from https://github.com/plataformatec/devise/blob/master/lib/devise/failure_app.rb:
def redirect_url
if warden_message == :unconfirmed
custom_redirect_path
else
super
end
end
For custom redirect after Sign Up:
There is a controller method after_inactive_sign_up_path_for within the RegistrationsController that you can overwrite to accomplish this.
First in your Routes you will need to specify to use your custom controller:
config/routes.rb:
devise_for :users, :controllers => { :registrations => "users/registrations" }
Second you create your custom controller that inherits from the normal controller in order to overwrite the method:
app/controllers/users/registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
protected
def after_inactive_sign_up_path_for(resource)
signed_up_path
end
end
In this case for my App my Devise model is User so you may want to change that namespace if your model is named differently. I wanted my users to be redirected to the signed_up_path, but you can change that to your desired path.
I just did this, but took a different approach.
in app/controllers/sessions_controller.rb:
class SessionsController < Devise::SessionsController
before_filter :check_user_confirmation, only: :create
#
# other code here not relevant to the example
#
private
def check_user_confirmation
user = User.find_by_email(params[:email])
redirect_to new_confirmation_path(:user) unless user && user.confirmed?
end
end
This worked for me and seemed minimally invasive. In my app new sessions always have to go through sessions#create and users always sign in with their email address, so this may be a simpler case than yours.
You can of course redirect_to any location you desire in the check_user_confirmation method. new_confirmation_path was the logical choice for me because it provides users with the resources to get confirmed.
This is my solution you need to add :unconfirmed message on devise locales below the sessions.
in app/controllers/sessions_controller.rb
def check_user_confirmation
user = User.where(email: params[:user][:email]).take
unless user && user.confirmed?
set_flash_message! :alert, :unconfirmed
expire_data_after_sign_in!
respond_with user, location: after_inactive_sign_up_path_for(user)
end
end
protected
def after_inactive_sign_up_path_for(resource)
new_user_session_path
end