Rails and Devise: Error with namespace - ruby-on-rails

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

Related

Rails Devise - prevent redirect to log in from root

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.

Authenticated Devise root with username

If a user is logged in with Devise, I'd like to redirect them to their Posts index.
/username/posts
According to the Devise docs
I can use an authenticated block.
authenticated :user do
....
end
But I need the user's username to redirect there. Something like this.
authenticated :user do |user|
get '/', to: user_posts(user)
end
But this is not supported.
How to redirect with the current user to an authenticated root?
Edit:
NOT trying to do a after sign in Devise path. Trying to achieve a permanent root for logged in users and one for logged out users.
Try that:
class ApplicationController < ActionController::Base
def after_sign_in_path_for(user)
user_posts_url(user)
end
end
So you can do something like this
in your routes:
#config/routes.rb
Rails.application.routes.draw do
devise_for :users, :controllers => {
...
}
authenticate :user do
namespace :users do
...
root :to => 'posts#index' # /users/posts # this will only be accessible to login users
end
end
root :to => 'pages#index' #/pages this is accessible to all people
end
you will need:
#app/controllers/user_controller.rb
class UserController < ApplicationController
before_action :authenticate_user!
end
and
#app/controllers/users/posts_controller.rb
class Users::PostsController < UserController
def index
#posts = current_user.posts
end
...
end
I hope that this helps

Only allow admin to create new admin

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

custom action for devise registrations controller getting nil resource

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%>

Rails NameError (uninitialized constant Registration):

I am currently using Cancan and my users basically have different 'roles'.
I only want people to be able to register 'consumer' user accounts and for business accounts admins will be doing that.
So now, I have this in my ability.rb
def initialize(user)
user ||= User.new
...
# You can only create accounts that are consumers
can :create, User do |user|
user.role? :consumer
end
and in my controller/users/registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
load_and_authorize_resource
end
and config/routes.rb:
devise_for :users, :controllers => {
:registrations => "users/registrations"
}
Now when I visit the registration page, I am seeing "uninitialized constant Registration" with NO stack trace whatsoever. Any ideas?
My code example
class ApplicationController < ActionController::Base
authorize_resource
check_authorization
end
class Users::SessionsController < Devise::SessionsController
skip_authorize_resource
skip_authorization_check
end
For load_and_authorize_resource you will need skip_load_and_authorize_resource. And all this code is applicable for custom devise's controller. Just create one.
The issue is with the routes, please follow the following steps
1. $ rake routes, you will see the list of routes
2. In your config/routes.rb write the route you need, In my case the route to create a new user was,
devise_for :users, :controllers => { :new_user_registration => "users/registrations#new" }
3. restart rails server

Resources