Reputation: 831
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
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
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
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
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