简体   繁体   中英

w Devise, how to allow a SignIn user to sign in as another user

My app auto-creates a guest user account. The problem there is that the guest user may want to sign-in to the real account.

I therefore want to let users Sign In that are already signed_in? according to devise.

While I can render the form, if I submit the signin form, devise kicks it to a redirect:

Started POST "/users/sign_in" for 127.0.0.1 at 2011-07-19 18:21:45 -0700
  Processing by Devise::SessionsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"RE/xxx=", "user"=>{"email"=>"sally.jones@gmail.com", "password"=>"[FILTERED]", "remember_me"=>"1"}, "commit"=>"Sign In"}
  User Load (0.6ms)  SELECT "users".* FROM "users" WHERE "users"."id" = 102 LIMIT 1
Redirected to http://localhost:3000/
Completed 302 Found in 266ms

Update

I tried:

class SessionsController < Devise::SessionsController

  def create
    Rails.logger.info 'XXXXX 2'
    super
    Rails.logger.info 'XXXXX 4'
  end

end

But devise seems to be kicking out the request before it even hits that method and the logger's aren't in the log file

Any ideas on how I can allow a signed_in user to sign in?

Devise has support for switching to another user using the sign_in method. https://github.com/plataformatec/devise/wiki/How-To:-Sign-in-as-another-user-if-you-are-an-admin . It also has the concept of Guest user: https://github.com/plataformatec/devise/wiki/How-To:-Create-a-guest-user

Well if you create an account automatically, does that mean your current_{resource} is gonna return an user? if so its normal that devise redirects you from sign_in and sign_up routes(if you see the source code there is a prepend_before_filter:require_no_authentication ).

That's to explain the redirect... now to solve your problem to have to extend the controllers and create a before filter with require authentication only for non guest users.

Take attention to this:

In https://github.com/plataformatec/devise/blob/master/app/controllers/devise_controller.rb

there is the definition of require_no_authentication, which does a little bit more than verifying if your user is authenticated. so got add another before filter just for guest_users

For example:

PS Everywhere you read {resource} is the name of your model class. If User then user, if Profile then profile, attention to downcasing.

class RegistrationsController < Devise::RegistrationsController
  before_filter :require_no_authentication, :unless => :guest_user?, :only => [:new,:create, :cancel]
  before_filter :require_no_authentication_for_guests, :if => :guest_user?, :only => [:new,:create, :cancel]

  private

  def guest_user?
    current_{resource}.is_guest?
  end

  def require_no_authentication_for_guests
    assert_is_devise_resource!
  end 
end

On your model:

Class {resource}
  def is_guest?
    # here you put the code that distinguishes a guest user which should return true if its one>
  end
end

also need to change the routes file:

if your registrations controller is called like in the example and the if the resource is user

devise_for :users, :controllers => {:sessions => "sessions",
                                  :registrations => "registrations"}

Then you do the same on your sessions controller. by that I mean to apply the same before filters on a custom sessions controller.

Attention where you wanna apply the before filter and examine your requirements before.

Did it help?

https://github.com/code-and-effect/effective_website/blob/develop/app/controllers/users/impersonations_controller.rb

this functionality “impersonating another user”. an admin can go onto Admin::Users#index -> Find a user, and impersonate them. That is, sign into their account.need a button that posts to this action

https://github.com/code-and-effect/effective_website/blob/develop/app/controllers/admin/users_controller.rb#L11

def impersonate
    @user = User.find(params[:id])
    authorize! :impersonate, @user
    # Impersonate
    session[:impersonation_user_id] = current_user.id
    expire_data_after_sign_in!
    warden.session_serializer.store(@user, Devise::Mapping.find_scope!(@user))
    redirect_to(root_path)
  end
  before_action :authenticate_user!
  skip_authorization_check only: [:destroy]
  def destroy
    @user = User.find(session[:impersonation_user_id])
    # Reset impersonation
    session[:impersonation_user_id] = nil
    expire_data_after_sign_in!
    warden.session_serializer.store(@user, Devise::Mapping.find_scope!(@user))
    redirect_to(admin_users_path)
  end
end

Which uses devise, to set the session[:impersonation_user_id] so later you know you are impersonating another use, and then this warden.session_serializer.store which signs you in as a new user. If you close the tab. Reopen the tab. You will still be impersonating that user. Put a partial in the site (haml) to display an alert to the user on every page when they're impersonating

  .bg-warning.d-print-none.text-center
    You are logged in as <strong>#{current_user}</strong>.
    = link_to 'click here', impersonate_path, 'data-method': :delete
    to return to your original account.

https://github.com/code-and-effect/effective_website/blob/develop/app/views/layouts/_impersonate.html.haml

you can do 2 actions. The first does sign out and redirect to the second one that initiate a new seesion by another user

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM