X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FCatalyst%2FPlugin%2FSession.pm;h=0aae81797d327f46556a3a4e293495bbf1f50943;hb=fa0221108e7d61b2fccb3fc7449edaec165933d7;hp=89e39aa90a109ce01b36fd701b98b02349937421;hpb=2110d07847641c3e7aa7fa1444c05b975e2480e7;p=catagits%2FCatalyst-Plugin-Session.git diff --git a/lib/Catalyst/Plugin/Session.pm b/lib/Catalyst/Plugin/Session.pm index 89e39aa..0aae817 100644 --- a/lib/Catalyst/Plugin/Session.pm +++ b/lib/Catalyst/Plugin/Session.pm @@ -13,7 +13,7 @@ use Carp; use namespace::clean -except => 'meta'; -our $VERSION = '0.30'; +our $VERSION = '0.34'; $VERSION = eval $VERSION; my @session_data_accessors; # used in delete_session @@ -102,8 +102,10 @@ sub prepare_action { sub finalize_headers { my $c = shift; - # fix cookie before we send headers - $c->_save_session_expires; + # Force extension of session_expires before finalizing headers, so a possible cookie will be + # up to date. First call to session_expires will extend the expiry, subsequent calls will + # just return the previously extended value. + $c->session_expires; return $c->maybe::next::method(@_); } @@ -124,6 +126,7 @@ sub finalize_session { $c->maybe::next::method(@_); + $c->_save_session_expires; $c->_save_session_id; $c->_save_session; $c->_save_flash; @@ -225,6 +228,7 @@ sub _load_session { no warnings 'uninitialized'; # ne __address if ( $c->_session_plugin_config->{verify_address} + && exists $session_data->{__address} && $session_data->{__address} ne $c->request->address ) { $c->log->warn( @@ -355,19 +359,39 @@ sub session_expires { sub extend_session_expires { my ( $c, $expires ) = @_; - $c->_extended_session_expires( my $updated = $c->calculate_extended_session_expires( $expires ) ); + $c->_extended_session_expires( my $updated = $c->calculate_initial_session_expires( $expires ) ); $c->extend_session_id( $c->sessionid, $updated ); return $updated; } -sub calculate_initial_session_expires { +sub change_session_expires { + my ( $c, $expires ) = @_; + + $expires ||= 0; + my $sid = $c->sessionid; + my $time_exp = time() + $expires; + $c->store_session_data( "expires:$sid" => $time_exp ); +} + +sub initial_session_expires { my $c = shift; return ( time() + $c->_session_plugin_config->{expires} ); } +sub calculate_initial_session_expires { + my $c = shift; + + my $initial_expires = $c->initial_session_expires; + my $stored_session_expires = 0; + if ( my $sid = $c->sessionid ) { + $stored_session_expires = $c->get_session_data("expires:$sid") || 0; + } + return ( $initial_expires > $stored_session_expires ) ? $initial_expires : $stored_session_expires; +} + sub calculate_extended_session_expires { my ( $c, $prev ) = @_; - $c->calculate_initial_session_expires; + return ( time() + $prev ); } sub reset_session_expires { @@ -578,7 +602,7 @@ sub dump_these { ( $c->maybe::next::method(), - $c->sessionid + $c->_sessionid ? ( [ "Session ID" => $c->sessionid ], [ Session => $c->session ], ) : () ); @@ -703,16 +727,10 @@ hashref. =item session_expires -=item session_expires $reset - This method returns the time when the current session will expire, or 0 if there is no current session. If there is a session and it already expired, it will delete the session and return 0 as well. -If the C<$reset> parameter is true, and there is a session ID the expiry time -will be reset to the current time plus the time to live (see -L). This is used when creating a new session. - =item flash This is like Ruby on Rails' flash data structure. Think of it as a stash that @@ -723,6 +741,15 @@ $c->flash (thus allowing multiple redirections), and the policy is to delete all the keys which haven't changed since the flash data was loaded at the end of every request. +Note that use of the flash is an easy way to get data across requests, but +it's also strongly disrecommended, due it it being inherently plagued with +race conditions. This means that it's unlikely to work well if your +users have multiple tabs open at once, or if your site does a lot of AJAX +requests. + +L is the recommended alternative solution, +as this doesn't suffer from these issues. + sub moose : Local { my ( $self, $c ) = @_; @@ -788,7 +815,7 @@ expiry time for the whole session). For example: - __PACKAGE__->config('Plugin::Session' => { expires => 10000000000 }); # "forever" + __PACKAGE__->config('Plugin::Session' => { expires => 10000000000 }); # "forever" (NB If this number is too large, Y2K38 breakage could result.) # later @@ -825,6 +852,14 @@ you should call change_session_id in your login controller like this: ... } +=item change_session_expires $expires + +You can change the session expiration time for this session; + + $c->change_session_expires( 4000 ); + +Note that this only works to set the session longer than the config setting. + =back =head1 INTERNAL METHODS @@ -953,6 +988,9 @@ dumped objects if session ID is defined. =item extend_session_expires +Note: this is *not* used to give an individual user a longer session. See +'change_session_expires'. + =item extend_session_id =item get_session_id @@ -1131,6 +1169,10 @@ Kent Fredric (kentnl) And countless other contributers from #catalyst. Thanks guys! +=head1 Contributors + +Devin Austin (dhoss) + =head1 COPYRIGHT & LICENSE Copyright (c) 2005 the aforementioned authors. All rights