Catalyst-Plugin-Session-Store-Cookie
view release on metacpan or search on metacpan
lib/Catalyst/Plugin/Session/Store/Cookie.pm view on Meta::CPAN
package Catalyst::Plugin::Session::Store::Cookie;
use Moose;
use Session::Storage::Secure;
use MRO::Compat;
use Catalyst::Utils;
extends 'Catalyst::Plugin::Session::Store';
with 'Catalyst::ClassData';
our $VERSION = '0.005';
__PACKAGE__->mk_classdata($_)
for qw/_secure_store _store_cookie_name _store_cookie_expires
_store_cookie_secure _store_cookie_httponly _store_cookie_samesite/;
sub get_session_data {
my ($self, $key) = @_;
$self->_needs_early_session_finalization(1);
# Don't decode if we've decoded this context already.
return $self->{__cookie_session_store_cache__}->{$key} if
exists($self->{__cookie_session_store_cache__}) &&
exists($self->{__cookie_session_store_cache__}->{$key});
my $cookie = $self->req->cookie($self->_store_cookie_name);
$self->{__cookie_session_store_cache__} = defined($cookie) ?
$self->_decode_secure_store($cookie, $key) : +{};
return $self->{__cookie_session_store_cache__}->{$key};
}
sub _decode_secure_store {
my ($self, $cookie, $key) = @_;
my $decoded = eval {
$self->_secure_store->decode($cookie->value);
} || do {
$self->log->error("Issue decoding cookie for key '$key': $@");
return +{};
};
return $decoded;
}
sub store_session_data {
my ($self, $key, $data) = @_;
$self->{__cookie_session_store_cache__} = +{
%{$self->{__cookie_session_store_cache__}},
$key => $data};
my $cookie = {
value => $self->_secure_store->encode($self->{__cookie_session_store_cache__}),
expires => $self->_store_cookie_expires,
};
# copied from Catalyst::Plugin::Session::State::Cookie
my $sec = $self->_store_cookie_secure;
$cookie->{secure} = 1 unless ( ($sec==0) || ($sec==2) );
$cookie->{secure} = 1 if ( ($sec==2) && $self->req->secure );
$cookie->{httponly} = $self->_store_cookie_httponly;
$cookie->{samesite} = $self->_store_cookie_samesite;
return $self->res->cookies->{$self->_store_cookie_name} = $cookie;
}
sub delete_session_data {
my ($self, $key) = @_;
delete $self->{__cookie_session_store_cache__}->{$key};
}
# Docs say 'this may be used in the future', like 10 years ago...
sub delete_expired_sessions { }
sub setup_session {
my $class = shift;
my $cfg = $class->_session_plugin_config;
$class->_store_cookie_name($cfg->{storage_cookie_name} || Catalyst::Utils::appprefix($class) . '_store');
$class->_store_cookie_expires($cfg->{storage_cookie_expires} || '+1d');
$class->_secure_store(
Session::Storage::Secure->new(
secret_key => ($cfg->{storage_secret_key} ||
die "storage_secret_key' configuration param for 'Catalyst::Plugin::Session::Store::Cookie' is missing!"),
sereal_encoder_options => ($cfg->{sereal_encoder_options} || +{ snappy => 1, stringify_unknown => 1 }),
sereal_decoder_options => ($cfg->{sereal_decoder_options} || +{ validate_utf8 => 1 })
)
);
$class->_store_cookie_secure($cfg->{storage_cookie_secure} || 0);
$class->_store_cookie_httponly($cfg->{storage_cookie_httponly} || 1);
$class->_store_cookie_samesite($cfg->{storage_cookie_samesite} || 'Lax');
return $class->maybe::next::method(@_);
}
__PACKAGE__->meta->make_immutable;
=head1 NAME
Catalyst::Plugin::Session::Store::Cookie - Store session data in the cookie
=head1 SYNOPSIS
( run in 1.848 second using v1.01-cache-2.11-cpan-39bf76dae61 )