2012-02-10 14 views
16

Esto es realmente una pregunta bastante simple pero parece que no puedo encontrar la respuesta. En el Omniauth Overview on Github, en realidad hay una explicación pero no conseguirlo:¿Qué significa ": event =>: authentication" do?

We pass the :event => :authentication to the sign_in_and_redirect method 
to force all authentication callbacks to be called. 

que ya tienen la autenticación de trabajo mediante una acción similar a éste:

def facebook 
    authenticator = UserAuthenticator.new(request.env["omniauth.auth"], current_user) 

    if authenticator.user_authenticated? 
    sign_in_and_redirect authenticator.user, :event => :authentication 
    else 
    session["devise.oauth_data"] = request.env["omniauth.auth"] 
    redirect_to new_user_registration_url 
    end 
end 

Todo lo que realmente quiero saber ¿Para qué sirve :event => :authentication?

Respuesta

20

Me gustaría ayudar a encontrar la respuesta. Seguí el código fuente yo mismo, que me ayudó a entender cómo funciona el parámetro :event => :authentication. Espero que también te ayude

Entonces, la pregunta es ¿por qué

pasar el: Evento =>: autenticación al método sign_in_and_redirect para obligar a todas las devoluciones de llamada de autenticación para ser llamados.

entonces, podemos rastrear la definición.

# Sign in a user and tries to redirect first to the stored location and 
# then to the url specified by after_sign_in_path_for. It accepts the same 
# parameters as the sign_in method. 
def sign_in_and_redirect(resource_or_scope, *args) 
    options = args.extract_options! 
    scope = Devise::Mapping.find_scope!(resource_or_scope) 
    resource = args.last || resource_or_scope 
    sign_in(scope, resource, options) 
    redirect_to after_sign_in_path_for(resource) 
end 

y luego sign_in definir de legado:

# All options given to sign_in is passed forward to the set_user method in warden. 
# The only exception is the :bypass option, which bypass warden callbacks and stores 
# the user straight in session. This option is useful in cases the user is already 
# signed in, but we want to refresh the credentials in session. 
# 
# Examples: 
# 
# sign_in :user, @user      # sign_in(scope, resource) 
# sign_in @user        # sign_in(resource) 
# sign_in @user, :event => :authentication # sign_in(resource, options) 
# sign_in @user, :bypass => true   # sign_in(resource, options) 
# 
def sign_in(resource_or_scope, *args) 
    options = args.extract_options! 
    scope = Devise::Mapping.find_scope!(resource_or_scope) 
    resource = args.last || resource_or_scope 

    expire_session_data_after_sign_in! 

    if options[:bypass] 
    warden.session_serializer.store(resource, scope) 
    elsif warden.user(scope) == resource && !options.delete(:force) 
    # Do nothing. User already signed in and we are not forcing it. 
    true 
    else 
    warden.set_user(resource, options.merge!(:scope => scope)) 
    end 
end 

bien, así :event => :authentication ahora se pasa a warden#set_user, a continuación, su pregunta se convierta en qué

pasar el: Evento =>: la autenticación al método sign_in_and_redirect para forzar todas las devoluciones de llamadas de autenticación.

# Manually set the user into the session and auth proxy 
# 
# Parameters: 
# user - An object that has been setup to serialize into and out of the session. 
# opts - An options hash. Use the :scope option to set the scope of the user, set the :store option to false to skip serializing into the session, set the :run_callbacks to false to skip running the callbacks (the default is true). 
# 
# :api: public 
def set_user(user, opts = {}) 
    scope = (opts[:scope] ||= @config.default_scope) 

    # Get the default options from the master configuration for the given scope 
    opts = (@config[:scope_defaults][scope] || {}).merge(opts) 
    opts[:event] ||= :set_user 
    @users[scope] = user 

    if opts[:store] != false && opts[:event] != :fetch 
    options = env[ENV_SESSION_OPTIONS] 
    options[:renew] = true if options 
    session_serializer.store(user, scope) 
    end 

    run_callbacks = opts.fetch(:run_callbacks, true) 
    manager._run_callbacks(:after_set_user, user, self, opts) if run_callbacks 

    @users[scope] 
end 

opta [: evento] puede ser [:set_user, :fetch, :authentication]

# Hook to _run_callbacks asserting for conditions. 
def _run_callbacks(kind, *args) #:nodoc: 
    options = args.last # Last callback arg MUST be a Hash 

    send("_#{kind}").each do |callback, conditions| 
    invalid = conditions.find do |key, value| 
     value.is_a?(Array) ? !value.include?(options[key]) : (value != options[key]) 
    end 

    callback.call(*args) unless invalid 
    end 
end 

# A callback hook set to run every time after a user is set. 
# This callback is triggered the first time one of those three events happens 
# during a request: :authentication, :fetch (from session) and :set_user (when manually set). 
# You can supply as many hooks as you like, and they will be run in order of decleration. 
# 
# If you want to run the callbacks for a given scope and/or event, you can specify them as options. 
# See parameters and example below. 
# 
# Parameters: 
# <options> Some options which specify when the callback should be executed 
# scope - Executes the callback only if it maches the scope(s) given 
# only - Executes the callback only if it matches the event(s) given 
# except - Executes the callback except if it matches the event(s) given 
# <block> A block where you can set arbitrary logic to run every time a user is set 
# Block Parameters: |user, auth, opts| 
#  user - The user object that is being set 
#  auth - The raw authentication proxy object. 
#  opts - any options passed into the set_user call includeing :scope 
# 
# Example: 
# Warden::Manager.after_set_user do |user,auth,opts| 
#  scope = opts[:scope] 
#  if auth.session["#{scope}.last_access"].to_i > (Time.now - 5.minutes) 
#  auth.logout(scope) 
#  throw(:warden, :scope => scope, :reason => "Times Up") 
#  end 
#  auth.session["#{scope}.last_access"] = Time.now 
# end 
# 
# Warden::Manager.after_set_user :except => :fetch do |user,auth,opts| 
#  user.login_count += 1 
# end 
# 
# :api: public 
def after_set_user(options = {}, method = :push, &block) 
    raise BlockNotGiven unless block_given? 

    if options.key?(:only) 
    options[:event] = options.delete(:only) 
    elsif options.key?(:except) 
    options[:event] = [:set_user, :authentication, :fetch] - Array(options.delete(:except)) 
    end 

    _after_set_user.send(method, [block, options]) 
end 

así,

# after_authentication is just a wrapper to after_set_user, which is only invoked 
# when the user is set through the authentication path. The options and yielded arguments 
# are the same as in after_set_user. 
# 
# :api: public 
def after_authentication(options = {}, method = :push, &block) 
    after_set_user(options.merge(:event => :authentication), method, &block) 
end 
12

Pasando :event => :authentication provoca Warden (subyacente Devise) para activar cualquier devoluciones de llamada definidas con:

Warden::Manager.after_authentication do |user,auth,opts| 
    # Code triggered by authorization here, for example: 
    user.last_login = Time.now 
end 

Si no usa ninguna devolución de llamada after_authentication, y está seguro de que sus bibliotecas tampoco lo son, no le será de utilidad inmediata. Como es un evento de autenticación, lo dejo, ahora que sabes para qué es potencialmente útil.