show user session stats

all roles having read-user-stats enabled can show a list of user
sessions (last login, creation times, and active flag) to find unused
accounts which could be deactivated.
This commit is contained in:
Milan
2020-03-01 14:57:26 +01:00
parent 9f8170507e
commit bf2128f13c
9 changed files with 206 additions and 35 deletions

View File

@@ -67,8 +67,6 @@ sub get ($$) {
$limit
};
#print STDERR Dumper($query).Dumper(\@bind_values);
my $results = db::get( $dbh, $query, \@bind_values );
return $results;
}
@@ -125,8 +123,6 @@ sub get_stats($$) {
$limit
};
#print STDERR Dumper($query).Dumper(\@bind_values);
my $results = db::get( $dbh, $query, \@bind_values );
for my $result (@$results) {
$result->{score} = 0;
@@ -193,7 +189,6 @@ sub update ($$) {
where user=? and project_id=? and studio_id=? and series_id=?
};
#print STDERR Dumper($query).Dumper(\@bind_values);
my $dbh = db::connect($config);
return db::put( $dbh, $query, \@bind_values );
}
@@ -203,25 +198,16 @@ sub increase ($$$) {
my $usecase = shift;
my $options = shift;
#print STDERR Dumper($usecase)." ".Dumper($options);
return undef unless defined $usecase;
return undef unless defined $options->{project_id};
return undef unless defined $options->{studio_id};
return undef unless defined $options->{series_id};
return undef unless defined $options->{user};
#print STDERR "ok\n";
my $columns = get_columns($config);
#print STDERR "columns:".Dumper($columns);
return undef unless defined $columns->{$usecase};
my $entries = get( $config, $options );
#print STDERR "exist:".Dumper($columns);
if ( scalar @$entries == 0 ) {
my $entry = {
project_id => $options->{project_id},
@@ -231,20 +217,37 @@ sub increase ($$$) {
$usecase => 1,
};
#print STDERR "user_stats::insert\n";
return insert( $config, $entry );
} elsif ( scalar @$entries == 1 ) {
my $entry = $entries->[0];
$entry->{$usecase}++ if defined
#print STDERR "user_stats::update\n";
return update( $config, $entry );
return update( $config, $entry );
} else {
print STDERR "user_stats: to few options given: $usecase," . Dumper($options) . "\n";
}
}
sub get_active_users{
my $config = shift;
my $dbh = db::connect($config);
my $query=qq{
select u.name login, u.full_name,
s.last_login, s.login_count,
u.disabled, u.created_at, u.created_by
from calcms_users u left join (
SELECT user , max(start) last_login, count(user) login_count
FROM calcms_user_sessions
group by user
) s on s.user=u.name
order by u.disabled, s.last_login desc, u.created_at desc
};
my $results = db::get( $dbh, $query, [] );
return $results;
}
sub error ($) {
my $msg = shift;
print "ERROR: $msg<br/>\n";

View File

@@ -58,3 +58,6 @@ msgstr "Dienstplan"
msgid "preview"
msgstr "Vorschau"
msgid "user-stats"
msgstr "Nutzeraktivität"

View File

@@ -31,3 +31,30 @@ msgstr "letzte Änderung"
msgid "label_score"
msgstr "Punkte"
msgid "label_login"
msgstr "Login"
msgid "label_full_name"
msgstr "Name"
msgid "label_last_login"
msgstr "letztes Login"
msgid "label_login_count"
msgstr "Anzahl Logins"
msgid "label_disabled"
msgstr "gesperrt"
msgid "label_created_at"
msgstr "erstellt am"
msgid "label_created_by"
msgstr "erstellt von"
msgid "button_show_active_users"
msgstr "aktive Nutzer"
msgid "button_show_user_stats"
msgstr "Nutzerstatistik"

View File

@@ -58,3 +58,6 @@ msgstr "Schedule"
msgid "preview"
msgstr "Preview"
msgid "user-stats"
msgstr "User Stats"

View File

@@ -31,3 +31,30 @@ msgstr "last modified at"
msgid "label_score"
msgstr "Score"
msgid "label_login"
msgstr "Login"
msgid "label_full_name"
msgstr "Name"
msgid "label_last_login"
msgstr "last login date"
msgid "label_login_count"
msgstr "login counts"
msgid "label_disabled"
msgstr "disabled"
msgid "label_created_at"
msgstr "created at"
msgid "label_created_by"
msgstr "created by"
msgid "button_show_active_users"
msgstr "active users"
msgid "button_show_user_stats"
msgstr "user stats"

View File

@@ -51,6 +51,10 @@
<div><a href="image.cgi?project_id=<TMPL_VAR project_id>&studio_id=<TMPL_VAR default_studio_id>&search=<TMPL_VAR .presets.user>"><i class="fas fa-images"></i>&nbsp;<TMPL_VAR .loc.images></a></div>
</TMPL_IF>
<TMPL_IF .allow.read_user_stats>
<div><a href="user-stats.cgi?project_id=<TMPL_VAR project_id>&studio_id=<TMPL_VAR default_studio_id>&action=show-user-stats"><i class="fas fa-images"></i>&nbsp;<TMPL_VAR .loc.user-stats></a></div>
</TMPL_IF>
<div title="<TMPL_VAR .loc.profile>"><a href="user-settings.cgi?project_id=<TMPL_VAR project_id>&studio_id=<TMPL_VAR default_studio_id>"><i class="fas fa-cog"></i>&nbsp;<TMPL_VAR .loc.profile></a></div>
<div title="<TMPL_VAR .loc.help>"><a href="help.cgi?project_id=<TMPL_VAR project_id>&studio_id=<TMPL_VAR default_studio_id>"><i class="fas fa-info"></i>&nbsp;<TMPL_VAR .loc.help></a></div>

View File

@@ -0,0 +1,67 @@
<script src="js/jquery.tablesorter.min.js"></script>
<script src="js/jquery.tablesorter.widgets.min.js"></script>
<script src="js/jquery.tablesorter.scroller.js"></script>
<script type="text/javascript">
$(document).ready(
function(){
$('table#user_stats_table').tablesorter({
widgets: ["filter"],
usNumberFormat : false
});
}
);
</script>
<style>
div.col {
float:left;
width:10px;
height:10px;
}
table#user_stats_table input{
max-width:6em;
}
</style>
<h2><TMPL_VAR loc.title></h2>
<hr>
<TMPL_INCLUDE status.html>
<button onclick="load('user-stats.cgi?project_id=<TMPL_VAR .project_id>&studio_id=<TMPL_VAR .studio_id>&action=show-user-stats')">
<TMPL_VAR .loc.button_show_user_stats>
</button>
<form method="post">
<input type="hidden" name="project_id" value="<TMPL_VAR project_id>">
<input type="hidden" name="studio_id" value="<TMPL_VAR studio_id>">
</form>
<table id="user_stats_table">
<thead>
<tr>
<th><TMPL_VAR loc.label_login></th>
<th><TMPL_VAR loc.label_full_name></th>
<th><TMPL_VAR loc.label_last_login></th>
<th><TMPL_VAR loc.label_login_count></th>
<th><TMPL_VAR loc.label_disabled></th>
<th><TMPL_VAR loc.label_created_at></th>
<th><TMPL_VAR loc.label_created_by></th>
</tr>
</thead>
<tbody>
<TMPL_LOOP user_stats>
<tr>
<td><TMPL_VAR login></td>
<td><TMPL_VAR full_name></td>
<td><TMPL_VAR last_login></td>
<td><TMPL_VAR login_count></td>
<td><TMPL_VAR disabled></td>
<td><TMPL_VAR created_at></td>
<td><TMPL_VAR created_by></td>
</tr>
</TMPL_LOOP>
</tbody>
</table>
</body>
</html>

View File

@@ -28,6 +28,10 @@ table#user_stats_table input{
<hr>
<TMPL_INCLUDE status.html>
<button onclick="load('user-stats.cgi?project_id=<TMPL_VAR .project_id>&studio_id=<TMPL_VAR .studio_id>&action=show-active-users');">
<TMPL_VAR .loc.button_show_active_users>
</button>
<form method="post">
<input type="hidden" name="project_id" value="<TMPL_VAR project_id>">
<input type="hidden" name="studio_id" value="<TMPL_VAR studio_id>">
@@ -36,15 +40,15 @@ table#user_stats_table input{
<table id="user_stats_table">
<thead>
<tr>
<th><TMPL_VAR loc.label_user></td>
<th><TMPL_VAR loc.label_score></td>
<th><TMPL_VAR loc.label_modified_at></td>
<th><TMPL_VAR loc.label_create_events></td>
<th><TMPL_VAR loc.label_update_events></td>
<th><TMPL_VAR loc.label_delete_events></td>
<th><TMPL_VAR loc.label_create_series></td>
<th><TMPL_VAR loc.label_update_series></td>
<th><TMPL_VAR loc.label_delete_series></td>
<th><TMPL_VAR loc.label_user></th>
<th><TMPL_VAR loc.label_score></th>
<th><TMPL_VAR loc.label_modified_at></th>
<th><TMPL_VAR loc.label_create_events></th>
<th><TMPL_VAR loc.label_update_events></th>
<th><TMPL_VAR loc.label_delete_events></th>
<th><TMPL_VAR loc.label_create_series></th>
<th><TMPL_VAR loc.label_update_series></th>
<th><TMPL_VAR loc.label_delete_series></th>
</tr>
</thead>
<tbody>

View File

@@ -58,9 +58,16 @@ return unless uac::check( $config, $params, $user_presets ) == 1;
our $errors = [];
show_stats( $config, $request );
if ($params->{action} eq 'show-active-users'){
show_active_users($config, $request);
return;
};
if ($params->{action} eq 'show-user-stats'){
show_user_stats( $config, $request );
return;
};
sub show_stats {
sub show_user_stats {
my $config = shift;
my $request = shift;
@@ -70,14 +77,38 @@ sub show_stats {
uac::permissions_denied('read_user_stats');
return;
}
print STDERR "continue\n";
$params->{user_stats} = user_stats::get_stats( $config, $params );
$params->{permissions} = $permissions;
$params->{errors} = $errors;
$params->{loc} = localization::get( $config, { user => $params->{presets}->{user}, file => 'user-stats' } );
uac::set_template_permissions( $permissions, $params );
template::process( $config, 'print', $params->{template}, $params );
my $template = template::check( $config, 'user-stats' );
template::process( $config, 'print', $template, $params );
}
sub show_active_users{
my $config = shift;
my $request = shift;
my $params = $request->{params}->{checked};
my $permissions = $request->{permissions};
unless ( $permissions->{read_user_stats} ) {
uac::permissions_denied('read_user_stats');
return;
}
my $user_stats = user_stats::get_active_users( $config, $params );
for my $user (@$user_stats){
$user->{disabled} = $user->{disabled} ? 'x' : '-';
}
$params->{user_stats} = $user_stats;
$params->{permissions} = $permissions;
$params->{errors} = $errors;
$params->{loc} = localization::get( $config, { user => $params->{presets}->{user}, file => 'user-stats' } );
uac::set_template_permissions( $permissions, $params );
my $template = template::check( $config, 'user-active' );
template::process( $config, 'print', $template, $params );
}
sub check_params {
@@ -86,10 +117,12 @@ sub check_params {
my $checked = {};
#template
my $template = '';
$template = template::check( $config, $params->{template}, 'user-stats' );
$checked->{template} = $template;
$checked->{action} = '';
if ( defined $params->{action} ) {
if ( $params->{action} =~ /^(show-user-stats|show-active-users)$/ ) {
$checked->{action} = $params->{action};
}
}
#numeric values
for my $param ( 'project_id', 'default_studio_id', 'studio_id', 'series_id' ) {