package CommsLog;
# switch on query output to console using "SQL_TRACE=1 dance"
use Dancer2;
use DateTime;
use Local::DB;
use Local::Utils;
use Data::Printer;
use SQL::Abstract::More;
# warn setting('environment'); # dispatch.cgi requires manual set in BEGIN block
# turn off datetime objects:
# $Local::DBIx::Simple::Result::NO_AUTO_DATE_INFLATION = 1;
my $dbix = Local::DB->dbix({ dbname => 'hilis4' });
# maximum number of records to retrieve ----------------------------------------
my $max_msg_num = setting('max_results');
#-------------------------------------------------------------------------------
our $VERSION = '0.01';
hook before => sub {
$ENV{SQL_TRACE} ||= setting('enable_sql_trace'); # don't override if already set
return if request->path_info =~ m!^/index!; # don't need a session for this
my $vars = request->parameters->as_hashref; _debug($vars);
my $session_id = $vars->{_sid} or halt 'Not logged into HILIS.';
check_session($session_id)
or halt 'Session expired. Please return to HILIS and try again.';
};
hook before_template_render => sub {
my $tokens = shift;
my %uri = map { $_ => uri_for('/' . $_) } qw(search new_record);
$tokens->{uri_for} = \%uri;
$tokens->{session_id} =
body_parameters->get('_sid') || query_parameters->get('_sid');
};
# original route/tt:
get '/index' => sub { template index => {}, { layout => 'default' } };
get '/' => sub { template 'main' };
post '/search' => sub {
my $vars = request->parameters->as_hashref; _debug($vars);
my $results = do_search($vars); # p $results;
template 'main', { results => $results };
};
post '/new_record' => sub {
# get user.id corresponding to session id:
my $user_id = get_user_id( body_parameters->get('_sid') ); # p $user_id;
my $details = body_parameters->get('details');
my %h = (
user_id => $user_id,
details => $details,
);
my $res = $dbix->insert('general_comms_log', \%h);
if ( $res->rows ) {
var msg => 'input success';
}
else {
var msg => 'input failed'; # may not get this far, probably 500 error
}
forward '/search', { details => $details };
};
#===============================================================================
sub do_search {
my $vars = shift; # username, details, start_date, end_date
my @cols = ( 'l.details', 'u.first_name', 'u.last_name', 'l.time' );
my @rels = ( 'general_comms_log|l' => 'l.user_id=u.id' => 'users|u' );
my %params = (
-columns => \@cols,
-where => get_search_params($vars),
-from => [ -join => @rels ],
); # p \%params;
my ($sql, @bind) = SQL::Abstract::More->new->select(%params); # p [$sql, \@bind];
{ # check count, return if excessive (> $max_msg_num):
local $params{'-columns'} = 'COUNT(*)';
my ($sql, @bind) = SQL::Abstract::More->new->select(%params); # p [$sql, \@bind];
my $n = $dbix->query($sql, @bind)->value;
if ( $n > $max_msg_num ) {
var msg => "too many records found ($n), please limit search"
. " and retry ...";
var total => $n;
return undef;
}
}
my $res = $dbix->query($sql, @bind)->hashes;
return $res;
}
sub get_search_params {
my $vars = shift;
my %h;
if ( my $username = $vars->{username} ) { # search username & last_name
push @{ $h{'-or'} }, [
'u.username' => { -like => $username . '%' },
'u.last_name' => { -like => $username . '%' },
];
}
if ( my $details = $vars->{details} ) {
$h{'l.details'} = { -rlike => $details };
}
{ # dates:
my ($start_date, $end_date) = map reformat_date($vars->{$_}),
qw/start_date end_date/; # p [$start_date, $end_date];
my $date_key = 'DATE(l.time)';
if ( $start_date && $end_date ) {
$h{$date_key} = { -between => [$start_date, $end_date] };
}
else {
if ( $start_date ) {
$h{$date_key} = { '>=' => $start_date };
}
elsif ( $end_date ) {
$h{$date_key} = { '<=' => $end_date };
}
} # p \%h;
}
return \%h;
}
sub get_user_id {
my $session_id = shift; # p $session_id;
my @rels = ( 'sessions|s' => 's.userid=u.username' => 'users|u' );
my %params = (
-columns => 'u.id',
-where => { 's.id' => $session_id },
-from => [ -join => @rels ],
);
my ($sql, @bind) = SQL::Abstract::More->new->select(%params); # p [$sql, \@bind];
my $id = $dbix->query($sql, @bind)->value;
return $id;
}
sub check_session {
my $session_id = shift || return 0; # p $session_id;
my $now = Local::Utils::time_now; # p $now;
my %h = (
id => $session_id,
time => { '>' => $now->subtract( minutes => 30 ) },
);
return $dbix->count(sessions => \%h);
}
sub reformat_date { # returns date in yyyy-mm-dd format
my $str = shift || return; # p $str;
# $date =~ s/(^\d{1,2})\/(\d{1,2})\/(\d{4}$)/$3-$2-$1/;
my $dt = Local::Utils::date_string_to_datetime($str)
or die "cannot parse date string: $str"; # p $dt->ymd;
return $dt->ymd;
}
sub _debug { p @_ if setting('environment') =~ /^dev/ }
true;