I need to override some methods in Devise::TwoFactorAuthenticationController from this repository but I cannot find a way of doing that.
I tried to create two_factor_authentication.rb file in config/initializers/ and try to override this way:
Devise::TwoFactorAuthenticationController.class_eval do
def name_of_the_method_you_want_to_override
code
end
end
But changes in this class are not affecting Devise::TwoFactorAuthenticationController
I tried standard any device controller overriding way
created:
app/controllers/administrators/two_factor_authentication_controller.rb
edited routes:
devise_for :administrators, controllers: {
two_factor_authentication: 'administrators/two_factor_authentication'
}
then tested:
class Administrators::TwoFactorAuthenticationController < Devise::TwoFactorAuthenticationController
def show
binding.pry
end
end
And it worked
Related
i build a ruby on rails app base on dookeeper and devise and now I'm going to change the default RegistrationController that is in Devise::RegistrationsController which made by default on ruby to the custom one that i made in a folder api/users/registrationController.
i tried several ways one of is this:
devise_for :users,
only: :registrations,
controllers: {
registrations: 'api/users/RegistrationsController'
}
but i get error that says this:
'api/RegistrationsController' is not a supported controller name. This can lead to potential routing problems. See http://guides.rubyonrails.org/routing.html#specifying-a-controller-to-use
the ways that i declare the RegistrationController is like this:
class RegistrationsController < Devise::RegistrationsController
respond_to :json
end
of course i made some method in like create in this file file but when i send post request like localhost:3000/users and a json file it refer me to this class class Devise::RegistrationsController < DeviseController and check whole process here.
You shouldn't have the word 'Controller' in the string, and you need to downcase it too:
'api/users/registrations'
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
I could not word the title properly but I hope you understand. I have followed the exact example on how to generate a controller.
rails generate devise:controllers users
My routes:
devise_for :users, controllers: { sessions: "users/sessions" }
Then copy (new.html.erb) from devise/sessions to views/users/sessions, then delete the view from devise/sessions/
Then in:
class Users::SessionsController < Devise::SessionsController
def new
super
#foo = 'Bar'
end
end
Now in my views/users/sessions/new.html.erb:
<%= #foo %> # should show Bar
That not showing. Am I missing something?
This is what your SessionsController should look like:
class Users::SessionsController < Devise::SessionsController
def new
#foo = 'bar'
super
end
end
Note how super is below your custom code.
When you call super, it calls the parent method; in our case Devise::SessionsController#new. You need to initialize #foo before calling that method and rendering the new.html.erb.
I want to create a method that, when called from a controller, will add a nested resource route with a given name that routes to a specific controller. For instance, this...
class Api::V1::FooController < ApplicationController
has_users_route
end
...should be equivalent to...
namespace :api do
namespace :v1 do
resources :foo do
resources :users, controller: 'api_security'
end
end
end
...which would allow them to browse to /api/v1/foo/:foo_id/users and would send requests to the ApiSecurityController. Or would it go to Api::V1::ApiSecurityController? It frankly doesn't matter since they're all in the same namespace. I want to do it this way because I want to avoid having dozens of lines of this:
resources :foo do
resources :users, controller: 'api_security'
end
resources :bar do
resources :users, controller: 'api_security'
end
Using a method is easier to setup and maintain.
I'm fine as far as knowing what to do once the request gets to the controller, but it's the automatic creation of routes that I'm a little unsure of. What's the best way of handling this? The closest I've been able to find is a lot of discussion about engines but that doesn't feel appropriate because this isn't separate functionality that I want to add to my app, it's just dynamic routes that add on to existing resources.
Advice is appreciated!
I ended up building on the blog post suggested by #juanpastas, http://codeconnoisseur.org/ramblings/creating-dynamic-routes-at-runtime-in-rails-4, and tailoring it to my needs. Calling a method from the controllers ended up being a bad way to handle it. I wrote about the whole thing in my blog at http://blog.subvertallmedia.com/2014/10/08/dynamically-adding-nested-resource-routes-in-rails/ but the TL;DR:
# First draft, "just-make-it-work" code
# app/controllers/concerns/user_authorization.rb
module UserAuthorization
extend ActiveSupport::Concern
module ClassMethods
def register_new_resource(controller_name)
AppName::Application.routes.draw do
puts "Adding #{controller_name}"
namespace :api do
namespace :v1 do
resources controller_name.to_sym do
resources :users, controller: 'user_security', param: :given_id
end
end
end
end
end
end
end
# application_controller.rb
include UserAuthorization
# in routes.rb
['resource1', 'resource2', 'resource3'].each { |resource| ApplicationController.register_new_resource(resource) }
# app/controllers/api/v1/user_security_controller.rb
class Api::V1::UserSecurityController < ApplicationController
before_action :authenticate_user!
before_action :target_id
def index
end
def show
end
private
attr_reader :root_resource
def target_id
# to get around `params[:mystery_resource_id_name]`
#target_id ||= get_target_id
end
def get_target_id
#root_resource = request.fullpath.split('/')[3].singularize
params["#{root_resource}_id".to_sym]
end
def target_model
#target_model ||= root_resource.capitalize.constantize
end
def given_id
params[:given_id]
end
end
Playing with Rails and controller inheritance.
I've created a controller called AdminController, with a child class called admin_user_controller placed in /app/controllers/admin/admin_user_controller.rb
This is my routes.rb
namespace :admin do
resources :admin_user # Have the admin manage them here.
end
app/controllers/admin/admin_user_controller.rb
class AdminUserController < AdminController
def index
#users = User.all
end
end
app/controllers/admin_controller.rb
class AdminController < ApplicationController
end
I have a user model which I will want to edit with admin privileges.
When I try to connect to: http://localhost:3000/admin/admin_user/
I receive this error:
superclass mismatch for class AdminUserController
This error shows up if you define two times the same class with different superclasses. Maybe try grepping class AdminUserController in your code so you're sure you're not defining it two times. Chances are there is a conflict with a file generated by Rails.
To complete what #Intrepidd said, you can wrap your class inside a module, so that the AdminUserController class doesn't inherit twice from ApplicationController, so a simple workaround would be :
module Admin
class AdminUserController < AdminController
def index
#users = User.all
end
end
end
I fixed it by creating a "Dashboard" controller and an "index" def. I then edited my routes.rb thusly:
Rails.application.routes.draw do
namespace :admin do
get '', to: 'dashboard#index', as: '/'
resources :posts
end
end