our
$VERSION
=
'2.0.14'
;
has
locationAttribute
=> (
is
=>
'rw'
);
has
locationDisplayAttribute
=> (
is
=>
'rw'
);
has
locationMaxValues
=> (
is
=>
'rw'
);
has
mailSessionKey
=> (
is
=>
'ro'
,
lazy
=> 1,
default
=>
sub
{
return
$_
[0]->{conf}->{newLocationWarningMailAttribute}
||
$_
[0]->{conf}->{mailSessionKey}
||
'mail'
;
}
);
extends
qw(
Lemonldap::NG::Portal::Main::Plugin
)
;
use
constant
afterSub
=> {
setLocalGroups
=>
'checkNewLocation'
};
use
constant
endAuth
=>
'sendWarningEmail'
;
sub
init {
my
(
$self
) =
@_
;
if
(
$self
->conf->{disablePersistentStorage} ) {
$self
->logger->error(
'"NewLocationWarning" plugin enabled WITHOUT persistent session storage"'
);
return
0;
}
unless
(
$self
->conf->{loginHistoryEnabled} ) {
$self
->logger->error(
'"NewLocationWarning" plugin enabled WITHOUT "History" plugin'
);
return
0;
}
$self
->locationAttribute(
$self
->conf->{newLocationWarningLocationAttribute}
||
'ipAddr'
);
$self
->locationDisplayAttribute(
$self
->conf->{newLocationWarningLocationDisplayAttribute}
||
$self
->locationAttribute );
$self
->locationMaxValues(
$self
->conf->{newLocationWarningMaxValues} || 0 );
return
1;
}
sub
checkNewLocation {
my
(
$self
,
$req
) =
@_
;
my
$successLogin
=
$req
->sessionInfo->{_loginHistory}->{successLogin} || [];
my
$location
=
$req
->sessionInfo->{
$self
->locationAttribute };
$self
->logger->debug(
"Could not find location of user "
.
$req
->user )
unless
$location
;
my
@envHistory
=
grep
{
$_
//
""
}
uniq(
map
{
$_
->{
$self
->locationAttribute } //
""
} @{
$successLogin
} );
my
$maxLocations
=
$self
->locationMaxValues;
splice
@envHistory
,
$maxLocations
if
(
$maxLocations
and (
scalar
@envHistory
>
$maxLocations
) );
if
(
grep
{
$_
eq
$location
}
@envHistory
) {
$self
->userLogger->debug(
"User "
.
$req
->user .
" logged in from known location $location"
);
}
else
{
if
(
@envHistory
) {
$self
->userLogger->info(
"User "
.
$req
->user
.
" logged in from unknown location $location"
);
my
$riskLevel
= (
$req
->sessionInfo->{_riskLevel} || 0 ) + 1;
$req
->sessionInfo->{_riskLevel} =
$riskLevel
;
$req
->sessionInfo->{_riskDetails}->{newLocation} =
$req
->sessionInfo->{
$self
->locationDisplayAttribute };
}
else
{
$self
->userLogger->info(
"User "
.
$req
->user
.
" logged with empty location history from location $location"
);
}
}
return
PE_OK;
}
sub
sendWarningEmail {
my
(
$self
,
$req
) =
@_
;
return
$self
->_sendMail(
$req
)
if
$req
->sessionInfo->{_riskDetails}->{newLocation};
return
PE_OK;
}
sub
_sendMail {
my
(
$self
,
$req
) =
@_
;
my
$date
= strftime(
'%F %X'
,
localtime
);
my
$location
=
$req
->sessionInfo->{_riskDetails}->{newLocation};
my
$ua
=
$req
->env->{HTTP_USER_AGENT};
my
$mail
=
$req
->sessionInfo->{
$self
->mailSessionKey };
my
$tr
=
$self
->translate(
$req
);
my
$subject
=
$self
->conf->{newLocationWarningMailSubject};
unless
(
$subject
) {
$self
->logger->debug(
'Use default warning subject'
);
$subject
=
'newLocationWarningMailSubject'
;
$tr
->( \
$subject
);
}
my
(
$body
,
$html
);
if
(
$self
->conf->{newLocationWarningMailBody} ) {
$self
->logger->debug(
'Use specific warning body message'
);
$body
=
$self
->conf->{newLocationWarningMailBody};
$body
=~ s/\
$ua
\b/
$ua
/ge;
$body
=~ s/\
$location
\b/
$location
/ge;
$body
=~ s/\
$date
\b/
$date
/ge;
$body
=~ s/\$(\w+)/
$req
->{sessionInfo}->{$1} ||
''
/ge;
}
else
{
$body
=
$self
->loadMailTemplate(
$req
,
'mail_new_location_warning'
,
filter
=>
$tr
,
params
=> {
location
=>
$location
,
date
=>
$date
,
ua
=>
$ua
},
);
$html
= 1;
}
if
(
$mail
&&
$subject
&&
$body
) {
$self
->logger->
warn
(
"User $mail is signing in from a new location"
);
$self
->logger->debug(
'Unable to send new location warning mail'
)
unless
(
$self
->send_mail(
$mail
,
$subject
,
$body
,
$html
) );
}
else
{
$self
->logger->error(
'Unable to send new location warning mail: missing parameter(s)'
);
}
return
PE_OK;
}
1;