My blog has a devise model called Admin.
I definitely don't want that visitors of my website can register as an admin. So I did the following:
In my config/routes.rb
devise_for :admins, controllers: { registrations: "registrations" }
After that I created a new app/controllers/registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
before_action :authenticate_admin!
end
But when I visit my my.site/admins/sign_up as a "normal visitor" the authenticate_admin! hook is not called - so I get a full working registration form. Why isn't this working as expected?
The accepted answer from this question may help. To summarize, Devise's RegistrationsController skips authentication by default:
prepend_before_action :require_no_authentication, only: [:new, :create, :cancel]
So, skip it and your before_action should work:
class RegistrationsController < Devise::RegistrationsController
skip_before_action :require_no_authentication
before_action :authenticate_scope!
end
Related
I want users to access the home page whether they're authenticated or not. Though, whenever the root url is visited, the user is immediately redirected to /users/sign_in. How do I disable this?
routes.rb
Rails.application.routes.draw do
root 'home#index'
devise_for :users
end
home_controller.rb
class HomeController < ApplicationController
before_action :authenticate_user!, except: [:index]
def index
end
end
With Devise is usually better to require authentication by default and then add exceptions with skip_before_action:
class ApplicationController < ActionController::Base
before_action :authenticate_user!
end
class HomeController < ApplicationController
skip_before_action :authenticate_user!
def index
end
end
This avoids the risk of leaving security holes just by programmer omission.
I can do this to skip calling "authenticate_user" in a certain controller where I need to:
class ApplicationController
before_filter :authenticate_user!
end
class MyController < ApplicationController
skip_before_filter :authenticate_user!
end
I want to call skip_before_filter for "login" action of devise gem and I don't want to have to override anything else. How can I do that?
One approach is to override devise sessions controler:
1) create a users/sessions_controller.rb file:
class Users::SessionsController < Devise::SessionsController
skip_before_filter :authenticate_user!
end
2) and set it on routes.rb:
devise_for :users, controllers: { sessions: "users/sessions"}
skip_before_filter is deprecated, so try to use skip_before_action
it's worked with me
What I need is that when a user goes to '/admin', it redirects to '/admins/sign_in' for the user to sign in.
This is what I did:
# routes.rb
devise_for :admins
namespace :admin do
root to: 'users#index'
end
.
# controllers/admin/base_controller.rb
class Admin::BaseController < ApplicationController
before_action :authenticate_user!
layout 'admin'
end
.
# controllers/admin/users_controller.rb
class Admin::UsersController < Admin::BaseController
def index
end
end
The problem is that when I go to '/admin' it returns me an error:
NoMethodError in Admin::UsersController#index ..
undefined method `authenticate_user!' for Admin::UsersController
How can I make it work?
We have nearly the same setup as you, and it works perfectly:
I think the problem is that you're using devise_for :admins, and yet calling authenticate_user!; it should be authenticate_admin! (as per the Devise docs):
class Admin::BaseController < ApplicationController
before_action :authenticate_admin!
end
basically I want to have two separate actions for change password and change email instead of just one.
I have updated my routes to point to my new controller which inherits from Devise::RegistrationsController.
My routes.rb:
devise_for :users, :controllers => { :registrations => "registrations" }
devise_scope :user do
get "/users/password" => "registrations#change_password", :as => :change_password
end
My registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
def change_password
end
end
My app/views/devise/registrations/change_password.html.erb
<%=debug resource%>
Which gives me nil.
What am I missing here?
Thanks!
In Devise's built-in registrations_controller.rb, there is an authenticate_scope! method that creates the resource object you're looking for. It is executed by a prepend_before_filter, but only for certain methods:
class Devise::RegistrationsController < DeviseController
...
prepend_before_filter :authenticate_scope!, :only => [:edit, :update, :destroy]`
So you simply need to tell your custom controller to run that filter on your change_password method:
class RegistrationsController < Devise::RegistrationsController
prepend_before_filter :authenticate_scope!, :only => [:change_password]
def change_password
end
end
class RegistrationsController < Devise::RegistrationsController
def change_password
super
#resource = resource
end
end
app/views/devise/registrations/change_password.html.erb
<%=debug #resource%>
I'm using Devise as authenticating solution in Rails and I have a cached fragment :recent_users.
I want this fragment to expire when a new user is registered, changed or removed, so I put in my(manually created) users_controller.rb
class UsersController < ApplicationController
cache_sweeper :user_sweeper, :only => [:create, :update, :destroy]
...
But my fragment does not expire when new creates or changes.
My user_sweeper contains basic prescriptions
class UserSweeper < ActionController::Caching::Sweeper
observe User
def after_save(user)
expire_cache(user)
end
def after_destroy(user)
expire_cache(user)
end
private
def expire_cache(user)
expire_fragment :recent_users
end
end
What am I doing wrong?
Problem solved!
I followed this steps and everything works:
$ mkdir app/controllers/users
$ touch app/controllers/users/registrations_controller.rb
In registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
cache_sweeper :user_sweeper, :only => [:create, :update, :destroy]
end
Problem was that Registrations in Devise is a separate controller.
Put this in applications_controller.rb
class ApplicationController < ActionController::Base
cache_sweeper :user_sweeper, :only => [:create, :update, :destroy]
...