user sessions: use database instead of filesystem
User sessions will be stored in database and not in files anymore. CGI::Session is not used anymore for this purpose. The new module user_sessions.pm provides functions on new database table user_sessions.
This commit is contained in:
231
lib/calcms/user_sessions.pm
Normal file
231
lib/calcms/user_sessions.pm
Normal file
@@ -0,0 +1,231 @@
|
||||
package user_sessions;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
no warnings 'redefine';
|
||||
|
||||
use Digest::MD5();
|
||||
|
||||
use time;
|
||||
|
||||
# access user name by session id
|
||||
|
||||
# table: calcms_user_sessions
|
||||
# columns: id,
|
||||
# user,
|
||||
# timeout,
|
||||
# pid,
|
||||
# start (timestamp),
|
||||
# end (timestamp),
|
||||
|
||||
use base 'Exporter';
|
||||
our @EXPORT_OK = qw(get_columns get insert update delete);
|
||||
|
||||
sub debug;
|
||||
|
||||
sub get_columns($) {
|
||||
my $config = shift;
|
||||
|
||||
my $dbh = db::connect($config);
|
||||
my $cols = db::get_columns( $dbh, 'calcms_user_sessions' );
|
||||
my $columns = {};
|
||||
for my $col (@$cols) {
|
||||
$columns->{$col} = 1;
|
||||
}
|
||||
return $columns;
|
||||
}
|
||||
|
||||
#map schedule id to id
|
||||
sub get($$) {
|
||||
my $config = shift;
|
||||
my $condition = shift;
|
||||
|
||||
my $dbh = db::connect($config);
|
||||
|
||||
my @conditions = ();
|
||||
my @bind_values = ();
|
||||
|
||||
if ( ( defined $condition->{id} ) && ( $condition->{id} ne '' ) ) {
|
||||
push @conditions, 'id=?';
|
||||
push @bind_values, $condition->{id};
|
||||
}
|
||||
|
||||
if ( ( defined $condition->{user} ) && ( $condition->{user} ne '' ) ) {
|
||||
push @conditions, 'user=?';
|
||||
push @bind_values, $condition->{user};
|
||||
}
|
||||
|
||||
if ( ( defined $condition->{session_id} ) && ( $condition->{session_id} ne '' ) ) {
|
||||
push @conditions, 'session_id=?';
|
||||
push @bind_values, $condition->{session_id};
|
||||
}
|
||||
|
||||
if ( ( defined $condition->{start} ) && ( $condition->{start} ne '' ) ) {
|
||||
push @conditions, 'start>?';
|
||||
push @bind_values, $condition->{start};
|
||||
}
|
||||
|
||||
my $conditions = '';
|
||||
$conditions = " where " . join( " and ", @conditions ) if @conditions;
|
||||
|
||||
my $query = qq{
|
||||
select *
|
||||
from calcms_user_sessions
|
||||
$conditions
|
||||
order by start
|
||||
};
|
||||
|
||||
my $entries = db::get( $dbh, $query, \@bind_values );
|
||||
return $entries;
|
||||
}
|
||||
|
||||
# insert entry and return database id
|
||||
sub insert ($$) {
|
||||
my $config = shift;
|
||||
my $entry = shift;
|
||||
|
||||
return undef unless defined $entry->{user};
|
||||
return undef unless defined $entry->{timeout};
|
||||
|
||||
unless ( defined $entry->{session_id} ) {
|
||||
my $md5 = Digest::MD5->new();
|
||||
$md5->add( $$, time(), rand(time) );
|
||||
$entry->{session_id} = $md5->hexdigest();
|
||||
}
|
||||
|
||||
$entry->{pid} = $$;
|
||||
$entry->{expires_at} = time::time_to_datetime( time() + $entry->{timeout} );
|
||||
|
||||
my $dbh = db::connect($config);
|
||||
return db::insert( $dbh, 'calcms_user_sessions', $entry );
|
||||
}
|
||||
|
||||
# start session and return generated session id
|
||||
sub start($$) {
|
||||
my $config = shift;
|
||||
my $entry = shift;
|
||||
|
||||
return undef unless defined $entry->{user};
|
||||
return undef unless defined $entry->{timeout};
|
||||
|
||||
my $id = insert(
|
||||
$config,
|
||||
{
|
||||
user => $entry->{user},
|
||||
timeout => $entry->{timeout},
|
||||
}
|
||||
);
|
||||
return undef unless defined $id;
|
||||
|
||||
my $sessions = get( $config, { id => $id } );
|
||||
return undef unless defined $sessions;
|
||||
|
||||
my $session = $sessions->[0];
|
||||
return undef unless defined $session;
|
||||
|
||||
return $session->{session_id};
|
||||
}
|
||||
|
||||
# expand session by timeout
|
||||
sub keep_alive ($$) {
|
||||
my $config = shift;
|
||||
my $entry = shift;
|
||||
|
||||
return undef unless defined $entry;
|
||||
|
||||
$entry->{pid} = $$;
|
||||
$entry->{expires_at} = time::time_to_datetime( time() + $entry->{timeout} );
|
||||
|
||||
my $dbh = db::connect($config);
|
||||
return update( $config, $entry );
|
||||
}
|
||||
|
||||
# get session by session id and expand session if valid
|
||||
sub check($$) {
|
||||
my $config = shift;
|
||||
my $entry = shift;
|
||||
|
||||
return undef unless defined $entry;
|
||||
my $entries = get( $config, { session_id => $entry->{session_id} } );
|
||||
return undef unless defined $entry;
|
||||
|
||||
$entry = $entries->[0];
|
||||
return undef unless defined $entry;
|
||||
|
||||
my $now = time::time_to_datetime( time() );
|
||||
return undef unless defined $entry->{expires_at};
|
||||
return undef unless defined $entry->{user};
|
||||
|
||||
return undef if $entry->{expires_at} le $now;
|
||||
return undef if $entry->{end} && ( $entry->{end} le $now );
|
||||
|
||||
keep_alive( $config, $entry );
|
||||
return $entry;
|
||||
}
|
||||
|
||||
# stop session
|
||||
sub stop ($$) {
|
||||
my $config = shift;
|
||||
my $entry = shift;
|
||||
|
||||
return undef unless defined $entry;
|
||||
|
||||
my $entries = get( $config, { session_id => $entry->{session_id} } );
|
||||
return undef unless defined $entries;
|
||||
|
||||
$entry = $entries->[0];
|
||||
return undef unless defined $entry;
|
||||
|
||||
$entry->{end} = time::time_to_datetime( time() );
|
||||
|
||||
my $dbh = db::connect($config);
|
||||
return update( $config, $entry );
|
||||
}
|
||||
|
||||
#schedule id to id
|
||||
sub update ($$) {
|
||||
my $config = shift;
|
||||
my $entry = shift;
|
||||
|
||||
return undef unless defined $entry->{session_id};
|
||||
|
||||
my $dbh = db::connect($config);
|
||||
my $values = join( ",", map { $_ . '=?' } ( keys %$entry ) );
|
||||
my @bind_values = map { $entry->{$_} } ( keys %$entry );
|
||||
|
||||
push @bind_values, $entry->{session_id};
|
||||
|
||||
my $query = qq{
|
||||
update calcms_user_sessions
|
||||
set $values
|
||||
where session_id=?
|
||||
};
|
||||
return db::put( $dbh, $query, \@bind_values );
|
||||
}
|
||||
|
||||
#map schedule id to id
|
||||
sub delete($$) {
|
||||
my $config = shift;
|
||||
my $entry = shift;
|
||||
|
||||
return undef unless defined $entry->{session_id};
|
||||
|
||||
my $dbh = db::connect($config);
|
||||
|
||||
my $query = qq{
|
||||
delete
|
||||
from calcms_user_sessions
|
||||
where session_id=?
|
||||
};
|
||||
my $bind_values = [ $entry->{session_id} ];
|
||||
|
||||
return db::put( $dbh, $query, $bind_values );
|
||||
}
|
||||
|
||||
sub error($) {
|
||||
my $msg = shift;
|
||||
print "ERROR: $msg<br/>\n";
|
||||
}
|
||||
|
||||
#do not delete last line!
|
||||
1;
|
||||
Reference in New Issue
Block a user