File Coverage

blib/lib/HTTP/Session2/ServerStore.pm
Criterion Covered Total %
statement 87 87 100.0
branch 9 12 75.0
condition 6 6 100.0
subroutine 20 20 100.0
pod 0 7 0.0
total 122 132 92.4


line stmt bran cond sub pod time code
1             package HTTP::Session2::ServerStore;
2 3     3   767636 use strict;
  3         7  
  3         111  
3 3     3   16 use warnings;
  3         6  
  3         77  
4 3     3   17 use utf8;
  3         5  
  3         18  
5 3     3   145 use 5.008_001;
  3         11  
  3         231  
6              
7             our $VERSION = "1.08";
8              
9 3     3   26 use Carp ();
  3         5  
  3         65  
10 3     3   1660 use Digest::HMAC;
  3         1328  
  3         197  
11 3     3   1907 use Digest::SHA ();
  3         9881  
  3         71  
12 3     3   1885 use Cookie::Baker ();
  3         5909  
  3         71  
13 3     3   1268 use HTTP::Session2::Expired;
  3         10  
  3         95  
14 3     3   1309 use HTTP::Session2::Random;
  3         9  
  3         89  
15              
16 3     3   19 use Mouse;
  3         6  
  3         32  
17              
18             extends 'HTTP::Session2::Base';
19              
20             has store => (
21             is => 'ro',
22             required => 1,
23             lazy => 1,
24             default => sub {
25             unless (defined $_[0]->get_store) {
26             Carp::croak("store or get_store is required.");
27             }
28             $_[0]->get_store->()
29             },
30             );
31              
32             has get_store => (
33             is => 'ro',
34             isa => 'CodeRef',
35             required => 0,
36             );
37              
38             has xsrf_token => (
39             is => 'ro',
40             lazy => 1,
41             builder => '_build_xsrf_token',
42             );
43              
44 3     3   1601 no Mouse;
  3         6  
  3         17  
45              
46             sub load_session {
47 19     19 0 24 my $self = shift;
48              
49             # Load from cookie.
50 19         132 my $cookies = Cookie::Baker::crush_cookie($self->env->{HTTP_COOKIE});
51 19 100       829 if (my $session_id = $cookies->{$self->session_cookie->{name}}) {
52 16         78 my $data = $self->store->get($session_id);
53 16 50       246 if (defined $data) {
54 16         37 $self->{id} = $session_id;
55 16         27 $self->{_data} = $data;
56 16         101 return 1;
57             }
58             }
59             }
60              
61             sub create_session {
62 3     3 0 7 my $self = shift;
63              
64 3         16 $self->{id} = HTTP::Session2::Random::generate_session_id();
65 3         55 $self->{_data} = +{};
66 3         36 $self->is_fresh(1);
67             }
68              
69             sub regenerate_id {
70 2     2 0 788 my ($self) = @_;
71              
72             # Load original session first.
73 2         10 $self->load_session();
74              
75             # Remove original session from storage.
76 2         11 my $cookies = Cookie::Baker::crush_cookie($self->env->{HTTP_COOKIE});
77 2 50       70 if (my $session_id = $cookies->{$self->session_cookie->{name}}) {
78 2         14 $self->store->remove($session_id);
79             }
80              
81             # Clear XSRF token
82 2         11 delete $self->{xsrf_token};
83              
84             # Create new session.
85 2         10 $self->{id} = HTTP::Session2::Random::generate_session_id();
86 2         10 $self->necessary_to_send(1);
87 2         11 $self->is_dirty(1);
88             }
89              
90             sub expire {
91 2     2 0 630 my $self = shift;
92              
93             # Load original session first.
94             # # Is this needed?
95 2         8 $self->load_session();
96              
97             # Remove original session from storage.
98 2         17 my $cookies = Cookie::Baker::crush_cookie($self->env->{HTTP_COOKIE});
99 2 50       73 if (my $session_id = $cookies->{$self->session_cookie->{name}}) {
100 2         11 $self->store->remove($session_id);
101             }
102              
103             # Rebless to expired object.
104 2         18 bless $self, 'HTTP::Session2::Expired';
105              
106 2         6 return;
107             }
108              
109             sub _build_xsrf_token {
110 9     9   16 my $self = shift;
111              
112             # @kazuho san recommend to change this code as `hmax(secret, id, hmac_function)`.
113             # It makes secure. But we can't change this code for backward compatibility.
114             # We should change this code at HTTP::Session3.
115 9         27 Digest::HMAC::hmac_hex($self->id, $self->secret, $self->hmac_function);
116             }
117              
118             sub save_data {
119 14     14 0 20 my $self = shift;
120              
121 14 100       66 return unless $self->is_dirty;
122              
123 7         38 $self->store->set($self->id, $self->_data);
124             }
125              
126             sub finalize {
127 14     14 0 29 my $self = shift;
128 14         36 $self->save_data();
129 14         62 return $self->make_cookies();
130             }
131              
132             sub make_cookies {
133 14     14 0 19 my $self = shift;
134              
135 14 100 100     141 unless (
      100        
136             ($self->is_dirty && $self->is_fresh)
137             || $self->necessary_to_send
138             ) {
139 10         36 return ();
140             }
141              
142 4         9 my @cookies;
143              
144             # Finalize session cookie
145             {
146 4         5 my %cookie = %{$self->session_cookie};
  4         8  
  4         31  
147 4         12 my $name = delete $cookie{name};
148 4         16 push @cookies, $name => +{
149             %cookie,
150             value => $self->id,
151             };
152             }
153              
154             # Finalize XSRF cookie
155             {
156 4         9 my %cookie = %{$self->xsrf_cookie};
  4         7  
  4         37  
157 4         11 my $name = delete $cookie{name};
158 4         31 push @cookies, $name => +{
159             %cookie,
160             value => $self->xsrf_token,
161             };
162             }
163              
164 4         178 return @cookies;
165             }
166              
167             1;
168             __END__