Comments (13)
This issue brought me here and I got inspired by @WojtekKruszewski and ended up writing my own to work with devise. Here is my controller
class MasqueradeController < ApplicationController
authorize_resource class: false
before_filter :authorize_masquerade!
def start
session[:original_user_id] = current_user.id
sign_in(:user, User.find(params[:user_id]))
redirect_to root_url
end
def stop
sign_in(:user, User.find(session[:original_user_id]))
session.delete(:original_user_id)
redirect_to root_url
end
private
def authorize_masquerade!
user = session[:original_user_id] ? User.find_by(id: session[:original_user_id]) : current_user
redirect_to root_path unless user && user.role?(:admin)
end
end
Just check the session token in the view with erb if you should show the token.
from switch_user.
Hi David, you've got a couple of choices.
- Adjust which users are showing up in the list by configuring
SwitchUser.available_users
- Use the switch back feature by sending http requests yourself.
If you want to use 2. The switch back feature is use by:
- Telling the server you want to remember the current user by sending an http request to
/switch_user/remember_user?remember=1
- Now
SwitchUserController#available?
will consider this remembered user as well as the current user. That's how we know whether to let you continue to use switch user even if devise (or whatever your current authentication provider is) thinks you're a user which might not normally have access to switch user (eg a customer account).
from switch_user.
Is it correct that the only way to remember the original user is to make a distinct request ahead of switching?
My use case is fairly straightforward in that I want to facilitate admins signing in as other users and then back again. Our user database has a few tens of thousands of records, so a dropdown doesn't work, and instead I am using a small form with a text field with user ID. However since I need to send a request to #remember_user
first, this form in itself is inadequate.
I've tried hacking around this. Ideally, I could switch users and remember the original user in a single request, e.g. /switch_user?scope_identifier=user_1234&remember=true
. In some ways I feel that the remember=true
is overly explicit. I know that there are security concerns here, but respectfully the idea that I have to sign out to resume my original user is counter-intuitive to me. If there is rationale that I am overlooking for why this approach would be inadvisable, please correct me :)
from switch_user.
I think what you might be missing is how we know whether to let you switch back or not. If you switch to a customer all I would know, without remembering that you were an admin before, is that you're a customer. We don't show customers the switch_user select box, so you're now locked out.
from switch_user.
I still don't understand why we can't (or wouldn't want to) remember the original user and switch users in a single request.
from switch_user.
You definitely could, I didn't realize that's what you were asking. The feature was added with a little haste, but I'm sure it could be refactored.
from switch_user.
Given my longwinded-ness, I probably didn't realize it was what I was asking either, heh. I just wanted to know if there was a security concern that prevented such an implementation. I will look into making such adjustments.
from switch_user.
I stumbled across the same issue and couldn't understand why there wasn't a single entry point remembering and switching. I already had a case where I wanted to pass the redirect path via the url so my redirect path already looked like this:
config.redirect_path = lambda { |request, params| params[:path].presence || request.referrer || '/' }
My link to become a user looks like this (in HAML):
- next_path = ERB::Util.url_encode("/switch_user?scope_identifier=user_#{@user.id}&path=/")
= link_to "Login as #{@user.full_name}", "/switch_user/remember_user?remember=true&path=#{next_path}"
The return path looks like this
- original_user = user_signed_in? && SwitchUser::Provider.init(controller).original_user
- if original_user
- next_path = ERB::Util.url_encode "/switch_user/remember_user?remember=false&path=#{ops_user_path(current_user.id)}"
= link_to "Back to #{original_user.simple_name}", "/switch_user?scope_identifier=user_#{original_user.id}&path=#{next_path}"
Maybe this will help. Seems to work for me. Still wouldn't mind a more direct way of doing this.
from switch_user.
I agree with the others that a switch-back feature would be ideal. I don't care about the user being able to switch to a third user, just switching back to their original admin account.
I tried implementing Helloenvoy's recommendation but ran into issues because I have a wildcard route that interferes with manually linking to the "/switch_user/remember_user" path. I could probably dig into the source code to figure out what controller action handles that and manually add a route, but for now I'll just force the admin to sign out and back in again.
from switch_user.
I added a patch that allows one to disable the default routes. I then just extended the default controller to handle a single request for remembering and switching. It seems to work. There's probably more elegant ways to get it done, but it works for me.
_widget.html.erb
<u>Login as another user</u>
<%= form_tag users_switch_user_path, method: :get, class: 'form' do %>
<div class="form-group">
<%= label_tag 'scope_identifier', 'User', class: 'sr-only' %>
<%= select_tag 'scope_identifier', options_from_collection_for_select(options, :scope_id, :label, current_scope), class: 'form-control' %>
</div>
<% if SwitchUser.switch_back %>
<div class="checkbox">
<%= label_tag 'remember' do %>
<% concat check_box_tag 'remember', 'true', provider.original_user.present? %>
<% concat 'Log me back in when I am done' %>
<% end %>
</div>
<% end %>
<button type="submit" class="btn btn-default">Switch to User</button>
<% end %>
users/switch_user_controller.rb
class Users::SwitchUserController < SwitchUserController
def set_current_user
if params[:remember] == 'true'
remember_user
handle_request(params)
else
super
end
end
end
Lastly, to support the notion of 'switch back', I just overrode devise's sessions controller to sign in the original user upon destroy.
users/sessions.rb
class Users::SessionsController < Devise::SessionsController
def destroy
su_provider = SwitchUser::Provider.init(self)
original_user = su_provider.original_user
super
if original_user
sign_in original_user
end
end
end
from switch_user.
@jhenkens can you submit a pull request?
from switch_user.
@WojtekKruszewski The ability to disable the routes (and thus, allow you to definite your own routes, replacing the controller) was pulled in via PR with 6759686. Everything else I did that I detailed above was personal changes within the directory of my own application, not within the gem itself.
from switch_user.
Actually, only now I realized warden.set_user(new_user, :scope => :user)
in the controller is all it takes to switch user. I removed switch_user gem and added some custom code for my existing admin infrastructure. 50 lines, including a big red button reminding that you're logged in as someone else and allowing switching back. Still, switch_user gem saved me some time and distraction a year ago when I started the project, so thank you @lcowell.
from switch_user.
Related Issues (20)
- before_action not defined in Rails 3 HOT 4
- no instructions for API applications HOT 2
- installed the gem attempted to use the hamle switch_user_select HOT 5
- Current_user and true_user. HOT 4
- Example site has failing SSL cert
- devise_for :admin_users makes current_user always nil in SwitchUser config HOT 1
- Rails 6 deprecation warning 'Initialization autoloaded the constant SwitchUserHelper' HOT 5
- Accessing `original_user` seems to be broken HOT 1
- Switching to another user causes a duplicate request HOT 1
- Conditional redirect_path Based on Current User. HOT 1
- form_user is invalid and is not listed in SwitchUser#available_users HOT 2
- loader returen array and throws error: undefined method `where' for #<Array:0x000000086f88c8> HOT 14
- grouped_options_for_select bug for rails 3.2
- Need to add route for remember_me when wildcarding routes HOT 1
- Opt out of "don't store sign in ip and sign in timestamp when switching user" HOT 1
- original_user is nill HOT 4
- Add helper for logout to origin user HOT 2
- Problem in controller_guard block HOT 3
- Switch User Select Box = Nil HOT 1
- Release new version with relative_url_root support HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from switch_user.