diff --git a/docs/changelog/7.x.x.txt b/docs/changelog/7.x.x.txt
index e107a5039..acf7de02e 100644
--- a/docs/changelog/7.x.x.txt
+++ b/docs/changelog/7.x.x.txt
@@ -55,6 +55,7 @@
- rfe: After committing a version there is now a back to site link
- rfe: Added sort order to Folder assets
- rfe: Added canEdit and canAddFile template vars to Folder assets
+ - rfe: Add logged-in time to Login History
7.5.22
- fixed: Layout template now gets prepared correctly
diff --git a/docs/upgrades/upgrade_7.5.21-7.6.0.pl b/docs/upgrades/upgrade_7.5.21-7.6.0.pl
index 6674a4c7c..91e876cbe 100644
--- a/docs/upgrades/upgrade_7.5.21-7.6.0.pl
+++ b/docs/upgrades/upgrade_7.5.21-7.6.0.pl
@@ -32,6 +32,7 @@ addUrlToAssetHistory ( $session ); ##This sub MUST GO FIRST
removeDoNothingOnDelete( $session );
fixIsPublicOnTemplates ( $session );
addSortOrderToFolder( $session );
+addLoginTimeStats( $session );
addEMSBadgeTemplate ( $session );
redirectChoice ($session);
@@ -68,6 +69,15 @@ sub addSortOrderToFolder {
print "Done.\n" unless $quiet;
}
+#----------------------------------------------------------------------------
+sub addLoginTimeStats {
+ my $session = shift;
+ print "\tAdding login time statistics... " unless $quiet;
+ $session->db->write( "alter table userLoginLog add column sessionId varchar(22)" );
+ $session->db->write( "alter table userLoginLog add column lastPageViewed int(11)" );
+ print "Done.\n" unless $quiet;
+}
+
#----------------------------------------------------------------------------
sub removeDoNothingOnDelete {
my $session = shift;
diff --git a/lib/WebGUI/Auth.pm b/lib/WebGUI/Auth.pm
index d3bfc430d..9dd26c7b2 100644
--- a/lib/WebGUI/Auth.pm
+++ b/lib/WebGUI/Auth.pm
@@ -102,13 +102,18 @@ sub _isValidUsername {
#-------------------------------------------------------------------
sub _logLogin {
my $self = shift;
- $self->session->db->write("insert into userLoginLog values (?,?,?,?,?)",
- [ $_[0],
- $_[1],
- $self->session->datetime->time(),
- $self->session->env->getIp,
- $self->session->env->get("HTTP_USER_AGENT") ]
- );
+ $self->timeRecordSession;
+ $self->session->db->write("insert into userLoginLog values (?,?,?,?,?,?,?)",
+ [
+ $_[0],
+ $_[1],
+ $self->session->datetime->time(),
+ $self->session->env->getIp,
+ $self->session->env->get("HTTP_USER_AGENT"),
+ $self->session->getId,
+ $self->session->datetime->time(),
+ ]
+ );
}
@@ -911,6 +916,32 @@ sub showMessageOnLogin {
return $output;
}
+#----------------------------------------------------------------------------
+
+=head2 timeRecordSession
+
+Record the last page viewed and the time viewed for the user
+
+=cut
+
+sub timeRecordSession {
+ my $self = shift;
+ my ($nonTimeRecordedRows) = $self->session->db->quickArray("select count(*) from userLoginLog where lastPageViewed = timeStamp and sessionId = ? ", [$self->session->getId] );
+ if ($nonTimeRecordedRows eq "1") {
+ # We would normally expect to only find one entry
+ $self->session->db->write("update userLoginLog set lastPageViewed = (select lastPageView from userSession where sessionId = ?) where lastPageViewed = timeStamp and sessionId = ? ",
+ [ $self->session->getId,
+ $self->session->getId]);
+ } elsif ($nonTimeRecordedRows eq "0") {
+ # Do nothing
+ } else {
+ # If something strange happened and we ended up with > 1 matching rows, cut our losses and remove offending userLoginLog rows (otherwise we
+ # could end up with ridiculously long user recorded times)
+ $self->session->errorHandler->warn("More than 1 old userLoginLog rows found, removing offending rows");
+ $self->session->db->write("delete from userLoginLog where lastPageViewed = timeStamp and sessionId = ? ", [$self->session->getId] );
+ }
+}
+
#-------------------------------------------------------------------
=head2 user ( [user] )
diff --git a/lib/WebGUI/Operation/LoginHistory.pm b/lib/WebGUI/Operation/LoginHistory.pm
index c940ee112..dce1bb102 100644
--- a/lib/WebGUI/Operation/LoginHistory.pm
+++ b/lib/WebGUI/Operation/LoginHistory.pm
@@ -61,7 +61,21 @@ sub www_viewLoginHistory {
$row[$i] .= '
'.$data{status}.' | ';
$row[$i] .= ''.$session->datetime->epochToHuman($data{timeStamp},"%H:%n%p %M/%D/%y").' | ';
$row[$i] .= ''.$data{ipAddress}.' | ';
- $row[$i] .= ''.$data{userAgent}.' | ';
+ $row[$i] .= ''.$data{userAgent}.' | ';
+ $row[$i] .= ''.$data{sessionId}.' | ';
+ if ($data{lastPageViewed}) {
+ if ($data{lastPageViewed} == $data{timeStamp}) {
+ $row[$i] .= "Active | ";
+ $row[$i] .= "Active | ";
+ } else {
+ $row[$i] .= ''.$session->datetime->epochToHuman($data{lastPageViewed},"%H:%n%p %M/%D/%y").' | ';
+ my ($interval, $units) = $session->datetime->secondsToInterval($data{lastPageViewed} - $data{timeStamp});
+ $row[$i] .= "$interval $units | ";
+ }
+ } else {
+ $row[$i] .= " | ";
+ $row[$i] .= " | ";
+ }
$i++;
}
$sth->finish;
@@ -72,7 +86,10 @@ sub www_viewLoginHistory {
$output .= ''.$i18n->get(434).' | ';
$output .= ''.$i18n->get(429).' | ';
$output .= ''.$i18n->get(431).' | ';
- $output .= ''.$i18n->get(433).' | ';
+ $output .= ''.$i18n->get(433).' | ';
+ $output .= '' . $i18n->get( 435 ) . ' | ';
+ $output .= '' . $i18n->get( 430 ) . ' | ';
+ $output .= '' . $i18n->get( "session length" ) . ' | ';
$output .= $p->getPage($session->form->process("pn"));
$output .= '';
$output .= $p->getBar($session->form->process("pn"));
diff --git a/lib/WebGUI/Operation/User.pm b/lib/WebGUI/Operation/User.pm
index dba5a4d5e..8775d2e6c 100644
--- a/lib/WebGUI/Operation/User.pm
+++ b/lib/WebGUI/Operation/User.pm
@@ -663,33 +663,54 @@ sub www_listUsers {
+
+
';
my $p = doUserSearch($session,"listUsers",1);
foreach my $data (@{$p->getPageData}) {
- $output .= '';
- $output .= '| '.$status{$data->{status}}.' | ';
- $output .= ''.$data->{username}.' | ';
- $output .= ''.$data->{email}.' | ';
- $output .= ''.$session->datetime->epochToHuman($data->{dateCreated},"%z").' | ';
- $output .= ''.$session->datetime->epochToHuman($data->{lastUpdated},"%z").' | ';
- my ($lastLoginStatus, $lastLogin) = $session->db->quickArray("select status,timeStamp from userLoginLog where
- userId=".$session->db->quote($data->{userId})." order by timeStamp DESC");
- if ($lastLogin) {
- $output .= ''.$session->datetime->epochToHuman($lastLogin).' | ';
- } else {
- $output .= ' - | ';
- }
- if ($lastLoginStatus) {
- $output .= ''.$lastLoginStatus.' | ';
- } else {
- $output .= ' - | ';
- }
- $output .= '
';
+ $output .= '';
+ $output .= '| '.$status{$data->{status}}.' | ';
+ $output .= ''.$data->{username}.' | ';
+ $output .= ''.$data->{email}.' | ';
+ $output .= ''.$session->datetime->epochToHuman($data->{dateCreated},"%z").' | ';
+ $output .= ''.$session->datetime->epochToHuman($data->{lastUpdated},"%z").' | ';
+ # Total Time Recorded is computed from userLoginLog table
+ my ($totalTimeRecorded)= $session->db->quickArray("select sum(lastPageViewed-timeStamp) from userLoginLog where userId = ?", [$data->{userId}]);
+ my ($lastLoginStatus, $lastLogin, $lastPageView)
+ = $session->db->quickArray(
+ "select ull.status, ull.timeStamp, us.lastPageView
+ from userLoginLog ull, userSession us
+ where ull.sessionId = us.sessionId and ull.lastPageViewed != ull.timeStamp and
+ ull.userId=".$session->db->quote($data->{userId})."
+ order by ull.timeStamp DESC"
+ );
+ if ($lastLogin) {
+ $output .= ''.$session->datetime->epochToHuman($lastLogin).' | ';
+ }
+ else {
+ $output .= ' - | ';
+ }
+ if ($lastLoginStatus) {
+ $output .= ''.$lastLoginStatus.' | ';
+ }
+ else {
+ $output .= ' - | ';
+ }
+ if ($lastPageView) {
+ $output .= ' '.$session->datetime->epochToHuman($lastPageView).' | ';
+ my ($interval, $units) = $session->datetime->secondsToInterval($totalTimeRecorded);
+ $output .= "$interval $units |
";
+ }
+ else {
+ $output .= " - | ";
+ $output .= " - | ";
+ }
+ $output .= '';
}
- $output .= '';
- $p->setAlphabeticalKey('username');
- $output .= $p->getBarTraditional;
+ $output .= '';
+ $p->setAlphabeticalKey('username');
+ $output .= $p->getBarTraditional;
my $submenu = _submenu(
$session,
{ workarea => $output, }
diff --git a/lib/WebGUI/Workflow/Activity/DeleteExpiredSessions.pm b/lib/WebGUI/Workflow/Activity/DeleteExpiredSessions.pm
index 5277f5014..b6dd12d13 100644
--- a/lib/WebGUI/Workflow/Activity/DeleteExpiredSessions.pm
+++ b/lib/WebGUI/Workflow/Activity/DeleteExpiredSessions.pm
@@ -68,21 +68,37 @@ See WebGUI::Workflow::Activity::execute() for details.
sub execute {
my $self = shift;
- my $sth = $self->session->db->read("select sessionId from userSession where expires",[time()]);
+ my $sth = $self->session->db->read("select sessionId, lastPageView from userSession where expires",[time()]);
my $time = time();
my $ttl = $self->getTTL;
- while (my ($sessionId) = $sth->array) {
+
+ while ( my ( $sessionId, $lastPageView ) = $sth->array ) {
+ # timeRecordSessions
+ my ($nonTimeRecordedRows) = $self->session->db->quickArray("select count(*) from userLoginLog where lastPageViewed = timeStamp and sessionId = ? ", [$sessionId] );
+ if ($nonTimeRecordedRows eq "1") {
+ # We would normally expect to only find one entry
+ $self->session->db->write("update userLoginLog set lastPageViewed = ? where lastPageViewed = timeStamp and sessionId = ? ",
+ [ $lastPageView, $sessionId ]);
+ } elsif ($nonTimeRecordedRows eq "0") {
+ # Do nothing
+ } else {
+ # If something strange happened and we ended up with > 1 matching rows, cut our losses and remove offending userLoginLog rows (otherwise we
+ # could end up with ridiculously long user recorded times)
+ $self->session->errorHandler->warn("More than 1 old userLoginLog rows found, removing offending rows");
+ $self->session->db->write("delete from userLoginLog where lastPageViewed = timeStamp and sessionId = ? ", [$sessionId] );
+ }
my $session = WebGUI::Session->open($self->session->config->getWebguiRoot, $self->session->config->getFilename, undef, undef, $sessionId, 1);
if (defined $session) {
$session->var->end;
$session->close;
}
if ((time() - $time) > $ttl) {
- $sth->finish;
+ $sth->finish;
return $self->WAITING;
}
- }
- return $self->COMPLETE;
+ }
+
+ return $self->COMPLETE;
}
diff --git a/lib/WebGUI/i18n/English/WebGUI.pm b/lib/WebGUI/i18n/English/WebGUI.pm
index ee1288776..080cbfcdf 100644
--- a/lib/WebGUI/i18n/English/WebGUI.pm
+++ b/lib/WebGUI/i18n/English/WebGUI.pm
@@ -4129,6 +4129,18 @@ LongTruncOk=1
context => q{Title of the template created by the Site Setup screen},
},
+ 'session length' => {
+ message => q{Session Length},
+ lastUpdated => 0,
+ context => q{The length the session has been alive},
+ },
+
+ "time recorded" => {
+ message => q{Time Recorded (excludes active sessions)},
+ lastUpdated => 0,
+ context => q{Column heading for the total logged in time for the user},
+ },
+
};
1;