Guest User

Untitled

a guest
May 13th, 2018
194
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.81 KB | None | 0 0
  1. Ever wondered how to login as another user within Devise?
  2.  
  3. Recently we had a feature request that would provide Admins with the ability
  4. to sign is as another user. You could imagine live demonstrations or even production
  5. support calls where you would like to be signed in as another user, yet not
  6. have to ask for or decrypt their current password. After stewing for a bit, we found a
  7. pretty nice solution with Devise.
  8.  
  9. Here's the Cucumber feature...
  10.  
  11. Feature: Sign in as another user
  12. As an admin
  13. I want to sign in as another user
  14.  
  15. Scenario: Admin can sign in as another user
  16. Given I am logged in as an admin user
  17. And a user: "bob" exists with email: "bob@example.com", password: "password", ...
  18. When I go to the admin users page
  19. And I follow the "Sign in as" link for user: "bob"
  20. Then I should see "Welcome Bob"
  21.  
  22. The trick was to store the admin info within the rack session.
  23.  
  24. request.env['rack.session']['devise.remember_admin_user_id']
  25.  
  26. We decided on using a Rails 3 concern to keep our actual strategy clean.
  27.  
  28. require 'devise/strategies/base'
  29.  
  30. module SignInAs
  31. module Concerns
  32. module RememberAdmin
  33. extend ActiveSupport::Concern
  34.  
  35. private
  36.  
  37. def remember_admin_id
  38. request.env['rack.session']['devise.remember_admin_user_id']
  39. end
  40.  
  41. def remember_admin_id=(id)
  42. request.env['rack.session']['devise.remember_admin_user_id'] = id
  43. end
  44.  
  45. def remember_admin_id?
  46. request.env['rack.session'] && request.env['rack.session']['devise.remember_admin_user_id'].present?
  47. end
  48.  
  49. def clear_remembered_admin_id
  50. request.env['rack.session']['devise.remember_admin_user_id'] = nil
  51. end
  52. end
  53. end
  54. end
  55.  
  56. The above really makes writing the Devise strategy fairly easy.
  57.  
  58. require 'devise/strategies/base'
  59.  
  60. module SignInAs
  61. module Devise
  62. module Strategies
  63. class FromAdmin < ::Devise::Strategies::Base
  64. include SignInAs::Concerns::RememberAdmin
  65.  
  66. def valid?
  67. remember_admin_id?
  68. end
  69.  
  70. def authenticate!
  71. resource = User.find(remember_admin_id)
  72. if resource
  73. clear_remembered_admin_id
  74. success!(resource)
  75. else
  76. pass
  77. end
  78. end
  79. end
  80. end
  81. end
  82. end
  83.  
  84.  
  85. Then we just wire in our new strategy.
  86.  
  87. Warden::Strategies.add(:sign_in_as, SignInAs::Devise::Strategies::FromAdmin)
  88.  
  89.  
  90. Lastly, here's our sign-in-as controller which sets the Devise session variable.
  91.  
  92. class SignInAsController < ApplicationController
  93. include SignInAs::Concerns::RememberAdmin
  94.  
  95. layout 'admin/application'
  96.  
  97. def create
  98. if can?(:manage, :users)
  99. self.remember_admin_id = current_user.id
  100. sign_in :user, User.find(params[:user_id])
  101. end
  102.  
  103. redirect_to '/admin'
  104. end
  105.  
  106. end
  107.  
  108. That's it, pretty neat and might make for a nice Gem or Devise addition.
Add Comment
Please, Sign In to add comment