Giter VIP home page Giter VIP logo

Comments (13)

DavidMMelin avatar DavidMMelin commented on July 27, 2024 6

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.

lcowell avatar lcowell commented on July 27, 2024

Hi David, you've got a couple of choices.

  1. Adjust which users are showing up in the list by configuring SwitchUser.available_users
  2. Use the switch back feature by sending http requests yourself.

If you want to use 2. The switch back feature is use by:

  1. Telling the server you want to remember the current user by sending an http request to /switch_user/remember_user?remember=1
  2. 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.

 avatar commented on July 27, 2024

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.

lcowell avatar lcowell commented on July 27, 2024

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.

 avatar commented on July 27, 2024

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.

lcowell avatar lcowell commented on July 27, 2024

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.

 avatar commented on July 27, 2024

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.

 avatar commented on July 27, 2024

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.

kevinvangelder avatar kevinvangelder commented on July 27, 2024

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.

jhenkens avatar jhenkens commented on July 27, 2024

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.

wkrsz avatar wkrsz commented on July 27, 2024

@jhenkens can you submit a pull request?

from switch_user.

jhenkens avatar jhenkens commented on July 27, 2024

@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.

wkrsz avatar wkrsz commented on July 27, 2024

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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.