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   114927 use 5.008001;
  2         8  
2 2     2   12 use strict;
  2         3  
  2         74  
3 2     2   12 use warnings;
  2         3  
  2         204  
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.008';
10 2     2   1364 use Session::Storage::Secure 0.010 ();
  2         127741  
  2         84  
11              
12 2     2   20 use Moo;
  2         3  
  2         10  
13 2     2   1642 use Dancer2::Core::Types;
  2         3286  
  2         1794  
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   1692 my ($self) = @_;
56 7         78 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       44 $args{default_duration} = $self->default_duration
62             if $self->has_default_duration;
63 7         154 return Session::Storage::Secure->new(%args);
64             }
65              
66             sub _change_id {
67             # This is a noop with session cookies.
68 4     4   245 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 16     16 0 233674 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 24     24   28097 sub _flush { return }
97              
98             # We have nothing to destroy, either; cookie expiration is all that matters
99 8     8   11267 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__