SessionTimeout plugin doesn't work w/other before_filters?


#1

All,

I’ve installed Luke R.'s SessionTimeout plugin and am trying to
make it work.

This is what I’ve put into my application.rb file:

session_times_out_in 30.seconds, :after_timeout =>
:handle_session_timeout, :except => :handle_session_timeout

But I also have a before_filter named :check_authentication. Even
though I do a “return false” from the handle_session_timeout method, it
still keeps trying to call check_authentication.

I looked at the SessionTimeout code and I was under the impression that
it prepended itself to the before_filter chain. So returning false from
the session timeout handler should cause the filter chain to stop
executing, correct?

Anyone know what’s going on here?

Here’s my handle_session_timeout method:

def handle_session_timeout
puts “Running handle_session_timeout”
return false
end

and what I believe to be the relevant code from SessionTimeout:

module ClassMethods
def session_times_out_in(time, opts={})
opts[:after_timeout] = opts[:after_timeout] || nil
class_eval { prepend_before_filter Proc.new { |c|
c.check_session_expiry(time, opts)}, :except => opts[:except] }
end
end

Am I misunderstanding what prepend_before_filter does?

Thanks,
Wes


#2

I think I see what’s going on here.
My :after_timeout callback is not a before_filter. The before_filter
that SessionTimeout sets up is a Proc that in turn calls my method.
This is in the body of the method that gets called as a before_filter…

if session_has_timed_out?
logger.info “::: Session has expired, resetting session.”
reset_session
unless opts[:after_timeout].nil?
logger.info “::: Calling after timeout callback”
opts[:after_timeout].call(self) if
opts[:after_timeout].instance_of?(Proc)
self.send(opts[:after_timeout]) if
opts[:after_timeout].instance_of?(Symbol)
return
end
else
logger.info “::: Session has not expired. Reinitialising.”
initialize_session_expiry(time)
end

I think if I just change this code so that it returns the value of
opts[:after_timeout], then it should work.

WG


#3

Yup, that was it. By making the method that the Proc calls
(check_session_expiry) return the value of the callback, the callback
can then halt the filter processing if that is appropriate.

See updated code below:

module ClassMethods
def session_times_out_in(time, opts={})
opts[:after_timeout] = opts[:after_timeout] || nil
class_eval { prepend_before_filter Proc.new { |c|
c.check_session_expiry(time, opts)}, :except => opts[:except] }
end
end

def check_session_expiry(time, opts)
logger.info “::: Checking session expiry”
if session[:expires_at]
if session_has_timed_out?
logger.info “::: Session has expired, resetting session.”
reset_session
unless opts[:after_timeout].nil?
logger.info “::: Calling after timeout callback”

#WG - bug fix so that callback method can halt filter processing.

opts[:after_timeout].call(self) if

opts[:after_timeout].instance_of?(Proc)

self.send(opts[:after_timeout]) if

opts[:after_timeout].instance_of?(Symbol)

return

      return opts[:after_timeout].call(self) if 

opts[:after_timeout].instance_of?(Proc)
return self.send(opts[:after_timeout]) if
opts[:after_timeout].instance_of?(Symbol)
end
else
logger.info “::: Session has not expired. Reinitialising.”
initialize_session_expiry(time)
end
else
“::: Session expiry not initialized”
initialize_session_expiry(time)
end
end

WG