File Coverage

blib/lib/HTTP/Session2/Base.pm
Criterion Covered Total %
statement 56 62 90.3
branch 9 12 75.0
condition n/a
subroutine 19 20 95.0
pod 5 11 45.4
total 89 105 84.7


line stmt bran cond sub pod time code
1             package HTTP::Session2::Base;
2 12     12   75050 use strict;
  12         25  
  12         406  
3 12     12   61 use warnings;
  12         25  
  12         321  
4 12     12   1079 use utf8;
  12         33  
  12         74  
5 12     12   566 use 5.008_001;
  12         48  
  12         516  
6              
7 12     12   8756 use Digest::SHA;
  12         45298  
  12         1079  
8 12     12   141 use Carp ();
  12         26  
  12         223  
9              
10 12     12   17842 use Mouse;
  12         557263  
  12         74  
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 12     12   9164 no Mouse;
  12         28  
  12         148  
86              
87             sub _data {
88 32     32   50 my $self = shift;
89 32 100       117 unless ($self->{_data}) {
90 15         64 $self->load_or_create();
91             }
92 32         142 $self->{_data};
93             }
94              
95             sub id {
96 27     27 0 60 my $self = shift;
97 27 50       71 unless ($self->{id}) {
98 0         0 $self->load_or_create();
99             }
100 27         134 $self->{id};
101             }
102              
103             sub load_or_create {
104 15     15 0 27 my $self = shift;
105 15 100       61 $self->load_session() || $self->create_session();
106             }
107              
108 1     1 0 153 sub load_session { die "Abstract method" }
109 1     1 0 959 sub create_session { die "Abstract method" }
110              
111             sub set {
112 13     13 1 3677 my ($self, $key, $value) = @_;
113 13         107 $self->_data->{$key} = $value;
114 13         71 $self->is_dirty(1);
115             }
116              
117             sub get {
118 4     4 1 1342 my ($self, $key) = @_;
119 4         18 $self->_data->{$key};
120             }
121              
122             sub remove {
123 1     1 1 2 my ($self, $key) = @_;
124 1         4 $self->is_dirty(1);
125 1         4 delete $self->_data->{$key};
126             }
127              
128             sub validate_xsrf_token {
129 2     2 1 1284 my ($self, $token) = @_;
130              
131             # If user does not have any session data, user don't need a XSRF protection.
132 2 50       4 return 1 unless %{$self->_data};
  2         9  
133 2 50       11 return 0 unless defined $token;
134 2 100       9 return 1 if $token eq $self->xsrf_token;
135 1         6 return 0;
136             }
137              
138             sub finalize_plack_response {
139 0     0 1 0 my ($self, $res) = @_;
140              
141 0         0 my @cookies = $self->finalize();
142 0         0 while (my ($name, $cookie) = splice @cookies, 0, 2) {
143 0         0 my $baked = Cookie::Baker::bake_cookie( $name, $cookie );
144 0         0 $res->headers->push_header('Set-Cookie' => $baked);
145             }
146             }
147              
148             sub finalize_psgi_response {
149 18     18 0 2467 my ($self, $res) = @_;
150 18         81 my @cookies = $self->finalize();
151 18         90 while (my ($name, $cookie) = splice @cookies, 0, 2) {
152 28         89 my $baked = Cookie::Baker::bake_cookie( $name, $cookie );
153 28         1451 push @{$res->[1]}, (
  28         219  
154             'Set-Cookie' => $baked,
155             );
156             }
157             }
158              
159 1     1 0 616 sub finalize { die "Abstract method" }
160              
161             1;
162             __END__