Enable history (#595)
This commit is contained in:
parent
22c22af3c0
commit
2e680c2ff1
|
@ -2,16 +2,13 @@
|
||||||
* write REST method to create session with an id
|
* write REST method to create session with an id
|
||||||
* Test ForceAuth
|
* Test ForceAuth
|
||||||
* Calendar in notifications explorer
|
* Calendar in notifications explorer
|
||||||
* login history
|
|
||||||
* Test for Zero
|
* Test for Zero
|
||||||
* replace SOAP by REST for notification creation
|
* replace SOAP by REST for notification creation
|
||||||
* "mail" in UserDB/*
|
* "mail" in UserDB/*
|
||||||
* checkLogins in SAML
|
* checkLogins in SAML
|
||||||
* verify activeTimer on/off on screen
|
* verify activeTimer on/off on screen
|
||||||
|
|
||||||
* Don't display "login" when connected
|
|
||||||
* Add test for #173
|
* Add test for #173
|
||||||
* lwpSslOpt
|
|
||||||
|
|
||||||
# Combination
|
# Combination
|
||||||
|
|
||||||
|
|
|
@ -406,6 +406,7 @@ t/50-IssuerGet.t
|
||||||
t/60-status.t
|
t/60-status.t
|
||||||
t/61-grantSession.t
|
t/61-grantSession.t
|
||||||
t/62-singleSession.t
|
t/62-singleSession.t
|
||||||
|
t/63-History.t
|
||||||
t/90-translations.t
|
t/90-translations.t
|
||||||
t/99-pod.t
|
t/99-pod.t
|
||||||
t/lmConf-1.js
|
t/lmConf-1.js
|
||||||
|
|
|
@ -21,7 +21,7 @@ our @pList = (
|
||||||
u2fActivation => '::Plugins::U2F',
|
u2fActivation => '::Plugins::U2F',
|
||||||
u2fSelfRegistration => '::Register::U2F',
|
u2fSelfRegistration => '::Register::U2F',
|
||||||
notification => '::Plugins::Notifications',
|
notification => '::Plugins::Notifications',
|
||||||
checkLogins => '::Plugins::History',
|
portalCheckLogins => '::Plugins::History',
|
||||||
);
|
);
|
||||||
|
|
||||||
##@method list enabledPlugins
|
##@method list enabledPlugins
|
||||||
|
|
|
@ -141,6 +141,7 @@ sub authLogout {
|
||||||
|
|
||||||
sub deleteSession {
|
sub deleteSession {
|
||||||
my ( $self, $req ) = @_;
|
my ( $self, $req ) = @_;
|
||||||
|
$req->userData( {} );
|
||||||
my $apacheSession = $self->getApacheSession( $req->id );
|
my $apacheSession = $self->getApacheSession( $req->id );
|
||||||
my $id = $req->id;
|
my $id = $req->id;
|
||||||
unless ($apacheSession) {
|
unless ($apacheSession) {
|
||||||
|
@ -267,7 +268,7 @@ sub getUser {
|
||||||
|
|
||||||
sub authenticate {
|
sub authenticate {
|
||||||
my ( $self, $req ) = @_;
|
my ( $self, $req ) = @_;
|
||||||
return $self->_authentication->authenticate($req);
|
return $req->authResult( $self->_authentication->authenticate($req) );
|
||||||
}
|
}
|
||||||
|
|
||||||
# Third block: Session data providing
|
# Third block: Session data providing
|
||||||
|
|
|
@ -12,6 +12,9 @@ extends 'Lemonldap::NG::Common::PSGI::Request';
|
||||||
# List of methods to call
|
# List of methods to call
|
||||||
has steps => ( is => 'rw' );
|
has steps => ( is => 'rw' );
|
||||||
|
|
||||||
|
# Authentication result
|
||||||
|
has authResult => ( is => 'rw' );
|
||||||
|
|
||||||
# Datas shared between methods
|
# Datas shared between methods
|
||||||
has datas => ( is => 'rw' );
|
has datas => ( is => 'rw' );
|
||||||
|
|
||||||
|
|
|
@ -152,12 +152,17 @@ sub do {
|
||||||
$req->steps($steps);
|
$req->steps($steps);
|
||||||
my $err = $req->error( $self->process($req) );
|
my $err = $req->error( $self->process($req) );
|
||||||
|
|
||||||
# TODO: updateStatus
|
# Update status
|
||||||
if ( my $p = $self->HANDLER->tsv->{statusPipe} ) {
|
if ( my $p = $self->HANDLER->tsv->{statusPipe} ) {
|
||||||
print $p ( $req->user ? $req->user : $req->address ) . ' => '
|
print $p ( $req->user ? $req->user : $req->address ) . ' => '
|
||||||
. $req->uri
|
. $req->uri
|
||||||
. " $err\n";
|
. " $err\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Update history
|
||||||
|
if ( $self->conf->{loginHistoryEnabled} ) {
|
||||||
|
$self->registerLogin($req);
|
||||||
|
}
|
||||||
if ( $err == PE_SENDRESPONSE ) {
|
if ( $err == PE_SENDRESPONSE ) {
|
||||||
return $req->response;
|
return $req->response;
|
||||||
}
|
}
|
||||||
|
@ -374,9 +379,6 @@ sub updatePersistentSession {
|
||||||
# Return if no infos to update
|
# Return if no infos to update
|
||||||
return () unless ( ref $infos eq 'HASH' and %$infos );
|
return () unless ( ref $infos eq 'HASH' and %$infos );
|
||||||
|
|
||||||
# Update current session
|
|
||||||
$self->updateSession( $req, $infos, $id );
|
|
||||||
|
|
||||||
$uid ||= $req->{sessionInfo}->{ $self->conf->{whatToTrace} }
|
$uid ||= $req->{sessionInfo}->{ $self->conf->{whatToTrace} }
|
||||||
|| $req->userData->{ $self->conf->{whatToTrace} };
|
|| $req->userData->{ $self->conf->{whatToTrace} };
|
||||||
unless ($uid) {
|
unless ($uid) {
|
||||||
|
@ -385,6 +387,9 @@ sub updatePersistentSession {
|
||||||
}
|
}
|
||||||
$self->logger->debug("Update $uid persistent session");
|
$self->logger->debug("Update $uid persistent session");
|
||||||
|
|
||||||
|
# Update current session
|
||||||
|
$self->updateSession( $req, $infos, $id );
|
||||||
|
|
||||||
my $persistentSession = $self->getPersistentSession($uid);
|
my $persistentSession = $self->getPersistentSession($uid);
|
||||||
|
|
||||||
$persistentSession->update($infos);
|
$persistentSession->update($infos);
|
||||||
|
@ -719,4 +724,43 @@ sub tplParams {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub registerLogin {
|
||||||
|
my ( $self, $req ) = @_;
|
||||||
|
return unless ( defined $req->authResult );
|
||||||
|
my $history = $req->sessionInfo->{loginHistory} ||= {};
|
||||||
|
my $type = ( $req->authResult > 0 ? 'failed' : 'success' ) . 'Login';
|
||||||
|
$history->{$type} ||= [];
|
||||||
|
$self->logger->debug("Current login saved into $type");
|
||||||
|
|
||||||
|
# Gather current login's parameters
|
||||||
|
my $login = $self->_sumUpSession( $req->{sessionInfo}, 1 );
|
||||||
|
$login->{error} = $self->error( $req->authResult )
|
||||||
|
if ( $req->authResult );
|
||||||
|
|
||||||
|
# Add current login into history
|
||||||
|
unshift @{ $history->{$type} }, $login;
|
||||||
|
|
||||||
|
# Forget oldest logins
|
||||||
|
splice @{ $history->{$type} }, $self->conf->{ $type . "Number" }
|
||||||
|
if ( scalar @{ $history->{$type} } > $self->conf->{ $type . "Number" } );
|
||||||
|
|
||||||
|
# Save into persistent session
|
||||||
|
$self->updatePersistentSession( $req, { loginHistory => $history, } );
|
||||||
|
}
|
||||||
|
|
||||||
|
# put main session data into a hash ref
|
||||||
|
# @param hashref $session The session to sum up
|
||||||
|
# @return hashref
|
||||||
|
sub _sumUpSession {
|
||||||
|
my ( $self, $session, $withoutUser ) = @_;
|
||||||
|
my $res =
|
||||||
|
$withoutUser
|
||||||
|
? {}
|
||||||
|
: { user => $session->{ $self->conf->{whatToTrace} } };
|
||||||
|
$res->{$_} = $session->{$_}
|
||||||
|
foreach ( "_utime", "ipAddr",
|
||||||
|
keys %{ $self->conf->{sessionDataToRemember} } );
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|
|
@ -40,11 +40,11 @@ sub grantSession {
|
||||||
foreach ( sort sortByComment keys %{ $self->rules } ) {
|
foreach ( sort sortByComment keys %{ $self->rules } ) {
|
||||||
$self->logger->debug("Grant session condition \"$_\"");
|
$self->logger->debug("Grant session condition \"$_\"");
|
||||||
unless ( $self->rules->{$_}->( $req->sessionInfo ) ) {
|
unless ( $self->rules->{$_}->( $req->sessionInfo ) ) {
|
||||||
$req->userData({});
|
$req->userData( {} );
|
||||||
$self->userLogger->error( 'User '
|
$self->userLogger->error( 'User '
|
||||||
. $req->user
|
. $req->user
|
||||||
. " was not granted to open session (rule $_)" );
|
. " was not granted to open session (rule $_)" );
|
||||||
return PE_SESSIONNOTGRANTED;
|
return $req->authResult(PE_SESSIONNOTGRANTED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return PE_OK;
|
return PE_OK;
|
||||||
|
|
|
@ -2,32 +2,41 @@ package Lemonldap::NG::Portal::Plugins::History;
|
||||||
|
|
||||||
use strict;
|
use strict;
|
||||||
use Mouse;
|
use Mouse;
|
||||||
use Lemonldap::NG::Portal::Main::Constants qw(PE_OK);
|
use Lemonldap::NG::Portal::Main::Constants qw(PE_INFO PE_OK);
|
||||||
|
|
||||||
extends 'Lemonldap::NG::Portal::Main::Plugin',
|
extends 'Lemonldap::NG::Portal::Main::Plugin',
|
||||||
'Lemonldap::NG::Portal::Lib::OtherSessions';
|
'Lemonldap::NG::Portal::Lib::OtherSessions';
|
||||||
|
|
||||||
sub afterDatas { 'run' }
|
sub afterDatas { 'run' }
|
||||||
|
|
||||||
|
sub init { 1 }
|
||||||
|
|
||||||
sub run {
|
sub run {
|
||||||
my ( $self, $req ) = @_;
|
my ( $self, $req ) = @_;
|
||||||
$req->info(
|
if ( $req->param('checkLogins') ) {
|
||||||
(
|
$self->logger->debug('History asked');
|
||||||
$req->sessionInfo->{loginHistory}->{successLogin}
|
$req->info(
|
||||||
? $self->mkSessionArray(
|
(
|
||||||
$req->sessionInfo->{loginHistory}->{successLogin},
|
$req->sessionInfo->{loginHistory}->{successLogin}
|
||||||
'lastLogins', 0, 0 )
|
? $self->mkSessionArray(
|
||||||
: ""
|
$req->sessionInfo->{loginHistory}->{successLogin},
|
||||||
)
|
'lastLogins', 0, 0 )
|
||||||
. (
|
: ""
|
||||||
$req->sessionInfo->{loginHistory}->{failedLogin}
|
)
|
||||||
? $self->mkSessionArray(
|
. (
|
||||||
$req->sessionInfo->{loginHistory}->{failedLogin},
|
$req->sessionInfo->{loginHistory}->{failedLogin}
|
||||||
'lastFailedLogins', 0, 1 )
|
? $self->mkSessionArray(
|
||||||
: ""
|
$req->sessionInfo->{loginHistory}->{failedLogin},
|
||||||
)
|
'lastFailedLogins', 0, 1 )
|
||||||
);
|
: ""
|
||||||
PE_OK;
|
)
|
||||||
|
);
|
||||||
|
unless($req->info) {
|
||||||
|
$req->info('<p trspan="noHistory"></p>');
|
||||||
|
}
|
||||||
|
return PE_INFO;
|
||||||
|
}
|
||||||
|
return PE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|
|
@ -35,11 +35,11 @@ sub run {
|
||||||
and $req->{sessionInfo}->{ipAddr} ne $session->data->{ipAddr} )
|
and $req->{sessionInfo}->{ipAddr} ne $session->data->{ipAddr} )
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
push @$deleted, $self->_sumUpSession( $session->data );
|
push @$deleted, $self->p->_sumUpSession( $session->data );
|
||||||
$self->p->_deleteSession( $req, $session, 1 );
|
$self->p->_deleteSession( $req, $session, 1 );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
push @$otherSessions, $self->_sumUpSession( $session->data );
|
push @$otherSessions, $self->p->_sumUpSession( $session->data );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( $self->conf->{singleUserByIP} ) {
|
if ( $self->conf->{singleUserByIP} ) {
|
||||||
|
@ -52,7 +52,7 @@ sub run {
|
||||||
unless ( $req->{sessionInfo}->{ $self->conf->{whatToTrace} } eq
|
unless ( $req->{sessionInfo}->{ $self->conf->{whatToTrace} } eq
|
||||||
$session->data->{ $self->conf->{whatToTrace} } )
|
$session->data->{ $self->conf->{whatToTrace} } )
|
||||||
{
|
{
|
||||||
push @$deleted, $self->_sumUpSession( $session->data );
|
push @$deleted, $self->p->_sumUpSession( $session->data );
|
||||||
$self->p->_deleteSession( $req, $session, 1 );
|
$self->p->_deleteSession( $req, $session, 1 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,21 +66,6 @@ sub run {
|
||||||
PE_OK;
|
PE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
# put main session data into a hash ref
|
|
||||||
# @param hashref $session The session to sum up
|
|
||||||
# @return hashref
|
|
||||||
sub _sumUpSession {
|
|
||||||
my ( $self, $session, $withoutUser ) = @_;
|
|
||||||
my $res =
|
|
||||||
$withoutUser
|
|
||||||
? {}
|
|
||||||
: { user => $session->{ $self->conf->{whatToTrace} } };
|
|
||||||
$res->{$_} = $session->{$_}
|
|
||||||
foreach ( "_utime", "ipAddr",
|
|
||||||
keys %{ $self->conf->{sessionDataToRemember} } );
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Build the removeOther link
|
# Build the removeOther link
|
||||||
# Last part of URL is built trough javascript
|
# Last part of URL is built trough javascript
|
||||||
# @return removeOther link in HTML code
|
# @return removeOther link in HTML code
|
||||||
|
|
64
lemonldap-ng-portal/t/63-History.t
Normal file
64
lemonldap-ng-portal/t/63-History.t
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
use Test::More;
|
||||||
|
use strict;
|
||||||
|
use IO::String;
|
||||||
|
|
||||||
|
BEGIN {
|
||||||
|
require 't/test-lib.pm';
|
||||||
|
}
|
||||||
|
|
||||||
|
my $res;
|
||||||
|
|
||||||
|
my $client = LLNG::Manager::Test->new(
|
||||||
|
{
|
||||||
|
ini => {
|
||||||
|
logLevel => 'error',
|
||||||
|
authentication => 'Demo',
|
||||||
|
userDB => 'Same',
|
||||||
|
loginHistoryEnabled => 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
# Case "no history"
|
||||||
|
ok(
|
||||||
|
$res = $client->_post(
|
||||||
|
'/',
|
||||||
|
IO::String->new('user=dwho&password=dwho&checkLogins=1'),
|
||||||
|
length => 37,
|
||||||
|
accept => 'text/html',
|
||||||
|
),
|
||||||
|
'Auth query'
|
||||||
|
);
|
||||||
|
count(1);
|
||||||
|
expectOK($res);
|
||||||
|
my $id1 = expectCookie($res);
|
||||||
|
ok( $res->[2]->[0] =~ /trspan="noHistory"/, 'No history found' );
|
||||||
|
count(1);
|
||||||
|
|
||||||
|
ok( $res = $client->_get( '/', cookie => "lemonldap=$id1" ),
|
||||||
|
'Verify connection' );
|
||||||
|
count(1);
|
||||||
|
expectOK($res);
|
||||||
|
|
||||||
|
$client->logout($id1);
|
||||||
|
|
||||||
|
# History with 1 success
|
||||||
|
ok(
|
||||||
|
$res = $client->_post(
|
||||||
|
'/',
|
||||||
|
IO::String->new('user=dwho&password=dwho&checkLogins=1'),
|
||||||
|
length => 37,
|
||||||
|
accept => 'text/html',
|
||||||
|
),
|
||||||
|
'Auth query'
|
||||||
|
);
|
||||||
|
count(1);
|
||||||
|
expectOK($res);
|
||||||
|
$id1 = expectCookie($res);
|
||||||
|
|
||||||
|
ok( $res->[2]->[0] =~ /trspan="lastLogins"/, 'History found' );
|
||||||
|
count(1);
|
||||||
|
|
||||||
|
clean_sessions();
|
||||||
|
|
||||||
|
done_testing( count() );
|
Loading…
Reference in New Issue
Block a user