Saran S.
Saran S.

Reputation: 267

Rails Devise authenticatate_user not working

I'm new to Ruby on Rails, currently I want to use Devise gem for authentication system. The system needs to have only Admin can list users and create a new user. (I added admin role by adding admin boolean field to the User model generated by Devise). I use Rails 3.2, Ruby 1.9.3 and the latest Devise gem.

However, the codes listed below do not prevent non authenticated users to access specific actions (index, new, and create).

# users_controller.rb
class UsersController < Devise::RegistrationsController
  before_filter :authenticate_user!, only: [:index, :new, :create]
  before_filter :is_admin, only: [:index, :new, :create]

  def index
  end

  private

  def is_admin
    current_user.admin?
  end
end

==

# config/routes.rb
App::Application.routes.draw do
  root to: 'static_pages#home'

  get '/about', to: 'static_pages#about'

  devise_scope :user do
    get '/users', to: 'users#index'
  end

  devise_for :users, controllers: { sessions: "sessions", registrations: "users" }
end 

The authenticate_user! method does not work (for example, non authenticated users can still access to /users or /users/sign_up) but also does not raise any exceptions. I did some searching but have no ideas why. Please help.

PS. Sorry for my English.

UPDATE

Thanks for all answers. I will update is_admin to correctly working as pointed out.

But the main problem here is that non logged in users can pass authenticate_user! filter in the first place (and raise exception on is_admin method since current_user here would be nil).

# Here non logged in users does not redirect to sign in page when access to,
# for example, /users or /users/sign_up.
before_filter :authenticate_user!, only: [:index, :new, :create] 

Sorry for being not obvious.

Upvotes: 5

Views: 3881

Answers (3)

rails_id
rails_id

Reputation: 8220

Using if..else statement on is_admin method

before_filter :authenticate_user!, only: [:index, :new, :create]
before_filter :is_admin, only: [:index, :new, :create]

private

def is_admin
 if user_signed_in?
  if current_user.admin?
    true
  else
    redirect_to some_path
  end
 else
   redirect_to login_path
 end
end

Upvotes: 0

bluehallu
bluehallu

Reputation: 10285

From the devise documentation:

Devise will create some helpers to use inside your controllers and views. To set up a controller with user authentication, just add this before_filter:

before_filter :authenticate_user!

To verify if a user is signed in, use the following helper:

user_signed_in?

For the current signed-in user, this helper is available:

current_user

So, :authenticate_user! will only make all the other helpers available on the controller (provided that you put it into a :before_filter), but it's still your responsability to define the logic for signed/unsigned users!

Keep in mind that Devise is an authentication solution, not an authorization one. If you need to handle authorization (seems like you do) without writing all the logic yourself use something like CanCan, which works wonderfully together with Devise.

Upvotes: 4

Himanth Kumar
Himanth Kumar

Reputation: 316

Obviously you need to check for a valid session user and then proceed as follows..

def is_admin
  if current_user.nil?
    redirect_to_some_path
  else
    if current_user.admin?
      true
    else
      redirect_to some_path
    end
  end
end

Upvotes: 1

Related Questions