Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Changeset 2612

Show
Ignore:
Timestamp:
10/15/05 14:39:29 (3 years ago)
Author:
marcel
Message:

Raise an exception if an attempt is made to insert more session data into the ActiveRecordStore data column than the column can hold. Closes #2234.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/actionpack/CHANGELOG

    r2611 r2612  
    11*SVN* 
     2 
     3* Raise an exception if an attempt is made to insert more session data into the ActiveRecordStore data column than the column can hold. #2234.  [justin@textdrive.com] 
    24 
    35* Removed references to assertions.rb from actionpack assert's backtraces. Makes error reports in functional unit tests much less noisy. [Tobias Luetke] 
  • trunk/actionpack/lib/action_controller/base.rb

    r2567 r2612  
    2525  end 
    2626  class MissingFile < ActionControllerError #:nodoc: 
     27  end 
     28  class SessionOverflowError < ActionControllerError #:nodoc: 
     29    DEFAULT_MESSAGE = 'Your session data is larger than the data column in which it is to be stored. You must increase the size of your data column if you intend to store large data.' 
    2730  end 
    2831  class DoubleRenderError < ActionControllerError #:nodoc: 
  • trunk/actionpack/lib/action_controller/session/active_record_store.rb

    r2275 r2612  
    3434    # The fast SqlBypass class is a generic SQL session store.  You may 
    3535    # use it as a basis for high-performance database-specific stores. 
     36    # 
     37    # If the data you are attempting to write to the +data+ column is larger 
     38    # than the column's size limit, ActionController::SessionOverflowError  
     39    # will be raised. 
    3640    class ActiveRecordStore 
    3741      # The default Active Record class. 
    3842      class Session < ActiveRecord::Base 
    3943        before_save   :marshal_data! 
     44        before_save   :ensure_data_not_too_big 
    4045        before_update :data_changed? 
    4146 
    4247        class << self 
     48 
     49          def data_column_size_limit 
     50            connection.columns(table_name).find {|column| column.name == 'data'}.limit 
     51          end 
     52 
    4353          # Hook to set up sessid compatibility. 
    4454          def find_by_session_id(session_id) 
     
    5666                id INTEGER PRIMARY KEY, 
    5767                #{connection.quote_column_name('session_id')} TEXT UNIQUE, 
    58                 #{connection.quote_column_name('data')} TEXT 
     68                #{connection.quote_column_name('data')} TEXT(255) 
    5969              ) 
    6070            end_sql 
     
    110120            old_fingerprint != @fingerprint 
    111121          end 
     122 
     123          # Ensures that the data about to be stored in the database is not 
     124          # larger than the data storage column. Raises 
     125          # ActionController::SessionOverflowError. 
     126          def ensure_data_not_too_big 
     127            return unless limit = self.class.data_column_size_limit 
     128            raise ActionController::SessionOverflowError, ActionController::SessionOverflowError::DEFAULT_MESSAGE if read_attribute('data').size > limit 
     129          end 
     130 
    112131      end 
    113132 
     
    127146        # Use the ActiveRecord::Base.connection by default. 
    128147        cattr_accessor :connection 
    129         def self.connection 
    130           @@connection ||= ActiveRecord::Base.connection 
    131         end 
    132148 
    133149        # The table name defaults to 'sessions'. 
     
    144160 
    145161        class << self 
     162 
     163          def connection 
     164            @@connection ||= ActiveRecord::Base.connection 
     165          end 
     166 
    146167          # Look up a session by id and unmarshal its data if found. 
    147168          def find_by_session_id(session_id) 
     
    202223        def save 
    203224          marshaled_data = self.class.marshal(data) 
     225 
    204226          if @new_record 
    205227            @new_record = false 
     
    232254          end 
    233255        end 
     256 
    234257      end 
    235258 
     
    279302        end 
    280303      end 
     304 
    281305    end 
    282306  end 
  • trunk/actionpack/test/controller/active_record_store_test.rb

    r2331 r2612  
    5454    end 
    5555  end 
     56 
    5657end 
    5758 
     
    7677    session_class.drop_table! 
    7778  end 
     79end 
     80 
     81class ColumnLimitTest < Test::Unit::TestCase 
     82 
     83  def setup 
     84    @session_class = CGI::Session::ActiveRecordStore::Session 
     85    @session_class.create_table! 
     86  end 
     87 
     88  def teardown 
     89    @session_class.drop_table! 
     90  end 
     91 
     92  def test_protection_from_data_larger_than_column 
     93    # Can't test this unless there is a limit 
     94    return unless limit = @session_class.data_column_size_limit 
     95    too_big = ':(' * limit 
     96    s = @session_class.new(:session_id => '666', :data => {'foo' => too_big}) 
     97    s.data 
     98    assert_raises(ActionController::SessionOverflowError) { s.save } 
     99  end 
     100 
    78101end 
    79102