File Coverage

blib/lib/HTTP/Session2/Base.pm
Criterion Covered Total %
statement 62 62 100.0
branch 12 12 100.0
condition n/a
subroutine 20 20 100.0
pod 5 11 45.4
total 99 105 94.2


line stmt bran cond sub pod time code
1             package HTTP::Session2::Base;
2 13     13   49633 use strict;
  13         32  
  13         478  
3 13     13   66 use warnings;
  13         25  
  13         331  
4 13     13   1802 use utf8;
  13         31  
  13         81  
5 13     13   482 use 5.008_001;
  13         44  
  13         529  
6              
7 13     13   14274 use Digest::SHA;
  13         36570  
  13         675  
8 13     13   95 use Carp ();
  13         25  
  13         251  
9              
10 13     13   12493 use Mouse;
  13         511620  
  13         75  
11              
12             has env => (
13             is => 'ro',
14             required => 1,
15             );
16              
17             has session_cookie => (
18             is => 'ro',
19             lazy => 1,
20             default => sub {
21             +{
22             httponly => 1,
23             secure => 0,
24             name => 'hss_session',
25             path => '/',
26             },
27             },
28             # Need shallow copy
29             trigger => sub {
30             my $self = shift;
31             $self->{session_cookie} = +{%{$self->{session_cookie}}};
32             },
33             );
34              
35             has xsrf_cookie => (
36             is => 'ro',
37             lazy => 1,
38             default => sub {
39             # httponly must be false. AngularJS need to read this value.
40             +{
41             httponly => 0,
42             secure => 0,
43             name => 'XSRF-TOKEN',
44             path => '/',
45             },
46             },
47             # Need shallow copy
48             trigger => sub {
49             my $self = shift;
50             $self->{xsrf_cookie} = +{%{$self->{xsrf_cookie}}};
51             },
52             );
53              
54             has hmac_function => (
55             is => 'ro',
56             default => sub { \&Digest::SHA::sha1_hex },
57             );
58              
59             has is_dirty => (
60             is => 'rw',
61             default => sub { 0 },
62             );
63              
64             has is_fresh => (
65             is => 'rw',
66             default => sub { 0 },
67             );
68              
69             has necessary_to_send => (
70             is => 'rw',
71             default => sub { 0 },
72             );
73              
74             has secret => (
75             is => 'ro',
76             required => 1,
77             trigger => sub {
78             my ($self, $secret) = @_;
79             if (length($secret) < 20) {
80             Carp::cluck("Secret string too short");
81             }
82             },
83             );
84              
85 13     13   9599 no Mouse;
  13         32  
  13         75  
86              
87             sub _data {
88 93     93   134 my $self = shift;
89 93 100       332 unless ($self->{_data}) {
90 22         111 $self->load_or_create();
91             }
92 93         348 $self->{_data};
93             }
94              
95             sub id {
96 89     89 0 20157 my $self = shift;
97 89 100       278 unless ($self->{id}) {
98 26         69 $self->load_or_create();
99             }
100 89         655 $self->{id};
101             }
102              
103             sub load_or_create {
104 48     48 0 407 my $self = shift;
105 48 100       211 $self->load_session() || $self->create_session();
106             }
107              
108 1     1 0 255 sub load_session { die "Abstract method" }
109 1     1 0 1038 sub create_session { die "Abstract method" }
110              
111             sub set {
112 26     26 1 6089 my ($self, $key, $value) = @_;
113 26         111 $self->_data->{$key} = $value;
114 26         153 $self->is_dirty(1);
115             }
116              
117             sub get {
118 25     25 1 1588 my ($self, $key) = @_;
119 25         82 $self->_data->{$key};
120             }
121              
122             sub remove {
123 1     1 1 3 my ($self, $key) = @_;
124 1         5 $self->is_dirty(1);
125 1         4 delete $self->_data->{$key};
126             }
127              
128             sub validate_xsrf_token {
129 16     16 1 3334 my ($self, $token) = @_;
130              
131             # If user does not have any session data, user don't need a XSRF protection.
132 16 100       23 return 1 unless %{$self->_data};
  16         44  
133 14 100       41 return 0 unless defined $token;
134 12 100       72 return 1 if $token eq $self->xsrf_token;
135 3         41 return 0;
136             }
137              
138             sub finalize_plack_response {
139 2     2 1 84 my ($self, $res) = @_;
140              
141 2         11 my @cookies = $self->finalize();
142 2         11 while (my ($name, $cookie) = splice @cookies, 0, 2) {
143 4         117 my $baked = Cookie::Baker::bake_cookie( $name, $cookie );
144 4         255 $res->headers->push_header('Set-Cookie' => $baked);
145             }
146             }
147              
148             sub finalize_psgi_response {
149 46     46 0 4323 my ($self, $res) = @_;
150 46         200 my @cookies = $self->finalize();
151 46         233 while (my ($name, $cookie) = splice @cookies, 0, 2) {
152 52         178 my $baked = Cookie::Baker::bake_cookie( $name, $cookie );
153 52         2569 push @{$res->[1]}, (
  52         390  
154             'Set-Cookie' => $baked,
155             );
156             }
157             }
158              
159 1     1 0 516 sub finalize { die "Abstract method" }
160              
161             1;
162             __END__