our
$VERSION
=
'2.0.15'
;
has
parser
=> (
is
=>
'rw'
,
builder
=>
sub
{
return
XML::LibXML->new(
load_ext_dtd
=> 0,
expand_entities
=> 0 );
}
);
has
stylesheet
=> (
is
=>
'rw'
,
lazy
=> 1,
builder
=>
sub
{
my
$self
=
$_
[0];
my
$xslt
= XML::LibXSLT->new();
my
$styleFile
=
(
$self
->conf->{notificationXSLTfile}
and -e
$self
->conf->{notificationXSLTfile} )
?
$self
->conf->{notificationXSLTfile}
:
$self
->conf->{templateDir} .
'/common/notification.xsl'
;
unless
( -e
$styleFile
) {
$self
->{logger}->error(
"$styleFile not found, aborting"
);
die
"$styleFile not found"
;
}
return
$xslt
->parse_stylesheet(
$self
->parser->parse_file(
$styleFile
) );
}
);
has
notifObject
=> (
is
=>
'rw'
);
has
imported
=> (
is
=>
'rw'
,
default
=> 0 );
has
server
=> (
is
=>
'rw'
);
sub
init {
return
1;
}
sub
checkForNotifications {
my
(
$self
,
$req
) =
@_
;
my
$uid
=
$req
->sessionInfo->{
$self
->notifObject->notifField };
my
(
$notifs
,
$forUser
) =
$self
->notifObject->getNotifications(
$uid
);
my
$form
;
unless
(
$notifs
) {
$self
->logger->info(
"No notification found"
);
return
0;
}
my
$i
= 0;
my
$now
= strftime
"%Y-%m-%d"
,
localtime
;
foreach
my
$file
(
values
%$notifs
) {
my
$xml
=
$self
->parser->parse_string(
$file
);
my
$j
= 0;
LOOP:
foreach
my
$notif
(
eval
{
$xml
->documentElement->getElementsByTagName(
'notification'
);
}
)
{
my
$reference
=
$notif
->getAttribute(
'reference'
);
$self
->logger->debug(
"Get reference $reference"
);
if
(
exists
$req
->{sessionInfo}->{
"notification_$reference"
} ) {
$self
->logger->debug(
"Notification $reference was already accepted"
);
$notif
->unbindNode();
next
LOOP;
}
my
$date
=
$notif
->getAttribute(
'date'
);
$self
->logger->debug(
"Get date: $date"
);
unless
(
$date
and
$date
=~ /\b\d{4}-\d{2}-\d{2}\b/ ) {
$self
->logger->error(
'Malformed date'
);
$notif
->unbindNode();
next
LOOP;
}
unless
(
$date
le
$now
) {
$self
->logger->debug(
'Notification date not reached'
);
$notif
->unbindNode();
next
LOOP;
}
if
(
my
$condition
=
$notif
->getAttribute(
'condition'
) ) {
$self
->logger->debug(
"Get condition $condition"
);
$condition
=
$self
->p->HANDLER->substitute(
$condition
);
unless
(
$condition
=
$self
->p->HANDLER->buildSub(
$condition
) )
{
$self
->logger->error(
'Notification condition error: '
.
$self
->p->HANDLER->tsv->{jail}->error );
$notif
->unbindNode();
next
LOOP;
}
unless
(
$condition
->(
$req
,
$req
->sessionInfo ) ) {
$self
->logger->debug(
'Notification condition not authorized'
);
$notif
->unbindNode();
next
LOOP;
}
}
$j
++;
}
next
unless
$j
;
$i
++;
my
$results
=
$self
->stylesheet->transform(
$xml
,
start
=>
$i
);
$form
.=
$self
->stylesheet->output_string(
$results
);
}
if
($@) {
$self
->userLogger->
warn
(
"Bad XML file: a notification for $uid was not done ($@)"
);
return
0;
}
return
0
unless
$i
;
$self
->userLogger->info(
"$i pending notification(s) found for $uid"
);
return
$form
;
}
sub
viewNotification {
my
(
$self
,
$req
,
$ref
,
$epoch
) =
@_
;
my
$uid
=
$req
->userData->{
$self
->notifObject->notifField };
my
(
$notifs
,
$forUser
) =
$self
->notifObject->getAcceptedNotifs(
$uid
,
$ref
);
my
$form
;
unless
(
$notifs
) {
$self
->logger->info(
"No accepted notification found"
);
return
0;
}
my
$i
= 0;
foreach
my
$file
(
values
%$notifs
) {
my
$xml
=
$self
->parser->parse_string(
$file
);
my
$j
= 0;
LOOP:
foreach
my
$notif
(
eval
{
$xml
->documentElement->getElementsByTagName(
'notification'
);
}
)
{
my
$reference
=
$notif
->getAttribute(
'reference'
);
$self
->logger->debug(
"Get reference $reference"
);
unless
(
exists
$req
->{userData}->{
"notification_$reference"
}
and
$req
->{userData}->{
"notification_$reference"
} eq
$epoch
and
$reference
eq
$ref
)
{
$self
->logger->debug(
"Notification $reference was already accepted"
);
$notif
->unbindNode();
next
LOOP;
}
$j
++;
}
next
unless
$j
;
$i
++;
my
$results
=
$self
->stylesheet->transform(
$xml
,
start
=>
$i
);
$form
.=
$self
->stylesheet->output_string(
$results
);
}
if
($@) {
$self
->userLogger->
warn
(
"Bad XML file: a notification for $uid was not done ($@)"
);
return
0;
}
return
0
unless
$i
;
$self
->userLogger->info(
"$i accepted notification(s) found for $uid"
);
return
$form
;
}
sub
getNotifBack {
my
(
$self
,
$req
,
$name
) =
@_
;
my
$id
;
return
$self
->p->sendError(
$req
,
'No cookie found'
, 401 )
unless
(
$id
=
$req
->cookies->{
$self
->{conf}->{cookieName} } );
if
(
$req
->param(
'cancel'
) ) {
$self
->logger->debug(
'Cancel called -> remove ciphered cookie'
);
$req
->addCookie(
$self
->p->cookie(
name
=>
$self
->conf->{cookieName},
value
=> 0,
domain
=>
$self
->conf->{domain},
secure
=>
$self
->conf->{securedCookie},
expires
=>
'Wed, 21 Oct 2015 00:00:00 GMT'
)
);
$req
->mustRedirect(1);
return
$self
->p->
do
(
$req
, [] );
}
$id
=
$self
->p->HANDLER->tsv->{cipher}->decrypt(
$id
)
or
return
$self
->sendError(
$req
,
'Unable to decrypt ciphered id'
, 400 );
$req
->userData(
$self
->p->HANDLER->retrieveSession(
$req
,
$id
) )
or
return
$self
->sendError(
$req
,
'Unknown session'
, 401 );
$self
->p->importHandlerData(
$req
);
my
$uid
=
$req
->sessionInfo->{
$self
->notifObject->notifField };
my
(
$notifs
,
$forUser
) =
eval
{
$self
->notifObject->getNotifications(
$uid
) };
return
$self
->p->sendError(
$req
, $@, 500 )
if
($@);
if
(
$notifs
) {
my
(
$refs
,
$checks
) = ( {}, {} );
my
$prms
=
$req
->parameters;
foreach
(
keys
%$prms
) {
my
$v
=
$prms
->{
$_
};
if
(s/^reference//) {
$refs
->{
$v
} =
$_
;
}
elsif
( s/^check// and /^(\d+x\d+)x(\d+)$/ and
$v
eq
'accepted'
) {
push
@{
$checks
->{$1} }, $2;
}
}
my
$result
= 1;
my
$now
= strftime
"%Y-%m-%d"
,
localtime
;
foreach
my
$fileName
(
keys
%$notifs
) {
my
$file
=
$notifs
->{
$fileName
};
my
$fileResult
= 1;
my
$xml
=
$self
->parser->parse_string(
$file
);
LOOP:
foreach
my
$notif
(
$xml
->documentElement->getElementsByTagName(
'notification'
) )
{
my
$reference
=
$notif
->getAttribute(
'reference'
);
my
$date
=
$notif
->getAttribute(
'date'
);
$self
->logger->debug(
"Get date: $date"
);
unless
(
$date
and
$date
=~ /\b\d{4}-\d{2}-\d{2}\b/ ) {
$self
->logger->error(
'Malformed date'
);
next
LOOP;
}
unless
(
$date
le
$now
) {
$self
->logger->debug(
'Notification date not reached'
);
$fileResult
= 0;
next
LOOP;
}
if
(
my
$condition
=
$notif
->getAttribute(
'condition'
) ) {
$self
->logger->debug(
"Get condition $condition"
);
$condition
=
$self
->p->HANDLER->substitute(
$condition
);
unless
(
$condition
=
$self
->p->HANDLER->buildSub(
$condition
) )
{
$self
->logger->error(
'Notification condition error: '
.
$self
->p->HANDLER->tsv->{jail}->error );
next
LOOP;
}
unless
(
$condition
->(
$req
,
$req
->sessionInfo ) ) {
$self
->logger->debug(
'Notification condition not authorized'
);
$fileResult
= 0;
next
LOOP;
}
}
if
(
my
$refId
=
$refs
->{
$reference
} ) {
my
@toCheck
=
$notif
->getElementsByTagName(
'check'
);
if
(
my
$toCheckCount
=
@toCheck
) {
unless
(
$checks
->{
$refId
}
and
$toCheckCount
== @{
$checks
->{
$refId
} } )
{
$self
->userLogger->notice(
"$uid has not accepted notification $reference"
);
$result
=
$fileResult
= 0;
next
;
}
}
}
else
{
$result
=
$fileResult
= 0;
$self
->logger->debug(
'Current pending notification has not been found'
);
next
;
}
$self
->userLogger->notice(
"$uid has accepted notification $reference"
);
$self
->p->updatePersistentSession(
$req
,
{
"notification_$reference"
=>
time
() } );
$self
->logger->debug(
"Notification $reference registered in persistent session"
);
}
if
(
$fileResult
and
exists
$forUser
->{
$fileName
} ) {
$self
->logger->debug(
"Notification file deleted"
);
$self
->notifObject->
delete
(
$fileName
);
}
}
unless
(
$result
) {
$self
->logger->debug(
'Pending notification has been found and not accepted'
);
return
$self
->p->
do
(
$req
, [ @{
$self
->p->endAuth } ] );
}
$self
->logger->debug(
'All pending notifications have been accepted'
);
$self
->p->rebuildCookies(
$req
);
return
$self
->p->
do
(
$req
, [
'controlUrl'
, @{
$self
->p->endAuth } ] );
}
else
{
$self
->logger->debug(
'No notifications checked'
);
$req
->mustRedirect(1);
return
$self
->p->
do
(
$req
, [] );
}
}
sub
notificationServer {
my
(
$self
,
$req
) =
@_
;
unless
(
$self
->imported ) {
eval
{
};
if
($@) {
return
$self
->p->sendError(
$req
, $@, 500 );
}
$self
->server( Lemonldap::NG::Common::PSGI::SOAPServer->new );
$self
->imported(1);
}
unless
(
$req
->env->{HTTP_SOAPACTION} ) {
return
$self
->p->sendError(
$req
,
'SOAP requests only'
, 400 );
}
return
$self
->server->dispatch_to(
Lemonldap::NG::Common::PSGI::SOAPService->new(
$self
,
$req
,
'newNotification'
,
)
)->handle(
$req
);
}
sub
newNotification {
my
(
$self
,
$req
,
$xml
) =
@_
;
return
$self
->notifObject->newNotification(
$xml
,
$self
->conf->{notificationDefaultCond} );
}
1;