sub prepare_action {
my $c = shift;
+ $c->_load_session;
+
+ $c->NEXT::prepare_action(@_);
+}
+
+sub _load_session {
+ my $c = shift;
+
if ( my $sid = $c->sessionid ) {
no warnings 'uninitialized'; # ne __address
else {
$c->log->debug(qq/Restored session "$sid"/) if $c->debug;
}
+
+ $c->_expire_ession_keys;
+
}
+}
- $c->NEXT::prepare_action(@_);
+sub _expire_ession_keys {
+ my ( $c, $data ) = @_;
+
+ my $now = time;
+
+ my $expiry = ($data || $c->_session || {})->{__expire_keys} || {};
+ foreach my $key (grep { $expiry->{$_} < $now } keys %$expiry ) {
+ delete $c->_session->{$key};
+ delete $expiry->{$key};
+ }
}
sub delete_session {
};
}
+sub session_expire_key {
+ my ( $c, %keys ) = @_;
+
+ my $now = time;
+ @{ $c->session->{__expire_keys} }{keys %keys} = map { $now + $_ } values %keys;
+}
+
sub initialize_session_data {
my $c = shift;
=back
+=item session_expire_key $key, $ttl
+
+Mark a key to expire at a certain time (only useful when shorter than the
+expiry time for the whole session).
+
+For example:
+
+ __PACKAGE__->config->{session}{expires} = 1000000000000; # forever
+
+ # later
+
+ $c->session_expire_key( __user => 3600 );
+
+Will make the session data survive, but the user will still be logged out after
+an hour.
+
+Note that these values are not auto extended.
+
=back
=item INTERNAL METHODS
use strict;
use warnings;
-use Test::More tests => 20;
+use Test::More tests => 25;
use Test::MockObject;
use Test::Deep;
use Test::Exception;
$now + 2000,
"session expires time extended"
);
+}
+
+{
+ my $c = MockCxt->new;
+ $c->setup;
dies_ok {
$c->sessionid("user:foo");
} "can't set invalid sessionid string";
}
+{
+ %session = (
+ %session,
+ __expire_keys => {
+ foo => time - 1000,
+ bar => time + 1000,
+ },
+ foo => 1,
+ bar => 2,
+ gorch => 3,
+ );
+
+ my $c = MockCxt->new;
+ $c->setup;
+
+ $c->sessionid("decafbad");
+ $c->prepare_action;
+ $c->finalize;
+
+ ok( !$c->session->{foo}, "foo was deleted, expired");
+ ok( $c->session->{bar}, "bar not deleted - still valid");
+ ok( $c->session->{gorch}, "gorch not deleted - no expiry");
+
+ is_deeply( [ sort keys %{ $c->session->{__expire_keys} } ], [qw/bar/], "expiry entry only for bar");
+
+ $c->session_expire_key( gorch => 10 );
+
+ is_deeply( [ sort keys %{ $c->session->{__expire_keys} } ], [qw/bar gorch/], "expiry entries for bar and gorch");
+}