File Coverage

blib/lib/Dancer2/Session/Cookie.pm
Criterion Covered Total %
statement 25 26 96.1
branch 2 2 100.0
condition n/a
subroutine 11 12 91.6
pod 0 1 0.0
total 38 41 92.6


line stmt bran cond sub pod time code
1 2     2   126424 use 5.008001;
  2         18  
2 2     2   17 use strict;
  2         5  
  2         73  
3 2     2   15 use warnings;
  2         5  
  2         227  
4              
5             package Dancer2::Session::Cookie;
6             our $AUTHORITY = 'cpan:YANICK';
7             # ABSTRACT: Dancer 2 session storage in secure cookies
8             # VERSION
9             $Dancer2::Session::Cookie::VERSION = '0.009';
10 2     2   1349 use Session::Storage::Secure 0.011 ();
  2         210302  
  2         95  
11              
12 2     2   23 use Moo;
  2         5  
  2         14  
13 2     2   1957 use Dancer2::Core::Types;
  2         223812  
  2         34  
14              
15             #--------------------------------------------------------------------------#
16             # Attributes
17             #--------------------------------------------------------------------------#
18              
19              
20             has secret_key => (
21             is => 'ro',
22             isa => Str,
23             required => 1,
24             );
25              
26              
27             has default_duration => (
28             is => 'ro',
29             isa => Int,
30             predicate => 1,
31             );
32              
33              
34             has with_request_address => (
35             is => 'ro',
36             isa => Bool,
37             );
38              
39             has _store => (
40             is => 'lazy',
41             isa => InstanceOf ['Session::Storage::Secure'],
42             handles => {
43             '_freeze' => 'encode',
44             '_retrieve' => 'decode',
45             },
46             );
47              
48             before [qw/ _freeze _retrieve /] => sub {
49             my $self = shift;
50             return unless $self->with_request_address;
51             $self->_store->{secret_key} = join '-', $self->secret_key, $self->request->address;
52             };
53              
54             sub _build__store {
55 7     7   1141 my ($self) = @_;
56 7         113 my %args = (
57             secret_key => $self->secret_key,
58             sereal_encoder_options => { snappy => 1, stringify_unknown => 1 },
59             sereal_decoder_options => { validate_utf8 => 1 },
60             );
61 7 100       51 $args{default_duration} = $self->default_duration
62             if $self->has_default_duration;
63 7         243 return Session::Storage::Secure->new(%args);
64             }
65              
66             sub _change_id {
67             # This is a noop with session cookies.
68 4     4   228 return;
69             }
70              
71             with 'Dancer2::Core::Role::SessionFactory';
72              
73             #--------------------------------------------------------------------------#
74             # Modified SessionFactory methods
75             #--------------------------------------------------------------------------#
76              
77             # We don't need to generate an ID. We'll set it during cookie generation
78 25     25 0 333837 sub generate_id { '' }
79              
80             # Cookie generation: serialize the session data into the session ID
81             # right before the cookie is generated
82             before 'cookie' => sub {
83             my ( $self, %params ) = @_;
84             my $session = $params{session};
85             return unless ref $session && $session->isa("Dancer2::Core::Session");
86             $session->id( $self->_freeze( $session->data, $session->expires ) );
87             };
88              
89             #--------------------------------------------------------------------------#
90             # SessionFactory implementation methods
91             #--------------------------------------------------------------------------#
92              
93             # _retrieve handled by _store
94              
95             # We don't actually flush data; instead we modify cookie generation
96 33     33   37492 sub _flush { return }
97              
98             # We have nothing to destroy, either; cookie expiration is all that matters
99 8     8   12371 sub _destroy { return }
100              
101             # There is no way to know about existing sessions when cookies
102             # are used as the store, so we lie and return an empty list.
103 0     0     sub _sessions { return [] }
104              
105             1;
106              
107              
108             # vim: ts=4 sts=4 sw=4 et:
109              
110             __END__