line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Dancer::Session::ElasticSearch; |
2
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
891
|
use strict; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
42
|
|
4
|
1
|
|
|
1
|
|
6
|
use warnings; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
37
|
|
5
|
1
|
|
|
1
|
|
17
|
use base 'Dancer::Session::Abstract'; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
707
|
|
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
use v5.10.0; |
8
|
|
|
|
|
|
|
use Dancer qw(:syntax); |
9
|
|
|
|
|
|
|
use ElasticSearch; |
10
|
|
|
|
|
|
|
use Try::Tiny; |
11
|
|
|
|
|
|
|
use Digest::HMAC_SHA1 qw(); |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
our $VERSION = 1.007; |
14
|
|
|
|
|
|
|
our $es = undef; |
15
|
|
|
|
|
|
|
our $data = {}; |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
sub create { |
18
|
|
|
|
|
|
|
my $self = __PACKAGE__->new; |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
$data = {}; |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
my $id = $self->_es->index( data => $data )->{_id}; |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
$self->id( $self->_sign($id) ); |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
return $self; |
27
|
|
|
|
|
|
|
} |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
sub flush { |
30
|
|
|
|
|
|
|
my $self = shift; |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
my $session_data = $data->{$self->id}; |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
try { |
35
|
|
|
|
|
|
|
my $id = $self->_verify( $self->id ); |
36
|
|
|
|
|
|
|
$self->_es->index( data => {%$session_data}, id => $id ); |
37
|
|
|
|
|
|
|
$data = {}; |
38
|
|
|
|
|
|
|
} |
39
|
|
|
|
|
|
|
catch { |
40
|
|
|
|
|
|
|
warning("Could not flush session ID ". $self->id . " - $_"); |
41
|
|
|
|
|
|
|
return; |
42
|
|
|
|
|
|
|
}; |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
return $self; |
45
|
|
|
|
|
|
|
} |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
sub retrieve { |
48
|
|
|
|
|
|
|
my ( $self, $session_id ) = @_; |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
my $session_data = try { |
51
|
|
|
|
|
|
|
# return what we have if the session is_lazy |
52
|
|
|
|
|
|
|
return $data->{$session_id} if defined $data->{$session_id} and $self->is_lazy; |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
my $id = $self->_verify($session_id); |
55
|
|
|
|
|
|
|
my $get = $self->_es->get( id => $id, ignore_missing => 1 ); |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
# store data locally if we're lazy |
58
|
|
|
|
|
|
|
my $source = defined $get ? $get->{_source} : {}; |
59
|
|
|
|
|
|
|
$data->{$session_id} = $source if $self->is_lazy; |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
return $source; |
62
|
|
|
|
|
|
|
} |
63
|
|
|
|
|
|
|
catch { |
64
|
|
|
|
|
|
|
warning("Could not retrieve session ID $session_id - $_"); |
65
|
|
|
|
|
|
|
return; |
66
|
|
|
|
|
|
|
}; |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
$session_data->{id} = $session_id; |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
return bless $session_data, __PACKAGE__; |
71
|
|
|
|
|
|
|
} |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
sub destroy { |
74
|
|
|
|
|
|
|
my $self = shift; |
75
|
|
|
|
|
|
|
try { |
76
|
|
|
|
|
|
|
$self->_es->delete( id => $self->id ); |
77
|
|
|
|
|
|
|
$self->write_session_id(0); |
78
|
|
|
|
|
|
|
delete $self->{id}; |
79
|
|
|
|
|
|
|
$data = {}; |
80
|
|
|
|
|
|
|
} |
81
|
|
|
|
|
|
|
catch { |
82
|
|
|
|
|
|
|
warning( "Could not delete session ID " . $self->id . " - $_" ); |
83
|
|
|
|
|
|
|
return; |
84
|
|
|
|
|
|
|
}; |
85
|
|
|
|
|
|
|
} |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
sub init { } |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
sub is_lazy { |
90
|
|
|
|
|
|
|
return setting('session_options')->{is_lazy} // 1; |
91
|
|
|
|
|
|
|
} |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
# internal methods |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
sub _es { |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
return $es if defined $es; |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
my $settings = setting('session_options'); |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
$es = ElasticSearch->new( %{ $settings->{connection} } ); |
102
|
|
|
|
|
|
|
$es->use_type( $settings->{type} // 'session' ); |
103
|
|
|
|
|
|
|
$es->use_index( $settings->{index} // 'session' ); |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
return $es; |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
} |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
sub _sign { |
110
|
|
|
|
|
|
|
my ( $self, $id ) = @_; |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
my $settings = setting('session_options'); |
113
|
|
|
|
|
|
|
my $length = $settings->{signing}{length} || 10; |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
my $salt = join "", |
116
|
|
|
|
|
|
|
( '.', '/', 0 .. 9, 'A' .. 'Z', 'a' .. 'z' ) |
117
|
|
|
|
|
|
|
[ map { rand 64 } ( 1 .. $length ) ]; |
118
|
|
|
|
|
|
|
my $hash = $self->_hash( $id, $salt ); |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
return ( $hash . $salt . $id ); |
121
|
|
|
|
|
|
|
} |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
sub _verify { |
124
|
|
|
|
|
|
|
my ( $self, $string ) = @_; |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
my $settings = setting('session_options'); |
127
|
|
|
|
|
|
|
my $length = $settings->{signing}{length} || 10; |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
my ( $hash, $salt, $id ) = unpack "A${length}A${length}A*", $string; |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
return $hash eq $self->_hash( $id, $salt ) |
132
|
|
|
|
|
|
|
? $id |
133
|
|
|
|
|
|
|
: die "Session ID not verified"; |
134
|
|
|
|
|
|
|
} |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
sub _hash { |
137
|
|
|
|
|
|
|
my ( $self, $id, $salt ) = @_; |
138
|
|
|
|
|
|
|
my $settings = setting('session_options'); |
139
|
|
|
|
|
|
|
my $secret = $settings->{signing}{secret}; |
140
|
|
|
|
|
|
|
my $length = $settings->{signing}{length} || 10; |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
return |
143
|
|
|
|
|
|
|
lc substr( Digest::HMAC_SHA1::hmac_sha1_hex( $id, $secret . $salt ), |
144
|
|
|
|
|
|
|
0, $length ); |
145
|
|
|
|
|
|
|
} |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
1; |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
__END__ |