Saturday, March 27, 2010

Supervisor Mode With Authlogic

Supervisor mode is a feature that allows site admins to quickly switch to any other user (say customers) and take a look at the site the same way the customers see it, may be perform some actions from this user, etc.

So here is a simple tip how you do that using the Authlogic plugin for Rails.

First of all you'll need couple new routes, one to switch to some user, another to get back to the admin mode.

map.super_login '/login/:id', :controller => 'user_sessions', :action => 'super'
map.back_login '/login/back', :controller => 'user_sessions', :action => 'back'

I used two new methods named 'super' and 'back', which are not exactly RESTful, but you can use 'edit' and 'update' if feel particularly evil about it. They are normally not used in the 'user_sessions' controller.

After that on the list of customers you add links to switch under this user, for example like that

....
%td= link_to 'Supervision', super_login(user)
....

And finally you'll need those two methods in your `UserSessions` controller

class UserSessions
.....
# switches under this user
def super
raise AccessDenied if !admin?
session[:original_admin_id] = @current_user_session.user.id
@current_user_session = UserSession.create(User.find(params[:id]))
redirect_to '/'
end

# switches back to the admin -mode
def back
raise AccessDenied unless @current_user_session && session[:original_admin_id]
@current_user_session = UserSession.create(User.find(session[:original_admin_id])
session[:original_admin_id] = nil
redirect_to '/'
end
.....
end

The idea is simple, in the first method you stash the original user_id in a session variable, then create new user session with that specific user. And in the second one we restore the original user in the session.

You also might consider to add two methods like `current_user` and `current_user=` in your application controller they are pretty useful and will make your code cleaner.

class ApplicationController
...
# returns the currently logged in user
def current_user
@current_user_session.user if @current_user_session
end

# assigns the currently logged in user
def current_user=(user)
@current_user_session = UserSession.create(user)
end
...
end


That's all. Have fun!

No comments: