aboutsummaryrefslogtreecommitdiffstats
path: root/perllib
diff options
context:
space:
mode:
authorM Somerville <matthew-github@dracos.co.uk>2020-10-23 07:26:00 +0100
committerM Somerville <matthew-github@dracos.co.uk>2020-10-23 07:26:00 +0100
commit65b2893f9c2512e51d66885a393b77f84efa8330 (patch)
tree48e4499d8d06ee80ad98cc1b81454a8a1ac15dce /perllib
parentea71d01e3f7ef9cb7be4e671aa8e23c01ebe84f7 (diff)
[Bromley] Waste notification endpoint.
Diffstat (limited to 'perllib')
-rw-r--r--perllib/FixMyStreet/App/Controller/Waste.pm92
1 files changed, 92 insertions, 0 deletions
diff --git a/perllib/FixMyStreet/App/Controller/Waste.pm b/perllib/FixMyStreet/App/Controller/Waste.pm
new file mode 100644
index 000000000..3cdd9fd42
--- /dev/null
+++ b/perllib/FixMyStreet/App/Controller/Waste.pm
@@ -0,0 +1,92 @@
+package FixMyStreet::App::Controller::Waste;
+use Moose;
+use namespace::autoclean;
+
+BEGIN { extends 'Catalyst::Controller' }
+
+use utf8;
+use Open311::GetServiceRequestUpdates;
+
+sub receive_echo_event_notification : Path('/waste/echo') : Args(0) {
+ my ($self, $c) = @_;
+ $c->stash->{format} = 'xml';
+ $c->response->header(Content_Type => 'application/soap+xml');
+
+ require SOAP::Lite;
+
+ $c->detach('soap_error', [ 'Invalid method', 405 ]) unless $c->req->method eq 'POST';
+
+ my $echo = $c->cobrand->feature('echo');
+ $c->detach('soap_error', [ 'Missing config', 500 ]) unless $echo;
+
+ # Make sure we log entire request for debugging
+ $c->detach('soap_error', [ 'Missing body' ]) unless $c->req->body;
+ my $soap = join('', $c->req->body->getlines);
+ $c->log->info($soap);
+
+ my $body = $c->cobrand->body;
+ $c->detach('soap_error', [ 'Bad jurisdiction' ]) unless $body;
+
+ my $env = SOAP::Deserializer->deserialize($soap);
+
+ my $header = $env->header;
+ $c->detach('soap_error', [ 'Missing SOAP header' ]) unless $header;
+ my $action = $header->{Action};
+ $c->detach('soap_error', [ 'Incorrect Action' ]) unless $action && $action eq $echo->{receive_action};
+ $header = $header->{Security};
+ $c->detach('soap_error', [ 'Missing Security header' ]) unless $header;
+ my $token = $header->{UsernameToken};
+ $c->detach('soap_error', [ 'Authentication failed' ])
+ unless $token && $token->{Username} eq $echo->{receive_username} && $token->{Password} eq $echo->{receive_password};
+
+ # Still want to say it is okay, even if we did nothing with it
+ $c->forward('soap_ok');
+}
+
+sub soap_error : Private {
+ my ($self, $c, $comment, $code) = @_;
+ $code ||= 400;
+ $c->response->status($code);
+ my $type = $code == 500 ? 'Server' : 'Client';
+ $c->response->body(SOAP::Serializer->fault($type, "Bad request: $comment", soap_header()));
+}
+
+sub soap_ok : Private {
+ my ($self, $c) = @_;
+ $c->response->status(200);
+ my $method = SOAP::Data->name("NotifyEventUpdatedResponse")->attr({
+ xmlns => "http://www.twistedfish.com/xmlns/echo/api/v1"
+ });
+ $c->response->body(SOAP::Serializer->envelope(method => $method, soap_header()));
+}
+
+sub soap_header {
+ my $attr = "http://www.twistedfish.com/xmlns/echo/api/v1";
+ my $action = "NotifyEventUpdatedResponse";
+ my $header = SOAP::Header->name("Action")->attr({
+ xmlns => 'http://www.w3.org/2005/08/addressing',
+ 'soap:mustUnderstand' => 1,
+ })->value("$attr/ReceiverService/$action");
+
+ my $dt = DateTime->now();
+ my $dt2 = $dt->clone->add(minutes => 5);
+ my $w3c = DateTime::Format::W3CDTF->new;
+ my $header2 = SOAP::Header->name("Security")->attr({
+ 'soap:mustUnderstand' => 'true',
+ 'xmlns' => 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd'
+ })->value(
+ \SOAP::Header->name(
+ "Timestamp" => \SOAP::Header->value(
+ SOAP::Header->name('Created', $w3c->format_datetime($dt)),
+ SOAP::Header->name('Expires', $w3c->format_datetime($dt2)),
+ )
+ )->attr({
+ xmlns => "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd",
+ })
+ );
+ return ($header, $header2);
+}
+
+__PACKAGE__->meta->make_immutable;
+
+1;