Last Updated: February 25, 2016
· trusche

Restricting access to a Rails engine

In our Rails applications , we routinely mount engines that should only be accessible to users with particular permissions, such as administrators. There are a couple of ways to achieve this.

If you have a simple :admin boolean flag on your users, the quick and dirty approach to restricting access to an engine is with a routing constraint defined directly in routes.rb. Here's an example based on Warden authentication (e.g. Devise) and the Resque engine:

# config/routes.rb
resque_constraint = lambda do |request|
  request.env['warden'].authenticate? && request.env['warden'].user.admin?

Now you can mount the engine within the constraint:

# config/routes.rb
constraints resque_constraint do
  mount Resque::Server, :at => "/resque"

Voila - non-admin users will get a routing error when they try to access the mount point.

For more targeted access control, we use the excellent CanCan gem. To use the CanCan ability to control the mounting of the engine, we first define the constraint as a class, for example in an initializer:

# config/initiazlizers/resque.rb
class CanAccessResque
  def matches?(request)
    user = request.env['warden'].user
    return false if user.blank?
    Ability.new(user).can? :manage, Resque

Then we use this constraint in the routes file. We also need to require the resque/server for this to work:

# config/routes.rb
require 'resque/server'

constraints CanAccessResque.new do
  mount Resque::Server.new, at: 'resque', as: :resque

Now you can give access to any class of user in the Ability class. Just note that non-authorized users will again get a routing error instead of any custom defined access denied errors CanCan may provide.

Say Thanks