Resque Rails Auth

Recently I found myself wanting to access the resque-web ui on a live application. I had considered just running resque-web as a separate process, but after reading this article I realised that I could mount resque directly in the router, awesome!

However, the application doesn’t use devise for authentication, so I wanted an easy way to restrict resque-web to admins.

Using rails 3 router’s advanced constraints you can pass a :constraints options with an object that responds to matches? and receives the current request as an argument.

Since the current user’s id is stored in the session, we can simply retrieve the user and check if they’re an admin.

class AdminRestriction
  def self.matches?(request)
    user_id = request.env['rack.session'][:user_id]
    user = User.find_by_id(user_id)
    return user && user.admin?
  end
end

MyApplication::Application.routes.draw do
  mount Resque::Server => '/resque', :constraints => AdminRestriction
  # Other application routes.
end

The AdminRestriction class performs the actual checks, in the router it is simply passed as a constraint.

First we pull the user_id out of the session, then we attempt to get the user from the database. Finally we check that we’ve found a user and that they are an admin.

If the user tries to access /resque and they are not an admin, they simply get a 404 error.

This technique can be used with any rack application, or indeed with any regular route, just pass a :constraints option (see the match method docs), and the constraints that you apply can use any part of the request to decide if it matches. You can restrict access by ip address, or do routing based on the request’s geolocation.

The possibilities are endless.