Tony Vincent
Tony Vincent

Reputation: 14372

Allow only admin users to access a resque web interface

In my rails app I am using devise for authentication and my model name is user for which I have a Boolean field admin. In my routes.rb, I am trying to limit all users except admins from accessing a url.

mount Resque::Server.new, :at => "/resque"

. I tried using devise's current_user helper like

 mount Resque::Server.new, :at => "/resque" if current_user.admin == true

But got the error undefined local variable or method 'current_user' for #<ActionDispatch::Routing::Mapper:0x000000053ac780> (NameError) . How to do this? I am new to rails please help

Upvotes: 1

Views: 1116

Answers (3)

Tony Vincent
Tony Vincent

Reputation: 14372

Finally this is what worked for me

  # routes.rb
  match "/resque" => Resque::Server, :anchor => false, :constraints => lambda { |req|
    req.env['warden'].authenticated? and req.env['warden'].user.is_admin?
  }

  # user.rb
  class MUserLogin < ActiveRecord::Base
    .
    .
    .
    def is_admin?
      # your admin logic here for example:
      self.admin == true
    end
  end

Upvotes: 1

Jaffa
Jaffa

Reputation: 12719

The best solution for this kind of behavior is to add a before_action to your controller which will produce an error if the user is not an admin:

before_action :authorize_admin_only

def authorize_admin_only
   raise RoutingError.new('Not found') if !current_user.admin
end

Your routes file is interpreted once on startup, and even if you can find ways to make routes depend on the request (e.g. with routing_filter) it is not a good idea to use this for authorization purpose.

In authorize_admin_only, you can also render an error file or simply redirect the user to another page, e.g. login.

For your specific case, as you want to mount another engine, you can also define authentication on a admin model in your routes (and special resque example)

  authenticate :admin_user do #replace admin_user(s) with whatever model your users are stored in.
    mount Resque::Server.new, :at => "/jobs"
  end

If you don't have an admin model, then you can refer to the devise documentation for authenticate and do something like this :

authenticate(:user, &:admin?) do
  mount Resque::Server.new, :at => "/jobs"
end

(&:admin? produce the same result as lambda{|user| user.admin?}, remove the ? if you did not define such alias)

Upvotes: 2

Alfie
Alfie

Reputation: 2784

There is a wiki page just for that in device,

https://github.com/plataformatec/devise/wiki/How-To:-Protect-Resque-Web-with-Devise

Upvotes: 1

Related Questions