lemonldap-ng/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/Notifications.pm

252 lines
6.9 KiB
Perl
Raw Normal View History

2016-05-29 09:48:06 +02:00
# Notifications plugin.
#
2016-05-31 13:47:08 +02:00
# Two entry points for notifications:
2016-05-29 09:48:06 +02:00
# * a new route "/notifback" for checking accepted notifications
# (sub getNotifBack). It launch then autoRedirect() with "mustRedirect"
# set to 1 because underlying handler has not seen user as authenticated
# so data are not set;
2016-05-31 13:47:08 +02:00
# * a callback inserted in process steps after authentication process,
# This callback launches checkForNotifications to get notification and
# cipher LemonLDAP::NG cookies.
2016-05-29 09:48:06 +02:00
2016-05-28 10:33:39 +02:00
package Lemonldap::NG::Portal::Plugins::Notifications;
use strict;
use Mouse;
use MIME::Base64;
use Lemonldap::NG::Portal::Main::Constants qw(
PE_OK
2020-10-09 22:26:00 +02:00
PE_ERROR
PE_NOTIFICATION
);
2016-05-28 10:33:39 +02:00
2019-02-12 18:21:38 +01:00
our $VERSION = '2.1.0';
2016-05-28 10:33:39 +02:00
extends 'Lemonldap::NG::Portal::Main::Plugin';
2016-06-09 20:40:20 +02:00
# INTERFACE
2016-05-29 09:48:06 +02:00
# Declare additional process steps
use constant endAuth => 'checkNotifDuringAuth';
2016-05-28 10:33:39 +02:00
2016-06-09 20:40:20 +02:00
# For now, notifications are done only during authentication process
#sub forAuthUser { 'checkNotifForAuthUser' }
# PROPERTIES
has module => ( is => 'rw' );
2016-06-09 20:40:20 +02:00
# INITIALIZATION
2016-05-28 10:33:39 +02:00
sub init {
my ($self) = @_;
2020-02-09 18:40:43 +01:00
# Declare new routes
2020-10-09 22:26:00 +02:00
$self->addUnauthRoute( notifback => 'getNotifBack', [ 'POST', 'GET' ] )
->addAuthRoute( notifback => 'getNotifBack', ['POST'] );
2020-02-09 18:40:43 +01:00
$self->addAuthRouteWithRedirect(
mynotifications => { '*' => 'myNotifs' },
['GET']
) if $self->conf->{notificationsExplorer};
2016-05-29 09:48:06 +02:00
2017-02-19 18:04:49 +01:00
if ( $self->conf->{notificationServer} ) {
$self->logger->debug('Notification server enable');
2019-07-31 23:38:48 +02:00
2017-02-19 18:04:49 +01:00
$self->addUnauthRoute(
2019-07-22 15:39:59 +02:00
notifications => 'notificationServer',
2017-02-19 18:04:49 +01:00
['POST']
2019-07-25 10:49:49 +02:00
) if ( $self->conf->{notificationServerPOST} // 1 );
2019-07-31 23:38:48 +02:00
2019-07-22 15:39:59 +02:00
$self->addUnauthRoute(
notifications => { '*' => 'notificationServer' },
['GET']
2019-07-25 10:49:49 +02:00
) if ( $self->conf->{notificationServerGET} );
2019-07-31 23:38:48 +02:00
2019-07-22 15:39:59 +02:00
$self->addUnauthRoute(
notifications =>
{ ':uid' => { ':reference' => 'notificationServer' } },
['DELETE']
2019-07-25 10:49:49 +02:00
) if ( $self->conf->{notificationServerDELETE} );
2017-02-19 18:04:49 +01:00
}
2016-05-29 09:48:06 +02:00
# Search for configuration options
2016-05-28 10:33:39 +02:00
my $type = $self->conf->{notificationStorage};
unless ($type) {
$self->error('notificationStorage is not defined, aborting');
return 0;
}
2016-05-29 09:48:06 +02:00
# Initialize notifications storage object
2016-06-02 23:20:36 +02:00
$type = "Lemonldap::NG::Common::Notifications::$type";
2016-05-29 09:48:06 +02:00
eval "require $type";
2016-05-28 10:33:39 +02:00
if ($@) {
2016-06-02 23:20:36 +02:00
$self->error(
"Unable to load Lemonldap::NG::Common::Notifications::$type: $@");
2016-05-28 10:33:39 +02:00
return 0;
}
$type->import( $self->conf->{oldNotifFormat} ? 'XML' : 'JSON' );
2016-05-28 10:33:39 +02:00
# TODO: use conf database?
2016-06-02 23:20:36 +02:00
my $prms = {
%{ $self->conf->{notificationStorageOptions} },
p => $self->p,
conf => $self->p->conf
};
if ( $self->conf->{oldNotifFormat} ) {
$self->module( $self->p->loadModule('::Lib::Notifications::XML') )
or return 0;
}
else {
$self->module( $self->p->loadModule('::Lib::Notifications::JSON') )
or return 0;
}
unless ( eval { $self->module->notifObject( $type->new($prms) ); } ) {
2016-05-28 10:33:39 +02:00
$self->error($@);
return 0;
}
2020-02-10 22:35:37 +01:00
2020-10-09 22:26:00 +02:00
return 1;
2016-05-28 10:33:39 +02:00
}
2016-05-31 13:47:08 +02:00
#sub checkNotifForAuthUser {
# my ( $self, $req ) = @_;
# if ( my $notif = $self->checkForNotifications($req) ) {
#
# # Cipher cookies
# return PE_NOTIFICATION;
# }
# else {
# return PE_OK;
# }
#}
2016-05-29 09:48:06 +02:00
2016-06-09 20:40:20 +02:00
# RUNNING METHODS
2016-05-31 13:47:08 +02:00
sub checkNotifDuringAuth {
2016-05-29 09:48:06 +02:00
my ( $self, $req ) = @_;
eval {
$req->{data}->{notification} =
$self->module->checkForNotifications($req);
};
if ($@) {
$self->logger->error($@);
return PE_ERROR;
}
if ( $req->{data}->{notification} ) {
2018-09-05 13:35:50 +02:00
# Cipher id
$req->id( $self->p->HANDLER->tsv->{cipher}->encrypt( $req->id ) );
$self->p->rebuildCookies($req);
if ( not $req->pdata->{_url}
and not $req->data->{_url}
and $req->env->{PATH_INFO} ne '/' )
{
$req->data->{_url} =
encode_base64( $self->conf->{portal} . $req->env->{PATH_INFO},
'' );
}
2016-05-29 09:48:06 +02:00
# Restore and cipher cookies
2016-05-30 22:20:53 +02:00
return PE_NOTIFICATION;
2016-05-29 09:48:06 +02:00
}
else {
return PE_OK;
}
}
2016-05-28 10:33:39 +02:00
sub getNotifBack {
my $self = shift;
return $self->module->getNotifBack(@_);
2016-05-30 13:32:21 +02:00
}
2017-02-19 18:04:49 +01:00
sub notificationServer {
2019-07-22 15:39:59 +02:00
my ( $self, $req, @args ) = @_;
2019-07-25 10:49:49 +02:00
return $self->module->notificationServer( $req, @args );
2017-02-19 18:04:49 +01:00
}
2020-02-09 17:47:25 +01:00
sub myNotifs {
my ( $self, $req, $ref ) = @_;
if ($ref) {
2020-05-23 23:52:09 +02:00
return $self->sendJSONresponse( $req,
{ error => 'Missing epoch parameter' } )
2020-02-09 17:47:25 +01:00
unless $req->param('epoch');
2020-02-12 21:50:35 +01:00
# Retrieve notification reference=$ref with epoch
2020-02-09 17:47:25 +01:00
my $notif = $self->_viewNotif( $req, $ref, $req->param('epoch') );
2020-02-10 10:04:10 +01:00
$notif =~ s/"checkbox"/"checkbox" checked disabled/g;
2020-02-10 10:58:48 +01:00
2020-02-12 21:50:35 +01:00
# Return HTML fragment
2020-02-09 17:47:25 +01:00
return $self->sendJSONresponse( $req,
2020-02-10 10:58:48 +01:00
{ notification => $notif, result => ( $notif ? 1 : 0 ) } );
2020-02-09 17:47:25 +01:00
}
my $_notifications = $self->retrieveNotifs($req);
2020-02-12 21:50:35 +01:00
my $nbr = @$_notifications;
my $msg = $nbr ? 'myNotification' : 'noNotification';
$msg .= 's' if ( $nbr > 1 );
$self->logger->debug("$nbr accepted notification(s) found");
2020-02-09 17:47:25 +01:00
2020-02-12 21:50:35 +01:00
# Build template
2020-02-09 17:47:25 +01:00
my $params = {
PORTAL => $self->conf->{portal},
MAIN_LOGO => $self->conf->{portalMainLogo},
SKIN => $self->p->getSkin($req),
LANGS => $self->conf->{showLanguages},
2020-02-09 18:22:34 +01:00
NOTIFICATIONS => $_notifications,
2020-02-10 09:31:43 +01:00
MSG => $msg
2020-02-09 17:47:25 +01:00
};
2020-02-12 21:50:35 +01:00
return $self->sendJSONresponse( $req, { %$params, result => $nbr } )
if ( $req->wantJSON );
2020-02-09 17:47:25 +01:00
2020-02-12 21:50:35 +01:00
# Display template
2020-02-09 17:47:25 +01:00
return $self->p->sendHtml( $req, 'notifications', params => $params );
}
sub retrieveNotifs {
my ( $self, $req ) = @_;
# Retrieve user's accepted notifications
2020-03-03 16:54:42 +01:00
$self->logger->debug( 'Searching for "'
. $req->userData->{ $self->conf->{whatToTrace} }
. '" accepted notification(s)' );
2020-02-12 21:50:35 +01:00
my @_notifications = sort {
$b->{epoch} <=> $a->{epoch}
or $a->{reference} cmp $b->{reference}
2020-05-23 23:52:09 +02:00
} (
2020-02-09 17:47:25 +01:00
map {
/^notification_(.+)$/
? { reference => $1, epoch => $req->{userData}->{$_} }
: ()
}
keys %{ $req->{userData} }
2020-05-23 23:52:09 +02:00
);
2020-02-12 21:50:35 +01:00
splice @_notifications, $self->conf->{notificationsMaxRetrieve};
2020-02-09 17:47:25 +01:00
2020-02-12 21:50:35 +01:00
return \@_notifications;
2020-02-09 17:47:25 +01:00
}
sub _viewNotif {
my ( $self, $req, $ref, $epoch ) = @_;
2020-03-03 16:54:42 +01:00
2020-05-23 23:52:09 +02:00
$self->logger->debug(
"Retrieve notification with reference: \"$ref\" and epoch: \"$epoch\"");
2020-02-10 22:35:37 +01:00
my $notif = eval { $self->module->viewNotification( $req, $ref, $epoch ); };
2020-02-09 17:47:25 +01:00
if ($@) {
2020-05-23 23:52:09 +02:00
$self->logger->debug("Notification not found");
2020-02-09 17:47:25 +01:00
$self->logger->error($@);
return '';
}
2020-02-12 21:50:35 +01:00
2020-02-10 22:35:37 +01:00
return $notif;
2020-02-09 17:47:25 +01:00
}
sub displayLink {
my ( $self, $req ) = @_;
my $_notifications = $self->retrieveNotifs($req);
return ( $self->conf->{notificationsExplorer} && scalar @$_notifications );
}
2016-05-30 13:32:21 +02:00
1;