I want to override show logic in order to permit change password not only if it is expired, but some days earlier. I need to modify or replace this before_filter logic
def skip_password_change
return if !resource.nil? && resource.need_change_password?
redirect_to :root
end
I want to make my controller like this:
class PasswordsController < Devise::PasswordExpiredController
# ...
def skip_password_change
return if !resource.nil? && (resource.need_change_password? || ... )
redirect_to :root
end
end
How to achieve my goal?
UPD:
all answers below are kind of right, I missed one thing - my custom controller was placed inside controllers/admin directory, so I should name it Admin::CustomPasswordExpiredController, but I missed Namespace prefix Admin and rails fell into circular dependency.
Just extend devise controller with your custom controller:
# config/routes.rb
devise_for :users, controllers: { passwords: 'custom_passwords' }
# app/controllers/custom_passwords_controller.rb
class CustomPasswordsController < Devise::PasswordsController
def edit
resource = resource_class.new
return unless resource.need_change_password? # your middleware logic here
super
end
end
More facilities can be found in devise PasswordsController documentation (by clicking "View source")
You can try this workaround, first skip the default before_action for skip_password_change method, then add a custom method to wrap it in a condition. Try this
class PasswordsController < Devise::PasswordExpiredController
skip_before_action :skip_password_change, only: :show
before_action :skip_password_change_show, only: :show
def skip_password_change_show
return if !resource.nil? && (resource.need_change_password? || #yourcondition )
redirect_to :root
end
end
Hope that helps!
Go to your routes file and overwrite the controller methods there.
Something like devise_for :users, controllers: {x: 'y'} where x is the name of the controller from devise that you want to overwrite and y is the name of your custom controller you want to overwrite with
Related
I am new to rails and just come across this can anyone tell me where and how to define these functions if I want to change my redirect hooks.
And what is the need of the protect_from_forgery in devise ?
Creating your own sessions controller and override the methods:
class SessionsController < Devise::SessionsController
def after_sign_in_path_for(resource)
# add your logic here.
end
def after_sign_out_path_for(resource)
# add your logic here.
end
end
In routes.rb add the below declaration:
devise_for :users, controllers: {sessions: "sessions"}
My goal is simple. I want to allow a user to sign up only if he possesses a unique secret code. I would like to check if this code is valid (being in my secret codes database) and then delete it once the user signed up.
I have a secret_code model with:
:secret_code column
I have a input for the secret code in my sign up form
<%= f.input :secret_code, required: true, autofocus: true %>
Should I personalize the class RegistrationsController < Devise::RegistrationsController?
How ? Thanks !
You can do that by overriding registrationcontroller. Uncomment create method like this.
def create
super
end
and add a filter like:
before_action :check_secret_code, only: [:create]
and you must modify your routes to tell devise use your controller instead of its default:
devise_for :users, controllers: { registrations: "users/registrations" }
you can specify what you want in that check_secret_code method and make render 'new' if code is wrong. Hope it helps.
You can achieve this with a simple before filter. This way you don't have to mess with devise code.
class RegistrationsController < Devise::RegistrationsController
before_filter :check_conditions, only: :create
def create
super
end
private
def check_conditions
#your conditions
end
end
Solved! Along to #Mehmet answer I had to cutomize application_helper.rb
module ApplicationHelper
def resource_name
:user
end
def resource
#user ||= User.new
end
def devise_mapping
#devise_mapping ||= Devise.mappings[:user]
end
end
And put include ApplicationHelper after the class name in registrations_controller.rb
I'd like to write a custom method around Devise's edit profile page. I'd like it to be run before the edit page is loaded and after it is submitted. However, my code doesn't seem to be working:
class RegistrationsController < Devise::RegistrationsController
before_filter :check_tutor, only: :edit
private
def check_tutor
if current_user.is_tutor
current_user.build_tutor if current_user.tutor.nil?
else
current_user.tutor.destroy
end
end
end
Any ideas as to why this may be? Thanks!
Try adding edit action to this controller
def edit
super
end
For the filter to execute after the form is submitted, you will have to add
before_filter :check_tutor, only: [:edit, :update]
def update
super
end
For devise to pick up you controller you need to do following change in routes
devise_for :users, controllers: {registrations: "registrations"}
you might also want to consider an around_filter http://guides.rubyonrails.org/action_controller_overview.html#after-filters-and-around-filters. i'd show some sample code but i'm not sure if you're trying to build the tutor in the before and destroy it in the after [as needed] or are these actions supposed to run on both sides of the controller action.
I am using Devise 1.5.3.
I inherited Devise::RegistrationsController for customizing my own path for after_update:
class RegistrationsController < Devise::RegistrationsController
protected
def after_update_path_for(resource)
some_path
end
end
After that Rails tries to find views for registration actions (new, create, etc) in views/registrations/ but no in /views/devise/registrations
Sure, I can copy all from /views/devise/registrations to views/registrations/. But it's not suitable for me, because rest of my view (for not customized controllers) still are in /views/devise/registrations.
How Can I fix it?
I think it should work if you scope your RegistrationsController into Devise's scope:
class Devise::MyRegistrationsController < Devise::RegistrationsController
# ...
end
Of course you can't use the same name for the RegistrationsController and you have rename the views/devise/registrations folder to views/devise/my_registrations and you have to update your routes.rb file as well... but with this setup it should work...
Another option, I think, would be to overwrite/inject the method in an initializer:
class Devise::RegistrationsController
protected
def after_update_path_for(resource)
some_path
end
end
which may be simpler...
Building on Vapire's answer. I think the inject option is simplest/best.
Because I want to include a permanent 'Edit my Registration' in the navbar, so that it can be called from any page,I also want to send the user back to the page they clicked from.
I found a simple way to do this was to override some of the controller behaviour and use a session variable to capture the referring path. Using a session variable keeps the referrer path intact if the form has to be reloaded to correct errors.
routes.rb
devise_for :users, :controllers => {:registrations=>'users/registrations'}
controllers/users/registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
def edit
session[:called_from]=request.referer
super #revert to standard behaviour
end
def after_update_path_for(resource)
session[:called_from] #returns to the page called from
end
end
The accepted answer by #Vapire does not work for me for Rails 4. I had to override the Devise Passwords controller like this:
# users/passwords_controller.rb
class Users::PasswordsController < Devise::PasswordsController
protected
def after_resetting_password_path_for(resource)
signed_in_root_path(resource)
end
end
There is documentation on this method here: https://github.com/plataformatec/devise/wiki/How-To:-redirect-to-a-specific-page-on-successful-sign-in
I have a before_filter in my ApplicationController; that is, for every controller in my project.
How can I skip_before_filter for Devise's SessionsController create action ?
Here's a method my colleague just showed me:
# In config/application.rb
module YourAppNameHere
class Application < Rails::Application
# Whatever else is already here...
# The part to add
config.to_prepare do
Devise::SessionsController.skip_before_filter :your_before_filter_here
end
end
end
I recently had this problem with filter in my application_controller I solved it using skip_before_filter
skip_before_filter :check_subdomain!, if: :devise_controller?
We did something like this:
First up, create your own session controller, make sure to inherit correctly:
class SessionsController < Devise::SessionsController
skip_before_filter :foobar
Then fix the routes
devise_for :users,
:controllers => {
:sessions => "sessions"
}
Alternatively you could monkey-patch Devise's session controller.
Here's another way in lib/devise_sessions_controller_decorator.rb:
module DeviseSessionsControllerDecorator
extend ActiveSupport::Concern
included do
skip_before_filter :your_filter_name
end
end
Devise::SessionsController.send(:include, DeviseSessionsControllerDecorator)
Because classes are not cached in development mode, you may need to add something like this to config/environments/development.rb:
config.to_prepare do
Devise::SessionsController.send(:include, DeviseSessionsControllerDecorator)
end
Before my colleague showed me the way I posted in my other answer, I did this. I'm posting this in case you think it's simpler.
class ApplicationController < ActionController::Base
# ...
before_filter :do_something
def do_something
unless params[:controller] == 'devise/sessions'
# ...
end
end
end
You can simply check in your filter method whether it is devise controller or not.
if params[:controller] != 'devise/sessions'
new answer
what about wrapping the before_filter in an unless block filtering by params[:controller]
def some_before_action
unless params[:controller] == "sessions_controller_for_devise_name"
... #=> do the stuff here
end
end
old answer
just authorize which actions should use the before filter
before_filter :action, :only => ...
and authorize your others.
found this here