smudge
smudge

Reputation: 831

skip_before_filter ignores conditionals

I'm trying to use skip_before_filter only if the app is in production mode. (I don't want my development instances public, and I want the app to automatically detect what type of instance it is on and display a log-in screen when it is not in production mode). So, my application controller has the following line:

before_filter :authenticate_user!, :except => "sign_in" #redirects to log-in

And the controller for displaying pages has this line:

skip_before_filter :authenticate_user!, :only => :show, :if => :in_production
#public pages are public, but only when in production.

And in_production is simply:

  def in_production
    ENV['RAILS_ENV']=='production'
  end

I realize that there may be other avenues here, but I'm curious as to why skip_before_filter seems to ignore the conditional and always just skip the before_filter. Is there something I'm missing?

Upvotes: 19

Views: 14880

Answers (4)

thebenman
thebenman

Reputation: 1621

This is how I got around this issue.

skip_before_filter :authenticate_user!, :if => { action_name == 'show' && in_production }

https://github.com/rails/rails/issues/9703#issuecomment-223574827

Upvotes: 0

Rafa Paez
Rafa Paez

Reputation: 4860

I have found that the solution posted by SmartLove in the described scenario presents a kind of security hole or an unexpected behaviour. The line

before_filter :authenticate_user!, :only => :show, :unless => :in_production

because of the :only => :show, is overriding the existing before_filter defined in the ApplicationController. That means that all the actions of this controller (e.g :edit, :create, etc.), except the :show one, will be omitting the authenticate_user! filter.

A possible solution is removing the :only clause and checking the action called inside the conditional method. For example:

before_filter :authenticate_user!, :unless => :skip_filter?

def skip_filter?
  params[:action] == "show" && in_production
end

Upvotes: 7

Tony - Currentuser.io
Tony - Currentuser.io

Reputation: 1475

It is a Rails bug (or at least an undocumented strange behaviour). It is tracked here: https://github.com/rails/rails/issues/9703

In this thread, you can find a (twisted) solution.

Instead of

skip_before_filter :authenticate_user!, :only => :show, :if => :in_production

write

skip_before_filter :authenticate_user!, :only => :show
before_filter      :authenticate_user!, :only => :show, :unless => :in_production

It worked for me.

Upvotes: 21

David Sulc
David Sulc

Reputation: 25994

I'm not sure skip_before_filter accepts an :if parameter, so I'd try this syntax

(skip_before_filter :authenticate_user!, :only => [:show]) if in_production

If it still doesn't work, try putting this in your application controller

if ENV['RAILS_ENV']=='production'
  skip_before_filter :authenticate_user!, :only => :show
end

Upvotes: 5

Related Questions