Commit 09f13b1b authored by Xavier Guimard's avatar Xavier Guimard

Notification server SOAP/REST (#595)

parent 761cf58e
......@@ -3,10 +3,8 @@
* Test ForceAuth
* Calendar in notifications explorer
* Test for Zero
* replace SOAP by REST for notification creation
* "mail" in UserDB/*
* verify activeTimer on/off on screen
* Add test for #173
# Combination
......
......@@ -129,7 +129,7 @@
.\" ========================================================================
.\"
.IX Title "llng-fastcgi-server 1"
.TH llng-fastcgi-server 1 "2017-02-18" "perl v5.24.1" "User Contributed Perl Documentation"
.TH llng-fastcgi-server 1 "2017-02-19" "perl v5.24.1" "User Contributed Perl Documentation"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
......
......@@ -38,7 +38,7 @@ sub _connect {
if ( $self->{proxyOptions} ) {
push @args, %{ $self->{proxyOptions} };
}
$self->{ns} ||= 'urn:/Lemonldap/NG/Common/CGI/SOAPService';
$self->{ns} ||= 'urn:/Lemonldap/NG/Common/PSGI/SOAPService';
return $self->{service} = SOAP::Lite->ns( $self->{ns} )->proxy(@args);
}
......
......@@ -170,7 +170,7 @@ sub defaultValues {
'remoteGlobalStorage' => 'Lemonldap::NG::Common::Apache::Session::SOAP',
'remoteGlobalStorageOptions' => {
'ns' =>
'http://auth.example.com/Lemonldap/NG/Common/CGI/SOAPService',
'http://auth.example.com/Lemonldap/NG/Common/PSGI/SOAPService',
'proxy' => 'http://auth.example.com/sessions'
},
'requireToken' => 1,
......
......@@ -1398,6 +1398,10 @@ qr/^(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-
'default' => 0,
'type' => 'bool'
},
'notificationServer' => {
'default' => 0,
'type' => 'bool'
},
'notificationStorage' => {
'default' => 'File',
'type' => 'PerlModule'
......@@ -2061,7 +2065,7 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.]
'remoteGlobalStorageOptions' => {
'default' => {
'ns' =>
'http://auth.example.com/Lemonldap/NG/Common/CGI/SOAPService',
'http://auth.example.com/Lemonldap/NG/Common/PSGI/SOAPService',
'proxy' => 'http://auth.example.com/sessions'
},
'type' => 'keyTextContainer'
......
......@@ -667,6 +667,11 @@ sub attributes {
type => 'bool',
documentation => 'Notification activation',
},
notificationServer => {
default => 0,
type => 'bool',
documentation => 'Notification server activation',
},
notificationStorage => {
type => 'PerlModule',
default => 'File',
......@@ -1984,7 +1989,7 @@ m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
default => {
proxy => 'http://auth.example.com/sessions',
ns =>
'http://auth.example.com/Lemonldap/NG/Common/CGI/SOAPService',
'http://auth.example.com/Lemonldap/NG/Common/PSGI/SOAPService',
},
documentation => 'Demo exported variables',
},
......
......@@ -518,6 +518,7 @@ sub tree {
help => 'notifications.html',
nodes => [
'notification',
'notificationServer',
'oldNotifFormat',
'notificationStorage',
'notificationStorageOptions',
......
......@@ -374,6 +374,7 @@
"notAValidPerlExpression": "Not a valid Perl expression",
"notification": "Activation",
"notifications": "Notifications",
"notificationServer": "Notification server",
"notificationCreated": "Notification has been created",
"notificationDeleted": "Notification deleted",
"notificationDone": "notification done",
......
......@@ -374,6 +374,7 @@
"notAValidPerlExpression": "Pas une expression Perl valide",
"notification": "Activation",
"notifications": "Notifications",
"notificationServer": "Serveur de notifications",
"notificationCreated": "La notification a été créée",
"notificationDeleted": "La notification a été marquée comme lue",
"notificationDone": "notification validée",
......
......@@ -744,7 +744,7 @@
}, {
"cnodes": "remoteGlobalStorageOptions",
"default": [{
"data": "http://auth.example.com/Lemonldap/NG/Common/CGI/SOAPService",
"data": "http://auth.example.com/Lemonldap/NG/Common/PSGI/SOAPService",
"id": "remoteGlobalStorageOptions/ns",
"title": "ns",
"type": "keyText"
......
......@@ -873,7 +873,7 @@
}, {
"cnodes": "remoteGlobalStorageOptions",
"default": [{
"data": "http://auth.example.com/Lemonldap/NG/Common/CGI/SOAPService",
"data": "http://auth.example.com/Lemonldap/NG/Common/PSGI/SOAPService",
"id": "remoteGlobalStorageOptions/ns",
"title": "ns",
"type": "keyText"
......
......@@ -883,7 +883,7 @@
}, {
"cnodes": "remoteGlobalStorageOptions",
"default": [{
"data": "http://auth.example.com/Lemonldap/NG/Common/CGI/SOAPService",
"data": "http://auth.example.com/Lemonldap/NG/Common/PSGI/SOAPService",
"id": "remoteGlobalStorageOptions/ns",
"title": "ns",
"type": "keyText"
......
......@@ -873,7 +873,7 @@
}, {
"cnodes": "remoteGlobalStorageOptions",
"default": [{
"data": "http://auth.example.com/Lemonldap/NG/Common/CGI/SOAPService",
"data": "http://auth.example.com/Lemonldap/NG/Common/PSGI/SOAPService",
"id": "remoteGlobalStorageOptions/ns",
"title": "ns",
"type": "keyText"
......
......@@ -1264,7 +1264,7 @@
{
"cnodes": "remoteGlobalStorageOptions",
"default": [{
"data": "http://auth.example.com/Lemonldap/NG/Common/CGI/SOAPService",
"data": "http://auth.example.com/Lemonldap/NG/Common/PSGI/SOAPService",
"id": "remoteGlobalStorageOptions/ns",
"title": "ns",
"type": "keyText"
......
......@@ -224,4 +224,13 @@ sub toForm {
return $tpl->output;
}
sub notificationServer {
my ( $self, $req ) = @_;
return $self->p->sendError( $req, 'Only JSON requests here', 400 )
unless ( $req->wantJSON );
my $res = $self->notifObject->newNotification( $req->content );
return $self->p->sendError( $req, 'Bad request', 400 ) unless ($res);
return $self->p->sendJSONresponse( $req, { result => $res } );
}
1;
......@@ -246,4 +246,37 @@ sub getNotifBack {
}
}
has imported => ( is => 'rw', default => 0 );
has server => ( is => 'rw' );
sub notificationServer {
my ( $self, $req ) = @_;
unless ($self->imported) {
eval {
require Lemonldap::NG::Common::PSGI::SOAPServer;
require Lemonldap::NG::Common::PSGI::SOAPService;
};
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);
}
1;
......@@ -299,7 +299,7 @@ sub getApacheSession {
if ( my $err = $as->error ) {
$self->lmLog( $err,
( $err =~ /Object does not exist/ ? 'notice' : 'error' ) );
( $err =~ /(?:Object does not exist|Invalid session ID)/ ? 'notice' : 'error' ) );
return;
}
......
......@@ -40,6 +40,14 @@ sub init {
$self->addUnauthRoute( 'notifback' => 'getNotifBack', ['POST'] );
$self->addAuthRoute( 'notifback' => 'getNotifBack', ['POST'] );
if ( $self->conf->{notificationServer} ) {
$self->logger->debug('Notification server enable');
$self->addUnauthRoute(
'notifications' => 'notificationServer',
['POST']
);
}
# Search for configuration options
my $type = $self->conf->{notificationStorage};
unless ($type) {
......@@ -114,4 +122,9 @@ sub getNotifBack {
return $self->module->getNotifBack(@_);
}
sub notificationServer {
my ( $self, $req ) = @_;
return $self->module->notificationServer($req);
}
1;
use Test::More;
use strict;
use IO::String;
BEGIN {
require 't/test-lib.pm';
}
eval { unlink 't/20160530_dwho_dGVzdHJlZg==.json' };
my $json = '{
"date": "2016-05-30",
"reference": "testref",
"uid": "dwho",
"title": "Test title",
"text": "This is a test text"
}';
my $client = LLNG::Manager::Test->new(
{
ini => {
logLevel => 'error',
useSafeJail => 1,
notification => 1,
notificationServer => 1,
templatesDir => 'site/templates/',
notificationStorage => 'File',
notificationStorageOptions => {
dirName => 't'
},
}
}
);
my $res;
ok(
$res = $client->_post(
'/notifications', IO::String->new($json),
type => 'application/json',
length => length($json)
),
'Create notification'
);
count(1);
# Try yo authenticate
# -------------------
my $res;
ok(
$res = $client->_post(
'/',
IO::String->new(
'user=dwho&password=dwho&url=aHR0cDovL3Rlc3QxLmV4YW1wbGUuY29tLw=='
),
accept => 'text/html',
length => 64,
),
'Auth query'
);
count(1);
expectOK($res);
my $id = expectCookie($res);
expectForm( $res, undef, '/notifback', 'reference1x1', 'url' );
eval { unlink 't/20160530_dwho_dGVzdHJlZg==.json' };
clean_sessions();
done_testing( count() );
use Test::More;
use strict;
use IO::String;
BEGIN {
require 't/test-lib.pm';
}
my $maintests = 3;
my $debug = 'error';
my $client;
eval { unlink 't/20160530_dwho_dGVzdHJlZg==.xml' };
my $xml = '<?xml version="1.0" encoding="UTF-8"?>
<root><notification uid="dwho" date="2016-05-30" reference="testref">
<title>Test title</title>
<subtitle>Test subtitle</subtitle>
<text>This is a test text</text>
</notification></root>';
SKIP: {
eval "use SOAP::Lite";
if ($@) {
skip 'SOAP::Lite not found', $maintests;
}
$client = LLNG::Manager::Test->new(
{
ini => {
logLevel => 'error',
useSafeJail => 1,
notification => 1,
notificationServer => 1,
templatesDir => 'site/templates/',
notificationStorage => 'File',
notificationStorageOptions => {
dirName => 't'
},
oldNotifFormat => 1,
}
}
);
my $soap;
ok(
$soap =
SOAP::Lite->new( proxy => 'http://auth.example.com/notifications' ),
'SOAP client'
);
$soap->default_ns('urn:Lemonldap/NG/Common/PSGI/SOAPService');
ok( $soap->call( 'newNotification', $xml )->result() ==1, ' SOAP call returns 1' );
# Try yo authenticate
# -------------------
my $res;
ok(
$res = $client->_post(
'/',
IO::String->new(
'user=dwho&password=dwho&url=aHR0cDovL3Rlc3QxLmV4YW1wbGUuY29tLw=='
),
accept => 'text/html',
length => 64,
),
'Auth query'
);
expectOK($res);
my $id = expectCookie($res);
expectForm( $res, undef, '/notifback', 'reference1x1', 'url' );
}
eval { unlink 't/20160530_dwho_dGVzdHJlZg==.xml' };
count($maintests);
clean_sessions();
done_testing( count() );
# Redefine LWP methods for tests
no warnings 'redefine';
sub LWP::UserAgent::request {
my ( $self, $req ) = @_;
ok( $req->uri =~ m#http://auth.example.com(.*)#, ' @ SOAP REQUEST @' );
my $url = $1;
my $res;
my $s = $req->content;
ok(
$res = $client->_post(
$url,
IO::String->new($s),
length => length($s),
type => $req->header('Content-Type'),
custom => {
HTTP_SOAPACTION => $req->header('Soapaction'),
},
),
' Execute request'
);
expectOK($res);
ok( getHeader( $res, 'Content-Type' ) =~ m#^(?:text|application)/xml#,
' Content is XML' )
or explain( $res->[1], 'Content-Type => application/xml' );
my $httpResp = HTTP::Response->new( $res->[0], 'OK' );
while ( my $name = shift @{ $res->[1] } ) {
$httpResp->header( $name, shift( @{ $res->[1] } ) );
}
$httpResp->content( join( '', @{ $res->[2] } ) );
pass(' @ END OF SOAP REQUEST @');
count(4);
return $httpResp;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment