aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_controller/session_management.rb
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/lib/action_controller/session_management.rb')
-rw-r--r--actionpack/lib/action_controller/session_management.rb174
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