rails devise after_sending_reset_password_instructions weird behaviour - ruby-on-rails

i want to redir to a page after sending reset pass instructions, so, by devise docu i added this to my password_controller
protected
def after_sending_reset_password_instructions_path_for(resource_name)
'buyers/sign_in'
end
in routes i have the
devise_for :buyers, :controllers => { :passwords => "passwords" }
and if i add 'puts 'xxxxxxx'' to the function i can even see this output in my server, but it wont REDIRECT to the path i m returning.
what s the problem?

in the end the problem was due to 'create' func was overloaded and changed severely(also calling super which didn't fit my needs), had to edit it and add this
if successfully_sent?(resource)
redirect_to new_partner_session_path
else
for it to work.

Related

Trying to override controller in Thoughtbot's Clearance gem for Rails

I am using Clearance 1.1.0 gem with Ruby on Rails 4.0.1. I am trying to override the sessions controller to provide my own custom method. I have not been able to successfully get rails to use my controller.
/app/controllers/sessions_controller.rb
class SessionsController < Clearance::SessionsController
private
def flash_failure_after_create
flash.now[:notice] = translate(:bad_email_or_password,
:scope => [:clearance, :controllers, :sessions],
:default => t('flashes.failure_after_create', :new_password_path => new_password_path).html_safe)
end
end
I have tried a few different things inside my routes.rb file, and have been unsuccessful. I want to change the route sign_in.
get '/sign_in' => 'sessions#new', :as => 'sign_in'
Yields the following error.
You may have defined two routes with the same name using the :as
option, or you may be overriding a route already defined by a resource
with the same naming.
Any ideas? Thank you!
Edit: I made a mistake. I actually need sessions#create to use my controller. I'm trying to pass a different variable to the yaml file for the flash when the session login fails.
Edit 2: I the appropriate session#create line to to my routes. In my session controller, I copied and edited for testing the flash_failure_after_create method. It is not being called. So I then copy the create method over. Now, my create method is being called, but not my flash_failure_after_create method. To get it to be called, I had to have the create method copied from gem, and changed status.failure_message to directly call the flash_failure_after_create method. Is this some sort of bug with clearance?
routes.rb
post 'session' => 'sessions#create', :as => nil
sessions_controller.rb
class SessionsController < Clearance::SessionsController
def create
#user = authenticate(params)
sign_in(#user) do |status|
if status.success?
redirect_back_or url_after_create
else
#flash.now.notice = status.failure_message
flash.now.notice = flash_failure_after_create
render :template => 'sessions/new', :status => :unauthorized
end
end
end
private
def flash_failure_after_create
# Changed flash for easy testing
flash.now[:notice] = 'Ballz.'
#flash.now[:notice] = translate(:bad_email_or_password,
# :scope => [:clearance, :controllers, :sessions],
# :default => t('flashes.failure_after_create', :sign_up_path => sign_up_path).html_safe)
end
end
I believe this will work:
get '/sign_in' => 'sessions#new', :as => nil
Rails 4 no longer supports overriding route names, so don't name your override. The mapping is still the same so sign_in_path should still work.

Why isn't Devise + Omniauth callback hitting the correct controller?

Can anyone help me get to the bottom of this problem?
I'm using Devise + Omniauth in a Rails 3.2 app. What I want to know is, what's happening behind the scenes with Devise's user_omniauth_authorize_path(provider) method.
I've had a dig through rake routes and the gem's source, but I can't see anything obvious that would cause the issue I'm having.
I assume this method simply calls the provider's signin url (e.g. Twitter) and then returns to the callback path defined in routes.rb.
In my routes.rb I have
devise_for :users, :controllers => { :omniauth_callbacks => 'users/omniauth_callbacks'}
devise_scope :user do
get '/users/auth/:provider' => 'users/omniauth_callbacks#passthru'
end
In users/omniauth_callbacks_controller.rb I have
def twitter
render :text => "This works"
end
def passthru
render :text => "This doesn't work"
end
In a view I have <%= link_to "Twitter", user_omniauth_authorize_path(:twitter) %>. Clicking this link goes to Twitter where I can log in, but upon return to my app I get an error "You are already signed in".
I can't work out how or why this error is being generated. I should only be seeing "This works" or "This doesn't work".
I also have a Facebook provider set up in exactly the same way, and this works as expected.
If I replace Devise's omniauth link with Twitter then I get "This works".
So this solves my issue, but its not ideal and I'd like to know why.
Can anyone shed any light?
EDIT
Rake routes looks like this:
user_omniauth_callback /users/auth/:action/callback(.:format) users/omniauth_callbacks#(?-mix:twitter|facebook)
Well, it is working for me, so it is definitely something on your end. First of all, have you compared in the console the GET calls /users/auth/twitter and /users/auth/twitter?callback obtained by the 2 different methods? They should look exactly the same (except for the token and the verifier, of course).
Now, I'm not sure if this is related, but with devise you don't use a passthru route, so you can remove that route. Instead, in your callbacks controller, you should implement an action called failure that handles a bad request. See here for devise's implementation.
I'm grasping at straws here, but you should also have this at the end of your callbacks controller:
# This is necessary since Rails 3.0.4
# See https://github.com/intridea/omniauth/issues/185
# and http://www.arailsdemo.com/posts/44
protected
def handle_unverified_request
true
end

Missing template with Devise custom registration controller

When using recaptcha for Devise I have to make a new custom registrations controller and my issue is I get a missing template error when their is an error for the email, password or password confirmation because its hitting a route that doesn't even exist.
Template is missing
Missing template registrations/new
The recaptcha works on its own error and renders back to the same page but not for the others.
class RegistrationsController < Devise::RegistrationsController
def create
if verify_recaptcha
super
else
flash.delete :recaptcha_error
build_resource
clean_up_passwords(resource)
flash[:alert] = "There was an error with the recaptcha code below."
render :template => '/devise/registrations/new'
end
end
end
devise_for :users, :controllers => { :registrations => "registrations" }
It should be hitting the same page the recaptcha does on errors ('/devise/registrations/new')How do I correct this issue?
Thanks.
Try moving the templates from /views/devise/registrations to just /views/registrations. (And changing the reference in your code from /devise/registrations/new to just /registrations/new.)
Add following line to your config/application.rb file
config.paths['app/views'] << 'app/views/devise'

Remove Devise Flash Notices for Sign out

As the name says, I am using devise for user auth in a rails 3 app
Upon user log out, there is a flash notice, "User Successfully signed out" that I don't want to appear. However, I can't figure out how to remove the notice.
Is there a way to get around just making it blank? I would like to completely remove the notice so that, ideally, there's not even an html div for notice
If you explicitly put in a blank string for this in your locale file, then Devise "won't bother" to render the message at all (e.g. there won't even be an empty HTML div).
#en.yml
devise:
sessions:
signed_in: 'Signed in successfully.'
signed_out: ''
My routes.rb
devise_for :users, :controllers => {
sessions: 'user/sessions'
}
My controller "account/sessions_controller.rb"
class User::SessionsController < Devise::SessionsController
def destroy
super
flash.delete(:notice)
end
end

How can I redirect a user's home (root) path based on their role using Devise?

I'm working on a project management app, and in the app, I have project_managers and clients. I'm using Devise and CanCan for authentication/authorization.
At what point after login should I be redirecting the user to their own specific controller/layout/views? Is there a way to check for current_user.role in routes.rb and set the root (or redirect) based on whether or not they're a project manager or a client? Is this a change I can make in Devise somewhere?
Thanks in advance for any help!
--Mark
Your routes.rb file won't have any idea what role the user has, so you won't be able to use it to assign specific root routes.
What you can do is set up a controller (for example, passthrough_controller.rb) which in turn can read the role and redirect. Something like this:
# 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'
This way, all users will have one point of entry, which in turn redirects them to the appropriate controller/action depending on their role.
The simplest solution is to use lambda:
root :to => 'project_managers#index', :constraints => lambda { |request| request.env['warden'].user.role == 'project_manager' }
root :to => 'clients#index'
Another option is to pass a proc to the authenticated method like this (I'm using rolify in this example):
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"
Note that in Rails 4 you have to specify a unique name for each root route, see this issue for details.
I do this in a Rails 3 app that uses Warden. Since Devise is built on top of Warden, I think it'll work for you, but be sure to experiment with it a bit before relying on it.
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'
If the user's role is "project_manager" the ProjectManagersController will be used - if it's not the ClientsController will be used. If they're not logged in at all, env['warden'].user will be nil and you'll get an error, so you'll probably want to work around that, but this will get you started.
Blog post with the implementation http://minhajuddin.com/2011/10/24/how-to-change-the-rails-root-url-based-on-the-user-or-role/

Resources