0
require 'abstract_unit'
0
+class CookieStoreTest < ActionController::IntegrationTest
0
+ SessionKey = '_myapp_session'
0
+ SessionSecret = 'b3c631c314c0bbca50c1b2843150fe33'
0
-class CGI::Session::CookieStore
0
- def ensure_secret_secure_with_test_hax(secret)
0
- if secret == CookieStoreTest.default_session_options['secret']
0
- ensure_secret_secure_without_test_hax(secret)
0
- alias_method_chain :ensure_secret_secure, :test_hax
0
+ DispatcherApp = ActionController::Dispatcher.new
0
+ CookieStoreApp = ActionController::Session::CookieStore.new(DispatcherApp,
0
+ :key => SessionKey, :secret => SessionSecret)
0
+ SignedBar = "BAh7BjoIZm9vIghiYXI%3D--" +
0
+ "fef868465920f415f2c0652d6910d3af288a0367"
0
- attr_reader :output_cookies, :output_hidden
0
+ class TestController < ActionController::Base
0
- attr_reader :data, :original, :cookie_options
0
-class CookieStoreTest < Test::Unit::TestCase
0
- def self.default_session_options
0
- { 'database_manager' => CGI::Session::CookieStore,
0
- 'session_key' => '_myapp_session',
0
- 'secret' => 'Keep it secret; keep it safe.',
0
- 'session_http_only' => true
0
+ render :text => "foo: #{session[:foo].inspect}"
0
- { :empty => ['BAgw--0686dcaccc01040f4bd4f35fe160afe9bc04c330', {}],
0
- :a_one => ['BAh7BiIGYWkG--5689059497d7f122a7119f171aef81dcfd807fec', { 'a' => 1 }],
0
- :typical => ['BAh7ByIMdXNlcl9pZGkBeyIKZmxhc2h7BiILbm90aWNlIgxIZXkgbm93--9d20154623b9eeea05c62ab819be0e2483238759', { 'user_id' => 123, 'flash' => { 'notice' => 'Hey now' }}],
0
- :flashed => ['BAh7ByIMdXNlcl9pZGkBeyIKZmxhc2h7AA==--bf9785a666d3c4ac09f7fe3353496b437546cfbf', { 'user_id' => 123, 'flash' => {} }]
0
+ def raise_data_overflow
0
+ session[:foo] = 'bye!' * 1024
0
+ def rescue_action(e) raise end
0
-
ENV.delete('HTTP_COOKIE')
0
+
@integration_session = open_session(CookieStoreApp)
0
def test_raises_argument_error_if_missing_session_key
0
- [nil, ''].each do |blank|
0
- assert_raise(ArgumentError, blank.inspect) { new_session 'session_key' => blank }
0
+ assert_raise(ArgumentError, nil.inspect) {
0
+ ActionController::Session::CookieStore.new(nil,
0
+ :key => nil, :secret => SessionSecret)
0
+ assert_raise(ArgumentError, ''.inspect) {
0
+ ActionController::Session::CookieStore.new(nil,
0
+ :key => '', :secret => SessionSecret)
0
def test_raises_argument_error_if_missing_secret
0
- [nil, ''].each do |blank|
0
- assert_raise(ArgumentError, blank.inspect) { new_session 'secret' => blank }
0
+ assert_raise(ArgumentError, nil.inspect) {
0
+ ActionController::Session::CookieStore.new(nil,
0
+ :key => SessionKey, :secret => nil)
0
- def test_raises_argument_error_if_secret_is_probably_insecure
0
- ["password", "secret", "12345678901234567890123456789"].each do |blank|
0
- assert_raise(ArgumentError, blank.inspect) { new_session 'secret' => blank }
0
+ assert_raise(ArgumentError, ''.inspect) {
0
+ ActionController::Session::CookieStore.new(nil,
0
+ :key => SessionKey, :secret => '')
0
- def test_reconfigures_session_to_omit_id_cookie_and_hidden_field
0
- new_session do |session|
0
- assert_equal true, @options['no_hidden']
0
- assert_equal true, @options['no_cookies']
0
+ def test_raises_argument_error_if_secret_is_probably_insecure
0
+ assert_raise(ArgumentError, "password".inspect) {
0
+ ActionController::Session::CookieStore.new(nil,
0
+ :key => SessionKey, :secret => "password")
0
- def test_restore_unmarshals_missing_cookie_as_empty_hash
0
- new_session do |session|
0
- assert_nil session.dbman.data
0
- assert_nil session['test']
0
- assert_equal Hash.new, session.dbman.data
0
+ assert_raise(ArgumentError, "secret".inspect) {
0
+ ActionController::Session::CookieStore.new(nil,
0
+ :key => SessionKey, :secret => "secret")
0
- def test_restore_unmarshals_good_cookies
0
- cookies(:empty, :a_one, :typical).each do |value, expected|
0
- new_session do |session|
0
- assert_nil session['lazy loads the data hash']
0
- assert_equal expected, session.dbman.data
0
+ assert_raise(ArgumentError, "12345678901234567890123456789".inspect) {
0
+ ActionController::Session::CookieStore.new(nil,
0
+ :key => SessionKey, :secret => "12345678901234567890123456789")
0
- def test_restore_deletes_tampered_cookies
0
- new_session do |session|
0
- assert_raise(CGI::Session::CookieStore::TamperedWithCookie) { session['fail'] }
0
- assert_cookie_deleted session
0
+ def test_setting_session_value
0
+ with_test_route_set do
0
+ get '/set_session_value'
0
+ assert_response :success
0
+ assert_equal ["_myapp_session=#{SignedBar}; path=/"],
0
- def test_close_doesnt_write_cookie_if_data_is_blank
0
- new_session do |session|
0
- assert_no_cookies session
0
- assert_no_cookies session
0
+ def test_getting_session_value
0
+ with_test_route_set do
0
+ cookies[SessionKey] = SignedBar
0
+ get '/get_session_value'
0
+ assert_response :success
0
+ assert_equal 'foo: "bar"', response.body
0
- def test_close_doesnt_write_cookie_if_data_is_unchanged
0
- set_cookie! cookie_value(:typical)
0
- new_session do |session|
0
- assert_no_cookies session
0
- session['user_id'] = session['user_id']
0
- assert_no_cookies session
0
+ def test_disregards_tampered_sessions
0
+ with_test_route_set do
0
+ cookies[SessionKey] = "BAh7BjoIZm9vIghiYXI%3D--123456780"
0
+ get '/get_session_value'
0
+ assert_response :success
0
+ assert_equal 'foo: nil', response.body
0
def test_close_raises_when_data_overflows
0
- set_cookie! cookie_value(:empty)
0
- new_session do |session|
0
- session['overflow'] = 'bye!' * 1024
0
- assert_raise(CGI::Session::CookieStore::CookieOverflow) { session.close }
0
- assert_no_cookies session
0
- def test_close_marshals_and_writes_cookie
0
- set_cookie! cookie_value(:typical)
0
- new_session do |session|
0
- assert_no_cookies session
0
- assert_no_cookies session
0
- assert_equal 1, session.cgi.output_cookies.size
0
- cookie = session.cgi.output_cookies.first
0
- assert_cookie cookie, cookie_value(:flashed)
0
- assert_http_only_cookie cookie
0
- assert_secure_cookie cookie, false
0
- def test_writes_non_secure_cookie_by_default
0
- set_cookie! cookie_value(:typical)
0
- new_session do |session|
0
- cookie = session.cgi.output_cookies.first
0
- assert_secure_cookie cookie,false
0
- def test_writes_secure_cookie
0
- set_cookie! cookie_value(:typical)
0
- new_session('session_secure'=>true) do |session|
0
- cookie = session.cgi.output_cookies.first
0
- assert_secure_cookie cookie
0
+ with_test_route_set do
0
+ assert_raise(ActionController::Session::CookieStore::CookieOverflow) {
0
+ get '/raise_data_overflow'
0
- def test_http_only_cookie_by_default
0
- set_cookie! cookie_value(:typical)
0
- new_session do |session|
0
- cookie = session.cgi.output_cookies.first
0
- assert_http_only_cookie cookie
0
+ def test_doesnt_write_session_cookie_if_session_is_not_accessed
0
+ with_test_route_set do
0
+ get '/no_session_access'
0
+ assert_response :success
0
+ assert_equal [], headers['Set-Cookie']
0
- def test_overides_http_only_cookie
0
- set_cookie! cookie_value(:typical)
0
- new_session('session_http_only'=>false) do |session|
0
- cookie = session.cgi.output_cookies.first
0
- assert_http_only_cookie cookie, false
0
- def test_delete_writes_expired_empty_cookie_and_sets_data_to_nil
0
- set_cookie! cookie_value(:typical)
0
- new_session do |session|
0
- assert_no_cookies session
0
- assert_cookie_deleted session
0
- # @data is set to nil so #close doesn't send another cookie.
0
- assert_cookie_deleted session
0
- def test_new_session_doesnt_reuse_deleted_cookie_data
0
- set_cookie! cookie_value(:typical)
0
- new_session do |session|
0
- assert_not_nil session['user_id']
0
- # Start a new session using the same CGI instance.
0
- post_delete_session = CGI::Session.new(session.cgi, self.class.default_session_options)
0
- assert_nil post_delete_session['user_id']
0
+ def test_doesnt_write_session_cookie_if_session_is_unchanged
0
+ with_test_route_set do
0
+ cookies[SessionKey] = "BAh7BjoIZm9vIghiYXI%3D--" +
0
+ "fef868465920f415f2c0652d6910d3af288a0367"
0
+ get '/no_session_access'
0
+ assert_response :success
0
+ assert_equal [], headers['Set-Cookie']
0
- def assert_no_cookies(session)
0
- assert_nil session.cgi.output_cookies, session.cgi.output_cookies.inspect
0
- def assert_cookie_deleted(session, message = 'Expected session deletion cookie to be set')
0
- assert_equal 1, session.cgi.output_cookies.size
0
- cookie = session.cgi.output_cookies.first
0
- assert_cookie cookie, nil, 1.year.ago.to_date, "#{message}: #{cookie.name} => #{cookie.value}"
0
- def assert_cookie(cookie, value = nil, expires = nil, message = nil)
0
- assert_equal '_myapp_session', cookie.name, message
0
- assert_equal [value].compact, cookie.value, message
0
- assert_equal expires, cookie.expires ? cookie.expires.to_date : cookie.expires, message
0
- def assert_secure_cookie(cookie,value=true)
0
- assert cookie.secure==value
0
- def assert_http_only_cookie(cookie,value=true)
0
- assert cookie.http_only==value
0
- self.class.cookies.values_at(*which)
0
- def cookie_value(which)
0
- self.class.cookies[which].first
0
- def set_cookie!(value)
0
- ENV['HTTP_COOKIE'] = "_myapp_session=#{value}"
0
- def new_session(options = {})
0
- assert_nil cgi.output_hidden, "Output hidden params should be empty: #{cgi.output_hidden.inspect}"
0
- assert_nil cgi.output_cookies, "Output cookies should be empty: #{cgi.output_cookies.inspect}"
0
- @options = self.class.default_session_options.merge(options)
0
- session = CGI::Session.new(cgi, @options)
0
- ObjectSpace.undefine_finalizer(session)
0
- assert_nil cgi.output_hidden, "Output hidden params should be empty: #{cgi.output_hidden.inspect}"
0
- assert_nil cgi.output_cookies, "Output cookies should be empty: #{cgi.output_cookies.inspect}"
0
- yield session if block_given?
0
+ def with_test_route_set
0
+ map.with_options :controller => "cookie_store_test/test" do |c|
0
- ENV['REQUEST_METHOD'] = 'GET'
0
- ENV['HTTP_HOST'] = 'example.com'
0
- ENV['QUERY_STRING'] = ''
0
- cgi = CGI.new('query', StringIO.new(''))
0
- yield cgi if block_given?
0
-class CookieStoreWithBlockAsSecretTest < CookieStoreTest
0
- def self.default_session_options
0
- CookieStoreTest.default_session_options.merge 'secret' => Proc.new { 'Keep it secret; keep it safe.' }
0
-class CookieStoreWithMD5DigestTest < CookieStoreTest
0
- def self.default_session_options
0
- CookieStoreTest.default_session_options.merge 'digest' => 'MD5'
0
- { :empty => ['BAgw--0415cc0be9579b14afc22ee2d341aa21', {}],
0
- :a_one => ['BAh7BiIGYWkG--5a0ed962089cc6600ff44168a5d59bc8', { 'a' => 1 }],
0
- :typical => ['BAh7ByIMdXNlcl9pZGkBeyIKZmxhc2h7BiILbm90aWNlIgxIZXkgbm93--f426763f6ef435b3738b493600db8d64', { 'user_id' => 123, 'flash' => { 'notice' => 'Hey now' }}],
0
- :flashed => ['BAh7ByIMdXNlcl9pZGkBeyIKZmxhc2h7AA==--0af9156650dab044a53a91a4ddec2c51', { 'user_id' => 123, 'flash' => {} }],
0
- :double_escaped => [CGI.escape('BAh7ByIMdXNlcl9pZGkBeyIKZmxhc2h7AA%3D%3D--0af9156650dab044a53a91a4ddec2c51'), { 'user_id' => 123, 'flash' => {} }] }
Josh,
Not sure if this makes sense, but we’ve been using CookieSessionStore with a persistent session_id for a few months to be able to track features such as visitors to resource X also viewed resource Y etc.
Sole motivation being API compat with other stores that do yield a consistent session identifier minus having to use a server side session store.
I updated it today for compat. with this commit.
http://github.com/methodmissing/stable_session_id/tree/master
Would you consider such a feature useful at the framework level ?
Yes, lets do that. I don’t want to invalidate anyones sessions intentionally.
Please open a ticket on LH and assign it to me.