| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Catalyst::Plugin::Session::Store::DBIC; |
|
2
|
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
841
|
use strict; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
26
|
|
|
4
|
1
|
|
|
1
|
|
5
|
use warnings; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
31
|
|
|
5
|
1
|
|
|
1
|
|
4
|
use base qw/Catalyst::Plugin::Session::Store::Delegate/; |
|
|
1
|
|
|
|
|
10
|
|
|
|
1
|
|
|
|
|
842
|
|
|
6
|
1
|
|
|
1
|
|
603505
|
use Catalyst::Exception; |
|
|
1
|
|
|
|
|
184007
|
|
|
|
1
|
|
|
|
|
35
|
|
|
7
|
1
|
|
|
1
|
|
796
|
use Catalyst::Plugin::Session::Store::DBIC::Delegate; |
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
8
|
|
|
8
|
1
|
|
|
1
|
|
886
|
use MIME::Base64 (); |
|
|
1
|
|
|
|
|
712
|
|
|
|
1
|
|
|
|
|
27
|
|
|
9
|
1
|
|
|
1
|
|
6
|
use MRO::Compat; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
22
|
|
|
10
|
1
|
|
|
1
|
|
969
|
use Storable (); |
|
|
1
|
|
|
|
|
3462
|
|
|
|
1
|
|
|
|
|
813
|
|
|
11
|
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
our $VERSION = '0.14'; |
|
13
|
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
=head1 NAME |
|
15
|
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
Catalyst::Plugin::Session::Store::DBIC - Store your sessions via DBIx::Class |
|
17
|
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
19
|
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
# Create a table in your database for sessions |
|
21
|
|
|
|
|
|
|
CREATE TABLE sessions ( |
|
22
|
|
|
|
|
|
|
id CHAR(72) PRIMARY KEY, |
|
23
|
|
|
|
|
|
|
session_data TEXT, |
|
24
|
|
|
|
|
|
|
expires INTEGER |
|
25
|
|
|
|
|
|
|
); |
|
26
|
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
# Create the corresponding table class |
|
28
|
|
|
|
|
|
|
package MyApp::Schema::Session; |
|
29
|
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
use base qw/DBIx::Class/; |
|
31
|
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
__PACKAGE__->load_components(qw/Core/); |
|
33
|
|
|
|
|
|
|
__PACKAGE__->table('sessions'); |
|
34
|
|
|
|
|
|
|
__PACKAGE__->add_columns(qw/id session_data expires/); |
|
35
|
|
|
|
|
|
|
__PACKAGE__->set_primary_key('id'); |
|
36
|
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
1; |
|
38
|
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
# In your application |
|
40
|
|
|
|
|
|
|
use Catalyst qw/Session Session::Store::DBIC Session::State::Cookie/; |
|
41
|
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
__PACKAGE__->config( |
|
43
|
|
|
|
|
|
|
# ... other items ... |
|
44
|
|
|
|
|
|
|
'Plugin::Session' => { |
|
45
|
|
|
|
|
|
|
dbic_class => 'DBIC::Session', # Assuming MyApp::Model::DBIC |
|
46
|
|
|
|
|
|
|
expires => 3600, |
|
47
|
|
|
|
|
|
|
}, |
|
48
|
|
|
|
|
|
|
); |
|
49
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
# Later, in a controller action |
|
51
|
|
|
|
|
|
|
$c->session->{foo} = 'bar'; |
|
52
|
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
54
|
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
This L<Catalyst::Plugin::Session> storage module saves session data in |
|
56
|
|
|
|
|
|
|
your database via L<DBIx::Class>. It's actually just a wrapper around |
|
57
|
|
|
|
|
|
|
L<Catalyst::Plugin::Session::Store::Delegate>; if you need complete |
|
58
|
|
|
|
|
|
|
control over how your sessions are stored, you probably want to use |
|
59
|
|
|
|
|
|
|
that instead. |
|
60
|
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
=head1 METHODS |
|
62
|
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
=head2 setup_finished |
|
64
|
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
Hook into the configured session class. |
|
66
|
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
=cut |
|
68
|
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
sub setup_finished { |
|
70
|
0
|
|
|
0
|
1
|
|
my $c = shift; |
|
71
|
|
|
|
|
|
|
|
|
72
|
0
|
0
|
|
|
|
|
return $c->next::method unless @_; |
|
73
|
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
# Try to determine id_field if it isn't set |
|
75
|
0
|
0
|
|
|
|
|
unless ($c->_session_plugin_config->{id_field}) { |
|
76
|
0
|
|
|
|
|
|
my $model = $c->session_store_model; |
|
77
|
0
|
0
|
|
|
|
|
my $rs = ref $model ? $model |
|
|
|
0
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
: $model->can('resultset_instance') ? $model->resultset_instance |
|
79
|
|
|
|
|
|
|
: $model; |
|
80
|
0
|
|
|
|
|
|
my @primary_columns = $rs->result_source->primary_columns; |
|
81
|
|
|
|
|
|
|
|
|
82
|
0
|
0
|
|
|
|
|
Catalyst::Exception->throw( |
|
83
|
|
|
|
|
|
|
message => __PACKAGE__ . qq/: Primary key consists of more than one column; please set id_field manually/ |
|
84
|
|
|
|
|
|
|
) if @primary_columns > 1; |
|
85
|
|
|
|
|
|
|
|
|
86
|
0
|
|
|
|
|
|
$c->_session_plugin_config->{id_field} = $primary_columns[0]; |
|
87
|
|
|
|
|
|
|
} |
|
88
|
|
|
|
|
|
|
|
|
89
|
0
|
|
|
|
|
|
$c->next::method(@_); |
|
90
|
|
|
|
|
|
|
} |
|
91
|
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
=head2 session_store_dbic_class |
|
93
|
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
Return the L<DBIx::Class> class name to be passed to C<< $c->model >>. |
|
95
|
|
|
|
|
|
|
Defaults to C<DBIC::Session>. |
|
96
|
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
=cut |
|
98
|
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
sub session_store_dbic_class { |
|
100
|
0
|
0
|
|
0
|
1
|
|
shift->_session_plugin_config->{dbic_class} || 'DBIC::Session'; |
|
101
|
|
|
|
|
|
|
} |
|
102
|
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
=head2 session_store_dbic_id_field |
|
104
|
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
Return the configured ID field name. Defaults to C<id>. |
|
106
|
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
=cut |
|
108
|
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
sub session_store_dbic_id_field { |
|
110
|
0
|
0
|
|
0
|
1
|
|
shift->_session_plugin_config->{id_field} || 'id'; |
|
111
|
|
|
|
|
|
|
} |
|
112
|
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
=head2 session_store_dbic_data_field |
|
114
|
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
Return the configured data field name. Defaults to C<session_data>. |
|
116
|
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
=cut |
|
118
|
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
sub session_store_dbic_data_field { |
|
120
|
0
|
0
|
|
0
|
1
|
|
shift->_session_plugin_config->{data_field} || 'session_data'; |
|
121
|
|
|
|
|
|
|
} |
|
122
|
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
=head2 session_store_dbic_expires_field |
|
124
|
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
Return the configured expires field name. Defaults to C<expires>. |
|
126
|
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
=cut |
|
128
|
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
sub session_store_dbic_expires_field { |
|
130
|
0
|
0
|
|
0
|
1
|
|
shift->_session_plugin_config->{expires_field} || 'expires'; |
|
131
|
|
|
|
|
|
|
} |
|
132
|
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
=head2 session_store_model |
|
134
|
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
Return the model used to find a session. |
|
136
|
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
=cut |
|
138
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
sub session_store_model { |
|
140
|
0
|
|
|
0
|
1
|
|
my ($c, $id) = @_; |
|
141
|
|
|
|
|
|
|
|
|
142
|
0
|
|
|
|
|
|
my $dbic_class = $c->session_store_dbic_class; |
|
143
|
0
|
0
|
|
|
|
|
$c->model($dbic_class, $id) or die "Couldn't find a model named $dbic_class"; |
|
144
|
|
|
|
|
|
|
} |
|
145
|
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
=head2 get_session_store_delegate |
|
147
|
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
Load the row corresponding to the specified session ID. If none is |
|
149
|
|
|
|
|
|
|
found, one is automatically created. |
|
150
|
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
=cut |
|
152
|
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
sub get_session_store_delegate { |
|
154
|
0
|
|
|
0
|
1
|
|
my ($c, $id) = @_; |
|
155
|
|
|
|
|
|
|
|
|
156
|
0
|
|
|
|
|
|
Catalyst::Plugin::Session::Store::DBIC::Delegate->new({ |
|
157
|
|
|
|
|
|
|
model => $c->session_store_model($id), |
|
158
|
|
|
|
|
|
|
id_field => $c->session_store_dbic_id_field, |
|
159
|
|
|
|
|
|
|
data_field => $c->session_store_dbic_data_field, |
|
160
|
|
|
|
|
|
|
}); |
|
161
|
|
|
|
|
|
|
} |
|
162
|
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
=head2 session_store_delegate_key_to_accessor |
|
164
|
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
Match the specified key and operation to the session ID and field |
|
166
|
|
|
|
|
|
|
name. |
|
167
|
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
=cut |
|
169
|
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
sub session_store_delegate_key_to_accessor { |
|
171
|
0
|
|
|
0
|
1
|
|
my $c = shift; |
|
172
|
0
|
|
|
|
|
|
my $key = $_[0]; |
|
173
|
0
|
|
|
|
|
|
my ($field, @args) = $c->next::method(@_); |
|
174
|
|
|
|
|
|
|
|
|
175
|
0
|
|
|
|
|
|
my ($type) = ($key =~ /^(\w+):/); |
|
176
|
|
|
|
|
|
|
|
|
177
|
0
|
0
|
|
|
|
|
$field = $c->session_store_dbic_id_field if $field eq 'id'; |
|
178
|
0
|
0
|
|
|
|
|
$field = $c->session_store_dbic_expires_field if $field eq 'expires'; |
|
179
|
0
|
0
|
0
|
|
|
|
$field = $c->session_store_dbic_data_field if $field eq 'session' or $field eq 'flash'; |
|
180
|
|
|
|
|
|
|
|
|
181
|
0
|
|
|
0
|
|
|
my $accessor = sub { shift->$type($key)->$field(@_) }; |
|
|
0
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
|
|
183
|
0
|
0
|
|
|
|
|
if ($field eq $c->session_store_dbic_data_field) { |
|
184
|
0
|
|
0
|
|
|
|
@args = map { MIME::Base64::encode(Storable::nfreeze($_ || '')) } @args; |
|
|
0
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
$accessor = sub { |
|
186
|
0
|
|
|
0
|
|
|
my $value = shift->$type($key)->$field(@_); |
|
187
|
0
|
0
|
|
|
|
|
return unless $value; |
|
188
|
0
|
|
|
|
|
|
return Storable::thaw(MIME::Base64::decode($value)); |
|
189
|
0
|
|
|
|
|
|
}; |
|
190
|
|
|
|
|
|
|
} |
|
191
|
|
|
|
|
|
|
|
|
192
|
0
|
|
|
|
|
|
return ($accessor, @args); |
|
193
|
|
|
|
|
|
|
} |
|
194
|
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
=head2 delete_session_data |
|
196
|
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
Delete the specified session from the backend store. |
|
198
|
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
=cut |
|
200
|
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
sub delete_session_data { |
|
202
|
0
|
|
|
0
|
1
|
|
my ($c, $key) = @_; |
|
203
|
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
# expires is stored on the session row for compatibility with Store::DBI |
|
205
|
0
|
0
|
|
|
|
|
return if $key =~ /^expires/; |
|
206
|
|
|
|
|
|
|
|
|
207
|
0
|
|
|
|
|
|
$c->session_store_model->search({ |
|
208
|
|
|
|
|
|
|
$c->session_store_dbic_id_field => $key, |
|
209
|
|
|
|
|
|
|
})->delete; |
|
210
|
|
|
|
|
|
|
} |
|
211
|
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
=head2 delete_expired_sessions |
|
213
|
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
Delete all expired sessions. |
|
215
|
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
=cut |
|
217
|
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
sub delete_expired_sessions { |
|
219
|
0
|
|
|
0
|
1
|
|
my $c = shift; |
|
220
|
|
|
|
|
|
|
|
|
221
|
0
|
|
|
|
|
|
$c->session_store_model->search({ |
|
222
|
|
|
|
|
|
|
$c->session_store_dbic_expires_field => { '<', time() }, |
|
223
|
|
|
|
|
|
|
})->delete; |
|
224
|
|
|
|
|
|
|
} |
|
225
|
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
=head1 CONFIGURATION |
|
227
|
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
The following parameters should be placed in your application |
|
229
|
|
|
|
|
|
|
configuration under the C<Plugin::Session> key. |
|
230
|
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
=head2 dbic_class |
|
232
|
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
(Required) The name of the L<DBIx::Class> that represents a session in |
|
234
|
|
|
|
|
|
|
the database. It is recommended that you provide only the part after |
|
235
|
|
|
|
|
|
|
C<MyApp::Model>, e.g. C<DBIC::Session>. |
|
236
|
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
If you are using L<Catalyst::Model::DBIC::Schema>, the following |
|
238
|
|
|
|
|
|
|
layout is recommended: |
|
239
|
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
=over 4 |
|
241
|
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
=item * C<MyApp::Schema> - your L<DBIx::Class::Schema> class |
|
243
|
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
=item * C<MyApp::Schema::Session> - your session table class |
|
245
|
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
=item * C<MyApp::Model::DBIC> - your L<Catalyst::Model::DBIC::Schema> class |
|
247
|
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
=back |
|
249
|
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
This module will then use C<< $c->model >> to access the appropriate |
|
251
|
|
|
|
|
|
|
result source from the composed schema matching the C<dbic_class> |
|
252
|
|
|
|
|
|
|
name. |
|
253
|
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
For more information, please see L<Catalyst::Model::DBIC::Schema>. |
|
255
|
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
=head2 expires |
|
257
|
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
Number of seconds for which sessions are active. |
|
259
|
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
Note that no automatic cleanup is done on your session data. To |
|
261
|
|
|
|
|
|
|
delete expired sessions, you can use the L</delete_expired_sessions> |
|
262
|
|
|
|
|
|
|
method with L<Catalyst::Plugin::Scheduler>. |
|
263
|
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
=head2 id_field |
|
265
|
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
The name of the field on your sessions table which stores the session |
|
267
|
|
|
|
|
|
|
ID. Defaults to C<id>. |
|
268
|
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
=head2 data_field |
|
270
|
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
The name of the field on your sessions table which stores session |
|
272
|
|
|
|
|
|
|
data. Defaults to C<session_data> for compatibility with |
|
273
|
|
|
|
|
|
|
L<Catalyst::Plugin::Session::Store::DBI>. |
|
274
|
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
=head2 expires_field |
|
276
|
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
The name of the field on your sessions table which stores the |
|
278
|
|
|
|
|
|
|
expiration time of the session. Defaults to C<expires>. |
|
279
|
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
=head1 SCHEMA |
|
281
|
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
Your sessions table should contain the following columns: |
|
283
|
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
id CHAR(72) PRIMARY KEY |
|
285
|
|
|
|
|
|
|
session_data TEXT |
|
286
|
|
|
|
|
|
|
expires INTEGER |
|
287
|
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
The C<id> column should probably be 72 characters. It needs to handle |
|
289
|
|
|
|
|
|
|
the longest string that can be returned by |
|
290
|
|
|
|
|
|
|
L<Catalyst::Plugin::Session/generate_session_id>, plus another eight |
|
291
|
|
|
|
|
|
|
characters for internal use. This is less than 72 characters when |
|
292
|
|
|
|
|
|
|
SHA-1 or MD5 is used, but SHA-256 will need all 72 characters. |
|
293
|
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
The C<session_data> column should be a long text field. Session data |
|
295
|
|
|
|
|
|
|
is encoded using L<MIME::Base64> before being stored in the database. |
|
296
|
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
Note that MySQL C<TEXT> fields only store 64 kB, so if your session |
|
298
|
|
|
|
|
|
|
data will exceed that size you'll want to use C<MEDIUMTEXT>, |
|
299
|
|
|
|
|
|
|
C<MEDIUMBLOB>, or larger. If you configure your |
|
300
|
|
|
|
|
|
|
L<DBIx::Class::ResultSource> to include the size of the column, you |
|
301
|
|
|
|
|
|
|
will receive warnings for this problem: |
|
302
|
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
This session requires 1180 bytes of storage, but your database |
|
304
|
|
|
|
|
|
|
column 'session_data' can only store 200 bytes. Storing this |
|
305
|
|
|
|
|
|
|
session may not be reliable; increase the size of your data field |
|
306
|
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
See L<DBIx::Class::ResultSource/add_columns> for more information. |
|
308
|
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
The C<expires> column stores the future expiration time of the |
|
310
|
|
|
|
|
|
|
session. This may be null for per-user and flash sessions. |
|
311
|
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
Note that you can change the column names using the L</id_field>, |
|
313
|
|
|
|
|
|
|
L</data_field>, and L</expires_field> configuration parameters. |
|
314
|
|
|
|
|
|
|
However, the column types must match the above. |
|
315
|
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
=head1 AUTHOR |
|
317
|
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
Daniel Westermann-Clark E<lt>danieltwc@cpan.orgE<gt> |
|
319
|
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
=head1 ACKNOWLEDGMENTS |
|
321
|
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
=over 4 |
|
323
|
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
=item * Andy Grundman, for L<Catalyst::Plugin::Session::Store::DBI> |
|
325
|
|
|
|
|
|
|
|
|
326
|
|
|
|
|
|
|
=item * David Kamholz, for most of the testing code (from |
|
327
|
|
|
|
|
|
|
L<Catalyst::Plugin::Authentication::Store::DBIC>) |
|
328
|
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
=item * Yuval Kogman, for assistance in converting to |
|
330
|
|
|
|
|
|
|
L<Catalyst::Plugin::Session::Store::Delegate> |
|
331
|
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
=item * Jay Hannah, for tests and warning when session size |
|
333
|
|
|
|
|
|
|
exceeds DBIx::Class storage size. |
|
334
|
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
=back |
|
336
|
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
=head1 COPYRIGHT |
|
338
|
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
Copyright (c) 2006 - 2009 |
|
340
|
|
|
|
|
|
|
the Catalyst::Plugin::Session::Store::DBIC L</AUTHOR> |
|
341
|
|
|
|
|
|
|
as listed above. |
|
342
|
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it |
|
344
|
|
|
|
|
|
|
under the same terms as Perl itself. |
|
345
|
|
|
|
|
|
|
|
|
346
|
|
|
|
|
|
|
=cut |
|
347
|
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
1; |