views:

382

answers:

4

I have several actions that are protected by filters that check for logged_in? and admin? and spit out 401 or 403 errors respectively if the tests fail. What's a good way of getting around these filters in development mode only so I can test out my app?

I can't go through the actual login procedure because it relies on infrastructure I don't have access to during development.

I'd also like to be able to check that the 401s and 403s properly, so I don't want to just turn all the auth filters off completely. And I want it defined in as few places as possible so I don't accidentally let the world bypass the filters in production.

Has anyone found a good overriding mechanism? Some ideas I've come up with:

  • add a check for params[:logged_in] && RAILS_ENV =~ /dev/ and params[:admin] && RAILS_ENV =~ /dev/ in the filters respectively. That works for GETs, but I have to add extra hidden fields to all my forms and my AJAX requests.
  • add a link available in devevelopment mode only that mocks a login as a regular user or as an admin. This seems to be a better option all around.
A: 

On development add a script to the environment that mocks the real authentication framework, or redefine the basic functionality (such as an #is_logged_in method) to always return ture, that way you just change the part that's different between environments anyway.

krusty.ar
+1  A: 

You could add some code the auth functions that return true if in development.

   def logged_in?
     return true if Rails.env.development?
     ... etc
   end
Toby Hede
True, but then I can't test the real functionality during development. That's what I was suggesting in my first bullet.
James A. Rosen
+2  A: 

You need two things when you're doing this:

  1. An alternate way to pass in authentication information during development, and
  2. A way to ensure that this is turned off in production.

The second I usually do with some sort of switch in a configuration file that defaults to "off." But you could also just check for the existence of a file with a special name, or whatever suits your fancy. Just to make truly sure that this never gets turned on for production, you might also add further checks, such as refusing to enable it when the server is running as a certain user (if you have a specific user name under which you run the production systems), or refusing to use it if the request does not come from the localhost address.

As for what you do, you've got lots of options. You could read the information from a file that the developer edits to his taste (YAML is a nice format for this, and the existence of the file itself can serve as the switch to turn this on. You could also include the authorized IP address in this file if you really need to test from a host other than localhost). If you've got a browser plug-in such as Web Developer for Firefox, setting headers is easy, and that also can be very handy for functional tests through HTTP. Adding extra parameters to the URL is popular, but I don't find that so convenient myself.

Once you've got the authentication information flowing in, then all you need to do is pick the appropriate point at which to insert mock objects instead of the real ones that communicate with the authentication system that's not available to you in development. If you don't have such a location now, you'll have to refactor your code to create it.

Curt Sampson
Mislav Marohnić has a neat twist on this: http://mislav.uniqpath.com/rails/haxor-backdoor-in-development/That way, you get auto-logged-in, but only if you GET the form for logging in (say, /login.html).
James A. Rosen
A: 

In config/environments you have scripts for each environment that allow you to apply environment-specific settings.

If those settings are applied late enough in the Rails boot process then I'd consider overriding the relevant aspects of your authentication mechanism there. This avoids having development-specific code in your production application, which seems like a good idea to me!

Mike Woodhouse