Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Ever wondered how to login as another user within Devise?
- Recently we had a feature request that would provide Admins with the ability
- to sign is as another user. You could imagine live demonstrations or even production
- support calls where you would like to be signed in as another user, yet not
- have to ask for or decrypt their current password. After stewing for a bit, we found a
- pretty nice solution with Devise.
- Here's the Cucumber feature...
- Feature: Sign in as another user
- As an admin
- I want to sign in as another user
- Scenario: Admin can sign in as another user
- Given I am logged in as an admin user
- And a user: "bob" exists with email: "bob@example.com", password: "password", ...
- When I go to the admin users page
- And I follow the "Sign in as" link for user: "bob"
- Then I should see "Welcome Bob"
- The trick was to store the admin info within the rack session.
- request.env['rack.session']['devise.remember_admin_user_id']
- We decided on using a Rails 3 concern to keep our actual strategy clean.
- require 'devise/strategies/base'
- module SignInAs
- module Concerns
- module RememberAdmin
- extend ActiveSupport::Concern
- private
- def remember_admin_id
- request.env['rack.session']['devise.remember_admin_user_id']
- end
- def remember_admin_id=(id)
- request.env['rack.session']['devise.remember_admin_user_id'] = id
- end
- def remember_admin_id?
- request.env['rack.session'] && request.env['rack.session']['devise.remember_admin_user_id'].present?
- end
- def clear_remembered_admin_id
- request.env['rack.session']['devise.remember_admin_user_id'] = nil
- end
- end
- end
- end
- The above really makes writing the Devise strategy fairly easy.
- require 'devise/strategies/base'
- module SignInAs
- module Devise
- module Strategies
- class FromAdmin < ::Devise::Strategies::Base
- include SignInAs::Concerns::RememberAdmin
- def valid?
- remember_admin_id?
- end
- def authenticate!
- resource = User.find(remember_admin_id)
- if resource
- clear_remembered_admin_id
- success!(resource)
- else
- pass
- end
- end
- end
- end
- end
- end
- Then we just wire in our new strategy.
- Warden::Strategies.add(:sign_in_as, SignInAs::Devise::Strategies::FromAdmin)
- Lastly, here's our sign-in-as controller which sets the Devise session variable.
- class SignInAsController < ApplicationController
- include SignInAs::Concerns::RememberAdmin
- layout 'admin/application'
- def create
- if can?(:manage, :users)
- self.remember_admin_id = current_user.id
- sign_in :user, User.find(params[:user_id])
- end
- redirect_to '/admin'
- end
- end
- That's it, pretty neat and might make for a nice Gem or Devise addition.
Add Comment
Please, Sign In to add comment