简体   繁体   中英

Testing if a user just logged in with Devise

I want to include a user's authentication_token in my JSON response if they just logged in so that a consumer of my API can keep track of it and authenticate future requests. But I do not want to include the token otherwise. I am using Active Model Serializers to customize my JSON output:

class UserSerializer < ActiveModel::Serializer
  attributes :id, :email, :authentication_token

  def include_authentication_token?
    # what to put here?
  end
end

The Devise session controller uses respond_with resource where resource is the logged-in user, so by default it will use the UserSerializer. I could customize the Devise controller, but I would rather use include_authentication_token? . Is there some method in Devise that will return true when a User just logged in (ie, the response is coming from Devise::SessionsController)?

While the current Request is not automatically available within your subclass of ActiveModel::Serializer , you can easily pass it into the serializer's options hash by including it in your call to UserSerializer.new .

If you explicitly create your serializer like:

UserSerializer.new(@user, scope: current_user)

That means you can simply pass a second option called request :

UserSerializer.new(@user, scope: current_user, request: request)

From then on, you can access the current Request in your serializer by calling options[:request] . For example, to inspect the current controller inside UserSerializer , simply check the value of

options[:request].params[:controller]

If it comes up as "devise/sessions" , you're OK to include the token. Otherwise, if you're using the standard Devise controllers to handle sign-ins, you'll probably have to subclass Devise::SessionsController and reroute sign-ins to your new controller:

# app/controllers/sessions_controller.rb
class SessionsController < Devise::SessionsController
  def create
    self.resource = warden.authenticate!(auth_options)
    set_flash_message(:notice, :signed_in) if is_navigational_format?
    sign_in(resource_name, resource)
    respond_with resource, location: after_sign_in_path_for(resource), request: request
  end
end

# config/routes.rb
devise_scope :user do
  post "sign_in" => "sessions#create", as: :user_session
end

Please note I haven't tested this yet. In reading the source for ActionController::MimeResponds#respond_with , it appears that any options given to #respond_with will be passed downward to the responder, which is hijacked by ActionController::Serialization and it looks like the options are passed all the way into the resource 's Serializer.

Good luck!

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