Listing logged-in users

I am trying to do a web element to list logged-in users, but I am
currently unable to get this information.

All I can get from a session is its “lastupdated” from the DB table,
wich seems to be the login time, which allows me to list “Who logged in
today”, and is quite different from “Who is logged in now”.

If I tie the session and Data::Dumper the object’s attributes, I see a
lot of session data, but I cannot find a reasonable time of last activity.

Am I missing something, or should I conclude that this is impossible
given the way web sessions work in general and in RT in particular?

My painful workaround is to hack my way to “Who looked at this Element
in the last hour” (don’t ask). Less painful workarounds welcome.

Thanks for you helpful attention,

				Bergonz

Ing. Michele Bergonzoni - Laboratori Guglielmo Marconi S.p.a.
Phone:+39-051-6781926 e-mail: bergonz@labs.it
alt.advanced.networks.design.configure.operate

Am I missing something, or should I conclude that this is impossible
given the way web sessions work in general and in RT in particular?

It’s not possible with just the session data because web sessions aren’t
stateful. You only get them on a request, so the best you can do is
update a cache of recently seen users (using one of the /autohandler
callbacks, which are invoked by RT::Interface::Web::HandleRequest for
every request). Your “Who is logged in now” then uses the recently seen
users to show “who accessed RT in the past X minutes” where X is
something appropriate for your usage like 5 or 30.

update a cache of recently seen users (using one of the /autohandler
callbacks, which are invoked by RT::Interface::Web::HandleRequest for
every request)

Thanks Thomas, this is a feature I failed to find. If I come up with
something decent, I’ll share it.

Regards,
Bergonz

If I come up with something decent, I’ll share it.

Decent? Maybe, at least I don’t see any obvious security hole. I don’t
know enough about RT to know if this will make a SQL query per row, or
if it will take the names from some cache. Anyway that’s what I have.

Regards,

			Bergonz
<&|/Widgets/TitleBox, title => loc("Who's seeing this page (last 5 min)"), bodyclass => "" &> <%perl> require RT::User; my $base = $RT::BasePath . '/var/logged_users'; my $file = $session{'CurrentUser'}->id();

Touch your file

open(F, '> ’ . $base . ‘/’ . $file);
close(F);

my $u = RT::User->new($RT::SystemUser);
my $now=time();

if (not opendir(Q,$base)){
die(“Can’t scan $base: $!\n”);
}

my $tref = [];
my $mtime;
my $uname;

while (defined($file=readdir(Q))){
$mtime=(stat($base . ‘/’ . $file))[9];
if ($mtime >= ($now - 300)) {
if($file =~ /^\d+$/){
$u->Load(int($file));
$uname = $u->Name();
if ($uname){
push(@$tref, [($uname)]);
}
}
}
}
closedir(Q);

my $i=0;
for my $line (@{$tref}){
</%perl>

<%perl> $i++; }
<% $$line[0] %>

Ing. Michele Bergonzoni - Laboratori Guglielmo Marconi S.p.a.
Phone:+39-051-6781926 e-mail: bergonz@labs.it
alt.advanced.networks.design.configure.operate

Why don’t you just set the AutoLogoff value in RT_SiteConfig.pm and
setup a cronjob for sbin/rt-clean-sessions and then create an element
’active sessions’ that loads the sessions.

Maybe this solution have a chance to go into RT core code as it isn’t an
assumption or a lie :wink:

ChrisAm 06.12.2012 12:27, schrieb Michele Bergonzoni:

If I come up with something decent, I’ll share it.

Decent? Maybe, at least I don’t see any obvious security hole. I don’t
know enough about RT to know if this will make a SQL query per row, or
if it will take the names from some cache. Anyway that’s what I have.

Regards,

            Bergonz

================================================================

<&|/Widgets/TitleBox, title => loc("Who's seeing this page (last 5 min)"), bodyclass => "" &> <%perl> require RT::User; my $base = $RT::BasePath . '/var/logged_users'; my $file = $session{'CurrentUser'}->id();

Touch your file

open(F, '> ’ . $base . ‘/’ . $file);
close(F);

my $u = RT::User->new($RT::SystemUser);
my $now=time();

if (not opendir(Q,$base)){
die(“Can’t scan $base: $!\n”);
}

my $tref = [];
my $mtime;
my $uname;

while (defined($file=readdir(Q))){
$mtime=(stat($base . ‘/’ . $file))[9];
if ($mtime >= ($now - 300)) {
if($file =~ /^\d+$/){
$u->Load(int($file));
$uname = $u->Name();
if ($uname){
push(@$tref, [($uname)]);
}
}
}
}
closedir(Q);

my $i=0;
for my $line (@{$tref}){
</%perl>

<%perl> $i++; }
<% $$line[0] %>
================================================================

Why don’t you just set the AutoLogoff value in RT_SiteConfig.pm and
setup a cronjob for sbin/rt-clean-sessions and then create an element
’active sessions’ that loads the sessions.

Thank you for your suggestion. This is a different way to solve the same
problem and I am not sure about which one I prefer. Showing the sessions
in the DB was my first attempt (I could not find a way to do that with
the API, so I got them with SQL, then “tie”, not a pleasant sight).

In my installation, if a person keeps using RT to update a ticket with
new details, but never looks back at the homepage (which is the way
people here learn about new tickets to take ownership of), I don’t want
that person listed in the box. That’s because the reason I am doing this
is to let people know who is looking at the list of new tickets in order
to service them. For me, having the session active and making a request
to RT is not enough.

Besides, setting AutoLogoff is good for security, but as such can be
annoying if that security is not needed.

Anyway, if someone stays in the home page with the autorefresh and
simply walks away, he will show up in my box as well as in your
suggested box.

Maybe this solution have a chance to go into RT core code as it isn’t an
assumption or a lie :wink:

I can change the title to “Who had this page sent to a browser, maybe
displayed on a monitor, and possibly seen (last 5 min)”.

Regards,
Bergonz

Ing. Michele Bergonzoni - Laboratori Guglielmo Marconi S.p.a.
Phone:+39-051-6781926 e-mail: bergonz@labs.it
alt.advanced.networks.design.configure.operate

Why don’t you just set the AutoLogoff value in RT_SiteConfig.pm and
setup a cronjob for sbin/rt-clean-sessions and then create an element
’active sessions’ that loads the sessions.

Thank you for your suggestion. This is a different way to solve the same
problem and I am not sure about which one I prefer. Showing the sessions
in the DB was my first attempt (I could not find a way to do that with
the API, so I got them with SQL, then “tie”, not a pleasant sight).

In my installation, if a person keeps using RT to update a ticket with
new details, but never looks back at the homepage (which is the way
people here learn about new tickets to take ownership of), I don’t want
that person listed in the box. That’s because the reason I am doing this
is to let people know who is looking at the list of new tickets in order
to service them. For me, having the session active and making a request
to RT is not enough.

Ok this is an very special need. I thought you want to have a “Logged in
user” list which I also thought about implementing this in our RT.

Besides, setting AutoLogoff is good for security, but as such can be
annoying if that security is not needed.

Anyway, if someone stays in the home page with the autorefresh and
simply walks away, he will show up in my box as well as in your
suggested box.

After the AutoLogoff time the user wouldn’t be in my list as the
Homepage request doesn’t update the session LastUpdated value (if you
also have an cronjob running sbin/rt-clean-sessions).
This was the reason for me to add an AutoLogoff value as my user set the
HomepageRefreshInterval to 2 minutes and then leave the office on
Fridays logged in to my RT and I was wondering about the DB load on
weekends.

After the AutoLogoff time the user wouldn’t be in my list as the
Homepage request doesn’t update the session LastUpdated

This is something I didn’t realize. I’ll restore my previous attempt
from backups and send you something.

Regards,
Bergonz

Ing. Michele Bergonzoni - Laboratori Guglielmo Marconi S.p.a.
Phone:+39-051-6781926 e-mail: bergonz@labs.it
alt.advanced.networks.design.configure.operate

This is something I didn’t realize. I’ll restore my previous attempt
from backups and send you something.

That’s the “ListSessions” box. The code mimics rt-clean-sessions. If a
user has two sessions, this will show him twice, so it is not really
"done" but Christian, you might want to play with this and see if you
like it.

There is surely a lot of things I don’t understand about the
"LastUpdated" field. Thomas knows better, because he told to use
callbacks (but I got lost trying to figure out their ARGS).

Thanks everybody for the help and the suggestions,

		Bergonz
<&|/Widgets/TitleBox, title => loc("Active sessions (last 5 min)"), bodyclass => "" &> <%perl> require RT::Interface::Web::Session;

my $class = RT::Interface::Web::Session->Class();
my $attrs = RT::Interface::Web::Session->Attributes();

require POSIX;
my $date = POSIX::strftime("%Y-%m-%d %H:%M:%S", localtime(time - 300));
my $sth = $RT::Handle->dbh->prepare(“select id from sessions where
LastUpdated > ? order by LastUpdated desc”);
die "couldn’t prepare query: ". $RT::Handle->dbh->errstr unless $sth;
my $rv = $sth->execute($date);
die "couldn’t execute query: ". $RT::Handle->dbhdbh->errstr unless
defined $rv;
my $arr = $sth->fetchall_arrayref();
my $i=0;
while ($i <= $#$arr){
my %session;
local $@;
eval { tie %session, $class, $$arr[$i][0], $attrs };
if( $@ ) {
$RT::Logger->debug("skipped session " . $$arr[$i][0] . “, couldn’t
load: $@”);
next;
}
</%perl>

<%perl> $i++; }
<% $session{'CurrentUser'}->UserObj->Name() %>

Ing. Michele Bergonzoni - Laboratori Guglielmo Marconi S.p.a.
Phone:+39-051-6781926 e-mail: bergonz@labs.it
alt.advanced.networks.design.configure.operate