diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/NewLocationWarning.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/NewLocationWarning.pm index 02a49b5b0..e7c54434b 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/NewLocationWarning.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/NewLocationWarning.pm @@ -4,16 +4,33 @@ use strict; use Mouse; use POSIX qw(strftime); use Lemonldap::NG::Portal::Main::Constants qw(PE_OK); +use List::MoreUtils qw/uniq/; our $VERSION = '2.0.14'; +has locationAttribute => ( is => 'rw' ); +has locationDisplayAttribute => ( is => 'rw' ); +has locationMaxValues => ( is => 'rw' ); + +has mailSessionKey => ( + is => 'rw', + lazy => 1, + default => sub { + return + $_[0]->{conf}->{newLocationWarningMailAttribute} + || $_[0]->{conf}->{mailSessionKey} + || 'mail'; + } +); + extends qw( Lemonldap::NG::Portal::Lib::SMTP Lemonldap::NG::Portal::Main::Plugin ); # Entrypoint -use constant aroundSub => { storeHistory => 'check' }; +use constant afterSub => { setLocalGroups => 'checkNewLocation' }; +use constant endAuth => 'sendWarningEmail'; sub init { my ($self) = @_; @@ -29,38 +46,76 @@ sub init { '"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 check { - my ( $self, $sub, $req ) = @_; - my $successLogin = $req->sessionInfo->{_loginHistory}->{successLogin}; - my $failedLogin = $req->sessionInfo->{_loginHistory}->{failedLogin}; - my $sourceIP = $req->env->{ipAddr}; - $self->logger->debug("Source IP: $sourceIP"); +sub checkNewLocation { + my ( $self, $req ) = @_; - my %knownIPs = map { $_->{ipAddr} => 1 } ( @$successLogin, @$failedLogin ); + my $successLogin = $req->sessionInfo->{_loginHistory}->{successLogin} || []; - if ( $knownIPs{$sourceIP} ) { - $self->logger->debug('Known location'); - return $sub->($req); + my $location = $req->sessionInfo->{ $self->locationAttribute }; + + unless ($location) { + $self->logger->debug( "Could not find location of user " . $req->user ); + } + + # Get all non-empty, unique values of location attribute through list of + # successful logins + my @envHistory = + grep { $_ // "" } + uniq( map { $_->{ $self->locationAttribute } // "" } @{$successLogin} ); + + # Only consider some of the past unique locations + 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 { - $self->logger->warn("New location found: $sourceIP"); - $self->_sendMail($req); - return $sub->($req); + # Not the first location in history, warn if new location + if (@envHistory) { + $self->userLogger->info( "User " + . $req->user + . " logged in from unknown location $location" ); + my $riskLevel = ( $req->sessionInfo->{_riskLevel} || 0 ) + 1; + $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 ) = @_; + if ( $req->sessionInfo->{_riskDetails}->{newLocation} ) { + return $self->_sendMail($req); + } + return PE_OK; } sub _sendMail { my ( $self, $req ) = @_; my $date = strftime( '%F %X', localtime ); - my $sourceIP = $req->env->{ipAddr}; - my $host = $req->env->{HTTP_HOST}; + my $location = $req->sessionInfo->{_riskDetails}->{newLocation}; my $ua = $req->env->{HTTP_USER_AGENT}; - my $mail = - $req->sessionInfo->{ $self->conf->{newLocationWarningMailAttribute} - || 'mail' }; + my $mail = $req->sessionInfo->{ $self->mailSessionKey }; # Build mail content my $tr = $self->translate($req); @@ -78,10 +133,10 @@ sub _sendMail { $body = $self->conf->{newLocationWarningMailBody}; # Replace variables in body - $body =~ s/\$newLocationUserAgent/$ua/ge; - $body =~ s/\$newLocationIP/$sourceIP/ge; - $body =~ s/\$newLocationDate/$date/ge; - $body =~ s/\$newLocationHost/$host/ge; + $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 { @@ -91,10 +146,9 @@ sub _sendMail { 'mail_new_location_warning', filter => $tr, params => { - session_ipAddr => $sourceIP, - date => $date, - host => $host, - ua => $ua + location => $location, + date => $date, + ua => $ua }, ); $html = 1; diff --git a/lemonldap-ng-portal/site/templates/common/mail/ar.json b/lemonldap-ng-portal/site/templates/common/mail/ar.json index fed1c585a..cb8d33045 100644 --- a/lemonldap-ng-portal/site/templates/common/mail/ar.json +++ b/lemonldap-ng-portal/site/templates/common/mail/ar.json @@ -7,6 +7,7 @@ "goToPortal":"انتقل إلى البوابة", "hello":"مرحبا ", "host":"Host", +"location": "Location", "mail2fSubject":"[LemonLDAP::NG] تسجيل الدخول الخاص بك هو ", "mailConfirmSubject":"تأكيد إعادة تعيين كلمة المرور[LemonLDAP::NG]", "mailSubject":"كلمة المرور الجديدة [LemonLDAP::NG]", diff --git a/lemonldap-ng-portal/site/templates/common/mail/en.json b/lemonldap-ng-portal/site/templates/common/mail/en.json index 506606e9e..e18aee857 100644 --- a/lemonldap-ng-portal/site/templates/common/mail/en.json +++ b/lemonldap-ng-portal/site/templates/common/mail/en.json @@ -7,6 +7,7 @@ "goToPortal":"Go to portal", "hello":"Hello", "host":"Host", +"location": "Location", "mail2fSubject":"[LemonLDAP::NG] Your login code", "mailConfirmSubject": "[LemonLDAP::NG] Password reset confirmation", "mailSubject": "[LemonLDAP::NG] Your new password", diff --git a/lemonldap-ng-portal/site/templates/common/mail/es.json b/lemonldap-ng-portal/site/templates/common/mail/es.json index 2a62fce1a..56494fa47 100644 --- a/lemonldap-ng-portal/site/templates/common/mail/es.json +++ b/lemonldap-ng-portal/site/templates/common/mail/es.json @@ -7,6 +7,7 @@ "goToPortal":"Ir al portal", "hello":"Hola", "host":"Host", +"location": "Location", "mail2fSubject":"[LemonLDAP::NG] Su código de acceso", "mailConfirmSubject":"[LemonLDAP::NG] Confirmación de reinicio de contraseña", "mailSubject":"[LemonLDAP::NG] Su nueva contraseña", diff --git a/lemonldap-ng-portal/site/templates/common/mail/fi.json b/lemonldap-ng-portal/site/templates/common/mail/fi.json index c039f932c..265ef7dca 100644 --- a/lemonldap-ng-portal/site/templates/common/mail/fi.json +++ b/lemonldap-ng-portal/site/templates/common/mail/fi.json @@ -7,6 +7,7 @@ "goToPortal":"Siirry portaaliin", "hello":"Hei", "host":"Host", +"location":"Location", "mail2fSubject":"[LemonLDAP::NG] Your login code", "mailConfirmSubject":"[LemonLDAP::NG] Salasanan nollauksen vahvistus", "mailSubject":"[LemonLDAP::NG] Uusi salasanasi", diff --git a/lemonldap-ng-portal/site/templates/common/mail/fr.json b/lemonldap-ng-portal/site/templates/common/mail/fr.json index 84ffa14a8..fa2f9d70c 100644 --- a/lemonldap-ng-portal/site/templates/common/mail/fr.json +++ b/lemonldap-ng-portal/site/templates/common/mail/fr.json @@ -7,6 +7,7 @@ "goToPortal":"Aller au portail", "hello":"Bonjour", "host":"Hôte", +"location":"Localisation", "mail2fSubject":"[LemonLDAP::NG] Votre code de connexion", "mailConfirmSubject": "[LemonLDAP::NG] Confirmation de réinitialisation de mot de passe", "mailSubject": "[LemonLDAP::NG] Votre nouveau mot de passe", diff --git a/lemonldap-ng-portal/site/templates/common/mail/it.json b/lemonldap-ng-portal/site/templates/common/mail/it.json index a90ce4d9c..2308f665e 100644 --- a/lemonldap-ng-portal/site/templates/common/mail/it.json +++ b/lemonldap-ng-portal/site/templates/common/mail/it.json @@ -7,6 +7,7 @@ "goToPortal":"Vai al portale", "hello":"Salve", "host":"Host", +"location":"Location", "mail2fSubject":"[LemonLDAP :: NG] Il tuo codice di accesso", "mailConfirmSubject":"Conferma reimpostazione password [LemonLDAP::NG] ", "mailSubject":"[LemonLDAP::NG] La tua nuova password", diff --git a/lemonldap-ng-portal/site/templates/common/mail/ms.json b/lemonldap-ng-portal/site/templates/common/mail/ms.json index 30382392b..c51b428bb 100644 --- a/lemonldap-ng-portal/site/templates/common/mail/ms.json +++ b/lemonldap-ng-portal/site/templates/common/mail/ms.json @@ -7,6 +7,7 @@ "goToPortal":"Go to portal", "hello":"Hello", "host":"Host", +"location":"Location", "mail2fSubject":"[LemonLDAP::NG] Kod login anda", "mailConfirmSubject":"[LemonLDAP::NG] Pengesahan penetapan semula kata laluan", "mailSubject":"[LemonLDAP::NG] Kata laluan baru anda", diff --git a/lemonldap-ng-portal/site/templates/common/mail/tr.json b/lemonldap-ng-portal/site/templates/common/mail/tr.json index 90a4b7f25..007afe18f 100644 --- a/lemonldap-ng-portal/site/templates/common/mail/tr.json +++ b/lemonldap-ng-portal/site/templates/common/mail/tr.json @@ -7,6 +7,7 @@ "goToPortal":"Portala git", "hello":"Merhaba", "host":"Host", +"location":"Location", "mail2fSubject":"[LemonLDAP::NG] Giriş kodunuz", "mailConfirmSubject":"[LemonLDAP::NG] Parola sıfırlama onayı", "mailSubject":"[LemonLDAP::NG] Yeni parolanız", diff --git a/lemonldap-ng-portal/site/templates/common/mail/vi.json b/lemonldap-ng-portal/site/templates/common/mail/vi.json index a032a689a..dc0ba8c55 100644 --- a/lemonldap-ng-portal/site/templates/common/mail/vi.json +++ b/lemonldap-ng-portal/site/templates/common/mail/vi.json @@ -7,6 +7,7 @@ "goToPortal":"Đi tới cổng thông tin", "hello":"Xin chào", "host":"Host", +"location":"Location", "mail2fSubject":"[LemonLDAP::NG] Your login code", "mailConfirmSubject":"[LemonLDAP::NG] Xác nhận thiết lập lại mật khẩu", "mailSubject":"[LemonLDAP::NG] Mật khẩu mới của bạn", diff --git a/lemonldap-ng-portal/site/templates/common/mail/zh_CN.json b/lemonldap-ng-portal/site/templates/common/mail/zh_CN.json index 254831821..d777f21c9 100644 --- a/lemonldap-ng-portal/site/templates/common/mail/zh_CN.json +++ b/lemonldap-ng-portal/site/templates/common/mail/zh_CN.json @@ -7,6 +7,7 @@ "goToPortal":"回到首页", "hello":"您好", "host":"Host", +"location":"Location", "mail2fSubject":"[LemonLDAP::NG] Your login code", "mailConfirmSubject":"[LemonLDAP::NG] 密码重置确认", "mailSubject":"[LemonLDAP::NG] 您的新密码", diff --git a/lemonldap-ng-portal/site/templates/common/mail/zh_TW.json b/lemonldap-ng-portal/site/templates/common/mail/zh_TW.json index 3848db65f..34ce5dcc8 100644 --- a/lemonldap-ng-portal/site/templates/common/mail/zh_TW.json +++ b/lemonldap-ng-portal/site/templates/common/mail/zh_TW.json @@ -7,6 +7,7 @@ "goToPortal":"回到首頁", "hello":"您好", "host":"Host", +"location":"Location", "mail2fSubject":"[LemonLDAP::NG] 您的登入代碼", "mailConfirmSubject":"[LemonLDAP::NG] 確認重設密碼", "mailSubject":"[LemonLDAP::NG] 您的新密碼", diff --git a/lemonldap-ng-portal/site/templates/common/mail_new_location_warning.tpl b/lemonldap-ng-portal/site/templates/common/mail_new_location_warning.tpl index ef94ada5d..fd44a1b76 100644 --- a/lemonldap-ng-portal/site/templates/common/mail_new_location_warning.tpl +++ b/lemonldap-ng-portal/site/templates/common/mail_new_location_warning.tpl @@ -4,7 +4,7 @@ Hello ,

Your account was signed in to from a new location


-Host
+Location
Date
UA