Commit 4e3fbf5d320a875de1c61299ad65772c5bef7616

Refactorize session authentication methods. Support calling them from other controllers beyond SessionsController
  
1212 end
1313
1414 def create
15 authentication_methods_chain(:create)
16
17 unless performed?
18 flash[:error] = t(:invalid_credentials)
19 render(:action => "new")
15 if authentication_methods_chain(:create)
16 redirect_back_or_default(after_create_path) if ! performed?
17 else
18 unless performed?
19 flash[:error] ||= t(:invalid_credentials)
20 render(:action => "new")
21 end
2022 end
2123 end
2224
2325 def destroy
2426 authentication_methods_chain(:destroy)
27
2528 reset_session
2629
2730 return if performed?
  
1010 module Sessions
1111 class << self
1212 def included(base) # :nodoc:
13 base.send :include, ActionController::Authentication unless base.ancestors.include?(ActionController::Authentication)
13 base.__send__ :include, ActionController::Authentication unless base.ancestors.include?(ActionController::Authentication)
1414
1515 ActiveRecord::Agent.authentication_methods.each do |method|
1616 mod = "ActionController::Sessions::#{ method.to_s.classify }".constantize
17 base.send :include, mod
17 base.__send__ :include, mod
1818 end
1919 end
2020 end
2121
22 # Go through all authentication methods definded for this action
23 # Return is one of them is performed
24 def authentication_methods_chain(controller_method_name)
22 # Authentication is supported in several ways; Login and password, OpenID, CAS, etc...
23 #
24 # Each of the modules define methods that should be called in each session stage: new, create, destroy.
25 #
26 # authentication_methods_chain evaluates each of the available methods, trying to authenticate one of the Agent classes.
27 #
28 # When one of the method performs the action, the chain stops. This is typical for redirections, like in OpenID.
29 #
30 # The chain is evaluated while the methods return nil.
31 #
32 # The chain is stopped when one of the methods returns an object. In the case of create, this object is the authenticated Agent.
33 #
34 #
35 def authentication_methods_chain(controller_method_name, &block)
2536 authentication_methods.each do |authentication_method|
26 chain_method = "#{ controller_method_name }_with_#{ authentication_method }"
27 send(chain_method) if respond_to?(chain_method)
37 chain_method = "#{ controller_method_name }_session_with_#{ authentication_method }"
38
39 # Only call existing authentication methods
40 next unless respond_to?(chain_method)
41
42 # Evaluate this authentication method
43 auth_response = __send__(chain_method)
44
45 # End if the method has performed the renderization
2846 break if performed?
47
48 # Return auth_response if authentication was successful
49 return auth_response if auth_response
2950 end
51
52 # If we reach here, none of the authentication methods succeeded
53 nil
3054 end
3155
3256 private
  
1010 # Central Authentication Service (CAS) session support
1111 module CAS
1212 # Initialize CAS session
13 def new_with_cas
13 def new_session_with_cas
1414 initialize_cas_filter
1515
1616 cas_filter_result = ::CASClient::Frameworks::Rails::Filter.filter(self)
2323 end
2424
2525 # Create session using CAS
26 def create_with_cas
27 return unless params[:ticket]
26 def create_session_with_cas
27 return nil unless params[:ticket]
2828 initialize_cas_filter
2929
3030 if ::CASClient::Frameworks::Rails::Filter.filter(self)
3737
3838 if authenticated?
3939 flash[:success] = t(:logged_in_successfully)
40 redirect_back_or_default(after_create_path)
40 return self.current_agent
4141 else
4242 redirect_to :controller => ActiveRecord::Agent.authentication_classes(:cas).first.to_s.tableize,
4343 :action => "new",
5151 end
5252
5353 # Logout on CAS Server
54 def destroy_with_cas
54 def destroy_session_with_cas
5555 initialize_cas_filter
5656
5757 redirect_to ::CASClient::Frameworks::Rails::Filter.client.logout_url(nil, request.referer)
  
55 # CookieToken remembers the Autnentication in the browser for certain amount of time
66 module CookieToken
77 # Destroy CookieToken Session data
8 def destroy_with_cookie_token
8 def destroy_session_with_cookie_token
99 current_agent.forget_me if authenticated?
1010 cookies.delete :auth_token
11 nil
1112 end
1213 end
1314 end
  
33 # Methods for Sessions based on LoginAndPassword Authentication
44 module LoginAndPassword
55 # Init Session using LoginAndPassword Authentication
6 def create_with_login_and_password
6 def create_session_with_login_and_password(params = self.params)
77 return if params[:login].blank? || params[:password].blank?
88
99 agent = nil
1919 elsif agent.respond_to?(:disabled) && agent.disabled
2020 flash[:error] = t(:disabled, :scope => agent.class.to_s.tableize)
2121 else
22 self.current_agent = agent
2322 flash[:success] = t(:logged_in_successfully)
24 redirect_back_or_default(after_create_path)
25 return
23 return self.current_agent = agent
2624 end
2725 else
2826 flash[:error] ||= t(:invalid_credentials)
2927 end
30 render :action => 'new'
28 return
3129 end
3230 end
3331 end
  
1010 # OpenID sessions management
1111 module OpenID
1212 # Create new Session using OpenID
13 def create_with_openid
14 if !params[:openid_identifier].blank?
13 def create_session_with_openid(params = self.params, options = {})
14 options[:return_to] ||= open_id_complete_url
15 options[:realm] ||= "http://#{ request.host_with_port }/"
16 options[:sreg_fields] ||= ['nickname', 'email']
17
18 if params[:openid_identifier].present?
1519 begin
1620 openid_request = openid_consumer.begin params[:openid_identifier]
1721 rescue ::OpenID::OpenIDError => e
1822 flash[:error] = t('openid.client.discovery_failed', :id => params[:openid_identifier], :error => e)
19 render :action => "new"
2023 return
2124 end
2225
2326 sreg_request = ::OpenID::SReg::Request.new
2427 # required fields
25 sreg_request.request_fields(['nickname', 'email'], true)
28 sreg_request.request_fields(options[:sreg_fields], true)
2629 # optional fields
2730 # sreg_request.request_fields(['fullname'], false)
2831
3434 # papereq = ::OpenID::PAPE::Request.new
3535 # ...
3636
37 return_to = open_id_complete_url
38 realm = "http://#{ request.host_with_port }/"
39
40 if openid_request.send_redirect?(realm, return_to)
41 redirect_to openid_request.redirect_url(realm, return_to)
37 if openid_request.send_redirect?(options[:realm], options[:return_to])
38 redirect_to openid_request.redirect_url(options[:realm], options[:return_to])
4239 else
40 #FIXME: create
4341 @form_text = openid_request.form_markup(realm, return_to, true, { 'id' => 'openid_form' })
4442 render :layout => nil
4543 end
4646 # Filter path parameters
4747 parameters = params.reject{ |k,v| request.path_parameters[k] }
4848 # Complete the OpenID verification process
49 openid_response = openid_consumer.complete(parameters, return_to)
49 openid_response = openid_consumer.complete(parameters, options[:return_to])
5050
5151 case openid_response.status
5252 when ::OpenID::Consumer::SUCCESS
5757 if authenticated? && ! current_agent.openid_uris.include?(uri)
5858 current_agent.openid_uris << uri
5959 flash[:notice] = t(:id_attached_to_account, :id => uri)
60 return
60 return current_agent
6161 end
6262
6363 ActiveRecord::Agent.authentication_classes(:openid).each do |klass|
6767 end
6868
6969 if authenticated?
70 redirect_back_or_default after_create_path
70 # redirect_back_or_default after_create_path
7171 flash[:success] = t(:logged_in_successfully)
72 return current_agent
7273 else
7374 # We create new local Agent with OpenID data
7475 session[:openid_identifier] = openid_response.display_identifier
8484 flash[:error] = openid_response.display_identifier ?
8585 t('openid.client.verification_failed_with_id', :id => openid_response.display_identifier, :message => openid_response.message) :
8686 t('openid.client.verification_failed', :message => openid_response.message)
87 render :action => 'new'
87 return
8888 when ::OpenID::Consumer::SETUP_NEEDED
89 flash[:error] = t(:immediate_request_failed)
90 render :action => 'new'
89 flash[:error] = t('openid.client.immediate_request_failed')
90 return
9191 when ::OpenID::Consumer::CANCEL
92 flash[:notice] = t(:transaction_cancelled)
93 render :action => 'new'
92 flash[:error] = t('openid.client.transaction_cancelled')
93 return
9494 end
9595 end
9696 end