简体   繁体   中英

Devise: How to redirect to the previous page after login, but only if previous page requires authentication?

Using the Devise gem, how can I redirect to the previous page after login, but only if the previous page requires authentication (otherwise redirect to a specific page I define)?

Required scenarios:

  • Try to access /my-private-account > Devise detects authentication required and redirects to login > Successfully login > redirect to /my-private-account
  • Visit / (doesn't require authentication) > visit /login > Successfully login > redirect to specific page eg. /dashboard
  • Visit /about (doesn't require authentication) > visit /login > Successfully login > redirect to /dashboard

This is almost covered by the Devise Wiki , but their answer redirects back for ALL pages. Eg. from / (doesn't require authentication) > visit /login > Successfully login > redirects back to /

My authentication is defined in routes:

# routes.rb
authenticate :user do
  resources :events
end
# application_controller.rb
class ApplicationController < ActionController::Base
  before_action :store_user_location!, if: :storable_location?

  private
    # Redirect back to current page after sign in
    # ref: https://github.com/heartcombo/devise/wiki/How-To:-Redirect-back-to-current-page-after-sign-in,-sign-out,-sign-up,-update
    def storable_location?
      request.get? && is_navigational_format? && !devise_controller? && !request.xhr? 
    end

    def store_user_location!
      # :user is the scope we are authenticating
      store_location_for(:user, request.fullpath)
    end

    def after_sign_in_path_for(resource)
      stored_location_for(resource) || dashboard_path
    end

end

Is there a way I can check whether a route requires authentication? Then I could override after_sign_in_path_for eg.

def after_sign_in_path_for(resource)
  if stored_location_for(resource).requires_authentication? # something like this...?
    stored_location_for(resource)
  else
    events_path
  end
end

Or am I tackling this in the wrong direction and is there a better way?

Lastly, is there anything else I need to be aware of to make this work for omniauth too?

I think what you actually need to override is the storable_location? method so you don't store locations you don't want to go back.

For example, in the controller that handles the / or /about routes, you could override that storable_location? method to always return false so those locations are not stored, then stored_location_for won't be set.

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