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;