diff options
Diffstat (limited to 'actionpack/lib/action_controller/session_management.rb')
-rw-r--r-- | actionpack/lib/action_controller/session_management.rb | 174 |
1 files changed, 48 insertions, 126 deletions
diff --git a/actionpack/lib/action_controller/session_management.rb b/actionpack/lib/action_controller/session_management.rb index 60a9aec39c..dd5001d328 100644 --- a/actionpack/lib/action_controller/session_management.rb +++ b/actionpack/lib/action_controller/session_management.rb @@ -3,8 +3,29 @@ module ActionController #:nodoc: def self.included(base) base.class_eval do extend ClassMethods - alias_method_chain :process, :session_management_support - alias_method_chain :process_cleanup, :session_management_support + end + end + + class Middleware + DEFAULT_OPTIONS = { + :path => "/", + :key => "_session_id", + :httponly => true, + }.freeze + + def self.new(app) + cgi_options = ActionController::Base.session_options + options = cgi_options.symbolize_keys + options = DEFAULT_OPTIONS.merge(options) + options[:path] = options.delete(:session_path) + options[:key] = options.delete(:session_key) + options[:httponly] = options.delete(:session_http_only) + + if store = ActionController::Base.session_store + store.new(app, options) + else # Sessions disabled + lambda { |env| app.call(env) } + end end end @@ -12,144 +33,45 @@ module ActionController #:nodoc: # Set the session store to be used for keeping the session data between requests. # By default, sessions are stored in browser cookies (<tt>:cookie_store</tt>), # but you can also specify one of the other included stores (<tt>:active_record_store</tt>, - # <tt>:p_store</tt>, <tt>:drb_store</tt>, <tt>:mem_cache_store</tt>, or - # <tt>:memory_store</tt>) or your own custom class. + # <tt>:mem_cache_store</tt>, or your own custom class. def session_store=(store) - ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS[:database_manager] = - store.is_a?(Symbol) ? CGI::Session.const_get(store == :drb_store ? "DRbStore" : store.to_s.camelize) : store + if store == :active_record_store + self.session_store = ActiveRecord::SessionStore + else + @@session_store = store.is_a?(Symbol) ? + Session.const_get(store.to_s.camelize) : + store + end end # Returns the session store class currently used. def session_store - ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS[:database_manager] + if defined? @@session_store + @@session_store + else + Session::CookieStore + end + end + + def session=(options = {}) + self.session_store = nil if options.delete(:disabled) + session_options.merge!(options) end # Returns the hash used to configure the session. Example use: # # ActionController::Base.session_options[:session_secure] = true # session only available over HTTPS def session_options - ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS - end - - # Specify how sessions ought to be managed for a subset of the actions on - # the controller. Like filters, you can specify <tt>:only</tt> and - # <tt>:except</tt> clauses to restrict the subset, otherwise options - # apply to all actions on this controller. - # - # The session options are inheritable, as well, so if you specify them in - # a parent controller, they apply to controllers that extend the parent. - # - # Usage: - # - # # turn off session management for all actions. - # session :off - # - # # turn off session management for all actions _except_ foo and bar. - # session :off, :except => %w(foo bar) - # - # # turn off session management for only the foo and bar actions. - # session :off, :only => %w(foo bar) - # - # # the session will only work over HTTPS, but only for the foo action - # session :only => :foo, :session_secure => true - # - # # the session by default uses HttpOnly sessions for security reasons. - # # this can be switched off. - # session :only => :foo, :session_http_only => false - # - # # the session will only be disabled for 'foo', and only if it is - # # requested as a web service - # session :off, :only => :foo, - # :if => Proc.new { |req| req.parameters[:ws] } - # - # # the session will be disabled for non html/ajax requests - # session :off, - # :if => Proc.new { |req| !(req.format.html? || req.format.js?) } - # - # # turn the session back on, useful when it was turned off in the - # # application controller, and you need it on in another controller - # session :on - # - # All session options described for ActionController::Base.process_cgi - # are valid arguments. - def session(*args) - options = args.extract_options! - - options[:disabled] = false if args.delete(:on) - options[:disabled] = true if !args.empty? - options[:only] = [*options[:only]].map { |o| o.to_s } if options[:only] - options[:except] = [*options[:except]].map { |o| o.to_s } if options[:except] - if options[:only] && options[:except] - raise ArgumentError, "only one of either :only or :except are allowed" - end - - write_inheritable_array(:session_options, [options]) + @session_options ||= {} end - # So we can declare session options in the Rails initializer. - alias_method :session=, :session - - def cached_session_options #:nodoc: - @session_options ||= read_inheritable_attribute(:session_options) || [] - end - - def session_options_for(request, action) #:nodoc: - if (session_options = cached_session_options).empty? - {} - else - options = {} - - action = action.to_s - session_options.each do |opts| - next if opts[:if] && !opts[:if].call(request) - if opts[:only] && opts[:only].include?(action) - options.merge!(opts) - elsif opts[:except] && !opts[:except].include?(action) - options.merge!(opts) - elsif !opts[:only] && !opts[:except] - options.merge!(opts) - end - end - - if options.empty? then options - else - options.delete :only - options.delete :except - options.delete :if - options[:disabled] ? false : options - end - end + def session(*args) + ActiveSupport::Deprecation.warn( + "Disabling sessions for a single controller has been deprecated. " + + "Sessions are now lazy loaded. So if you don't access them, " + + "consider them off. You can still modify the session cookie " + + "options with request.session_options.", caller) end end - - def process_with_session_management_support(request, response, method = :perform_action, *arguments) #:nodoc: - set_session_options(request) - process_without_session_management_support(request, response, method, *arguments) - end - - private - def set_session_options(request) - request.session_options = self.class.session_options_for(request, request.parameters["action"] || "index") - end - - def process_cleanup_with_session_management_support - clear_persistent_model_associations - process_cleanup_without_session_management_support - end - - # Clear cached associations in session data so they don't overflow - # the database field. Only applies to ActiveRecordStore since there - # is not a standard way to iterate over session data. - def clear_persistent_model_associations #:doc: - if defined?(@_session) && @_session.respond_to?(:data) - session_data = @_session.data - - if session_data && session_data.respond_to?(:each_value) - session_data.each_value do |obj| - obj.clear_association_cache if obj.respond_to?(:clear_association_cache) - end - end - end - end end end |