2021-06-12 12:13:15 +02:00
< ? php
use Cake\ORM\TableRegistry ;
use Cake\Filesystem\File ;
2021-06-14 16:46:53 +02:00
use Cake\Http\Exception\NotFoundException ;
2021-06-12 12:13:15 +02:00
2021-06-18 11:09:19 +02:00
require_once ( ROOT . DS . 'libraries' . DS . 'default' . DS . 'InboxProcessors' . DS . 'GenericInboxProcessor.php' );
2021-06-12 12:13:15 +02:00
2021-06-18 11:09:19 +02:00
class LocalToolInboxProcessor extends GenericInboxProcessor
2021-06-12 12:13:15 +02:00
{
protected $scope = 'LocalTool' ;
protected $action = 'not-specified' ; //overriden when extending
protected $description = '' ; // overriden when extending
protected $registeredActions = [
'IncomingConnectionRequest' ,
'AcceptedRequest' ,
'DeclinedRequest' ,
];
protected $processingTemplate = 'LocalTool/GenericRequest' ;
protected $Broods ;
2021-06-12 14:04:17 +02:00
protected $LocalTools ;
2021-06-12 12:13:15 +02:00
public function __construct ( $loadFromAction = false )
{
parent :: __construct ( $loadFromAction );
$this -> Broods = TableRegistry :: getTableLocator () -> get ( 'Broods' );
2021-06-12 14:04:17 +02:00
$this -> LocalTools = TableRegistry :: getTableLocator () -> get ( 'LocalTools' );
2021-06-12 12:13:15 +02:00
}
public function create ( $requestData )
{
return parent :: create ( $requestData );
}
2021-06-18 10:03:03 +02:00
protected function updateProcessingTemplate ( $request )
2021-06-12 12:13:15 +02:00
{
2021-06-18 10:03:03 +02:00
$connectorName = $request -> connector [ 'connector' ];
2021-06-14 16:46:53 +02:00
$processingTemplatePath = sprintf ( '%s/%s/%s.php' , $this -> scope , $connectorName , $this -> action );
2021-06-12 12:13:15 +02:00
$file = new File ( $this -> processingTemplatesDirectory . DS . $processingTemplatePath );
if ( $file -> exists ()) {
$this -> processingTemplate = str_replace ( '.php' , '' , $processingTemplatePath );
}
$file -> close ();
}
2021-06-14 16:46:53 +02:00
protected function validateConnectorName ( $requestData )
2021-06-12 12:13:15 +02:00
{
2021-06-14 16:46:53 +02:00
if ( empty ( $requestData [ 'data' ][ 'connectorName' ])) {
throw new NotFoundException ( 'Error while validating request data. Connector name is missing.' );
}
$connector = $this -> getConnectorFromClassname ( $requestData [ 'data' ][ 'connectorName' ]);
if ( is_null ( $connector )) {
throw new NotFoundException ( __ ( 'Error while validating request data. Unkown connector `{0}`' , $requestData [ 'data' ][ 'connectorName' ]));
2021-06-12 12:13:15 +02:00
}
}
protected function getIssuerBrood ( $request )
{
$brood = $this -> Broods -> find ()
-> where ([ 'url' => $request [ 'origin' ]])
-> first ();
return $brood ;
}
2021-06-17 14:13:10 +02:00
protected function getConnection ( $requestData )
{
$local_tool_id = $requestData [ 'remote_tool_id' ]; // local_tool_id is actually the remote_tool_id for the sender
$connection = $this -> LocalTools -> find () -> where ([ 'id' => $local_tool_id ]) -> first ();
return $connection ;
}
2021-06-14 16:46:53 +02:00
protected function filterAlignmentsForBrood ( $individual , $brood )
{
foreach ( $individual -> alignments as $i => $alignment ) {
if ( $alignment -> organisation_id != $brood -> organisation_id ) {
unset ( $individual -> alignments [ $i ]);
}
}
return $individual ;
}
2021-06-12 14:04:17 +02:00
protected function getConnector ( $request )
{
try {
2021-06-14 16:46:53 +02:00
$connectorClasses = $this -> LocalTools -> getConnectors ( $request -> local_tool_connector_name );
2021-06-12 14:04:17 +02:00
if ( ! empty ( $connectorClasses )) {
2021-06-14 13:30:26 +02:00
$connector = array_values ( $connectorClasses )[ 0 ];
2021-06-12 14:04:17 +02:00
}
2021-06-14 16:46:53 +02:00
} catch ( NotFoundException $e ) {
2021-06-12 14:04:17 +02:00
$connector = null ;
}
return $connector ;
}
2021-06-14 13:30:26 +02:00
protected function getConnectorMeta ( $request )
{
try {
2021-06-14 16:46:53 +02:00
$className = $request -> local_tool_connector_name ;
$connector = $this -> getConnectorFromClassname ( $className );
$connectorMeta = $this -> LocalTools -> extractMeta ([ $className => $connector ])[ 0 ];
} catch ( NotFoundException $e ) {
$connectorMeta = [];
}
return $connectorMeta ;
}
protected function getConnectorFromClassname ( $className )
{
try {
$connectorClasses = $this -> LocalTools -> getConnectors ( $className );
2021-06-14 13:30:26 +02:00
if ( ! empty ( $connectorClasses )) {
2021-06-14 16:46:53 +02:00
$connector = array_values ( $connectorClasses )[ 0 ];
2021-06-14 13:30:26 +02:00
}
2021-06-14 16:46:53 +02:00
} catch ( NotFoundException $e ) {
$connector = null ;
}
return $connector ;
}
protected function getConnectorMetaFromClassname ( $className )
{
try {
$connector = $this -> getConnectorFromClassname ( $className );
$connectorMeta = $this -> LocalTools -> extractMeta ([ $className => $connector ])[ 0 ];
} catch ( NotFoundException $e ) {
$connectorMeta = [];
2021-06-14 13:30:26 +02:00
}
2021-06-14 16:46:53 +02:00
return $connectorMeta ;
}
protected function attachRequestAssociatedData ( $request )
{
$request -> brood = $this -> getIssuerBrood ( $request );
$request -> connector = $this -> getConnectorMeta ( $request );
$request -> individual = $request -> user -> individual ;
$request -> individual = $this -> filterAlignmentsForBrood ( $request -> individual , $request -> brood );
return $request ;
2021-06-14 13:30:26 +02:00
}
2021-06-17 14:13:10 +02:00
protected function genBroodParam ( $remoteCerebrate , $connection , $connector , $requestData )
{
$local_tool_id = $requestData [ 'remote_tool_id' ]; // local_tool_id is actually the remote_tool_id for the sender
$remote_tool_id = $requestData [ 'local_tool_id' ]; // remote_tool_id is actually the local_tool_id for the sender
$remote_org = $this -> Broods -> Organisations -> find () -> where ([ 'id' => $remoteCerebrate -> organisation_id ]) -> first ();
return [
'remote_tool' => [
'id' => $remote_tool_id ,
'connector' => $connector -> connectorName ,
2021-06-21 14:30:32 +02:00
'name' => $requestData [ 'tool_name' ],
2021-06-17 14:13:10 +02:00
],
'remote_org' => $remote_org ,
'remote_tool_data' => $requestData ,
'remote_cerebrate' => $remoteCerebrate ,
'connection' => $connection ,
2021-06-21 14:30:32 +02:00
'connector' => [ $connector -> connectorName => $connector ],
2021-06-17 14:13:10 +02:00
];
}
2021-06-12 12:13:15 +02:00
protected function addBaseValidatorRules ( $validator )
{
return $validator
2021-06-14 16:46:53 +02:00
-> requirePresence ( 'connectorName' )
-> notEmpty ( 'connectorName' , 'The connector name must be provided' )
-> requirePresence ( 'cerebrateURL' )
2021-06-17 14:13:10 +02:00
-> notEmpty ( 'cerebrateURL' , 'A url must be provided' )
-> requirePresence ( 'local_tool_id' )
-> numeric ( 'local_tool_id' , 'A local_tool_id must be provided' )
-> requirePresence ( 'remote_tool_id' )
-> numeric ( 'remote_tool_id' , 'A remote_tool_id must be provided' );
2021-06-12 12:13:15 +02:00
// ->add('url', 'validFormat', [
// 'rule' => 'url',
// 'message' => 'URL must be valid'
// ]);
}
}
2021-06-21 14:30:32 +02:00
class IncomingConnectionRequestProcessor extends LocalToolInboxProcessor implements GenericInboxProcessorActionI {
2021-06-12 12:13:15 +02:00
public $action = 'IncomingConnectionRequest' ;
protected $description ;
public function __construct () {
parent :: __construct ();
$this -> description = __ ( 'Handle Phase I of inter-connection when another cerebrate instance performs the request.' );
}
protected function addValidatorRules ( $validator )
{
return $this -> addBaseValidatorRules ( $validator );
}
public function create ( $requestData ) {
2021-06-14 16:46:53 +02:00
$this -> validateConnectorName ( $requestData );
2021-06-12 12:13:15 +02:00
$this -> validateRequestData ( $requestData );
2021-06-14 16:46:53 +02:00
$connectorMeta = $this -> getConnectorMetaFromClassname ( $requestData [ 'data' ][ 'connectorName' ]);
$requestData [ 'title' ] = __ ( 'Request for {0} Inter-connection' , $connectorMeta [ 'name' ]);
2021-06-12 12:13:15 +02:00
return parent :: create ( $requestData );
}
public function getViewVariables ( $request )
{
2021-06-14 16:46:53 +02:00
$request = $this -> attachRequestAssociatedData ( $request );
2021-06-12 12:13:15 +02:00
return [
'request' => $request ,
'progressStep' => 0 ,
];
}
2021-06-14 13:25:49 +02:00
public function process ( $id , $requestData , $inboxRequest )
2021-06-12 12:13:15 +02:00
{
2021-06-14 13:30:26 +02:00
/**
* /! \ Should how should sent message be ? be fire and forget ? Only for delined ?
*/
2021-06-12 12:13:15 +02:00
$interConnectionResult = [];
2021-06-14 13:30:26 +02:00
$remoteCerebrate = $this -> getIssuerBrood ( $inboxRequest );
$connector = $this -> getConnector ( $inboxRequest );
if ( ! empty ( $requestData [ 'is_discard' ])) { // -> declined
$connectorResult = $this -> declineConnection ( $connector , $remoteCerebrate , $inboxRequest [ 'data' ]); // Fire-and-forget?
2021-06-21 14:30:32 +02:00
$connectionSuccessfull = ! empty ( $connectorResult [ 'success' ]);
2021-06-14 13:30:26 +02:00
$resultTitle = __ ( 'Could not sent declined message to `{0}`\'s for {1}' , $inboxRequest [ 'origin' ], $inboxRequest [ 'local_tool_name' ]);
$errors = [];
if ( $connectionSuccessfull ) {
$resultTitle = __ ( 'Declined message successfully sent to `{0}`\'s for {1}' , $inboxRequest [ 'origin' ], $inboxRequest [ 'local_tool_name' ]);
$this -> discard ( $id , $inboxRequest );
}
} else {
$errors = [];
2021-06-17 14:13:10 +02:00
$connectorResult = [];
2021-06-21 14:30:32 +02:00
$thrownErrorMessage = '' ;
2021-06-17 14:13:10 +02:00
try {
$connectorResult = $this -> acceptConnection ( $connector , $remoteCerebrate , $inboxRequest [ 'data' ]);
2021-06-21 14:30:32 +02:00
$connectionSuccessfull = ! empty ( $connectorResult [ 'success' ]);
2021-06-17 14:13:10 +02:00
} catch ( \Throwable $th ) {
$connectionSuccessfull = false ;
2021-06-21 14:30:32 +02:00
$thrownErrorMessage = $th -> getMessage ();
2021-06-17 14:13:10 +02:00
}
2021-06-21 14:30:32 +02:00
$resultTitle = $connectorResult [ 'message' ] ? ? __ ( 'Could not inter-connect `{0}`\'s {1}' , $inboxRequest [ 'origin' ], $inboxRequest [ 'local_tool_name' ]);
$errors = $connectorResult [ 'errors' ] ? ? $thrownErrorMessage ;
2021-06-14 13:30:26 +02:00
if ( $connectionSuccessfull ) {
$resultTitle = __ ( 'Interconnection for `{0}`\'s {1} created' , $inboxRequest [ 'origin' ], $inboxRequest [ 'local_tool_name' ]);
2021-06-21 14:30:32 +02:00
}
if ( $connectionSuccessfull || ! empty ( $connectorResult [ 'placed_in_outbox' ])) {
2021-06-14 13:30:26 +02:00
$this -> discard ( $id , $inboxRequest );
}
2021-06-12 12:13:15 +02:00
}
return $this -> genActionResult (
2021-06-17 14:13:10 +02:00
$connectorResult ,
2021-06-12 12:13:15 +02:00
$connectionSuccessfull ,
2021-06-14 13:30:26 +02:00
$resultTitle ,
$errors
2021-06-12 12:13:15 +02:00
);
}
public function discard ( $id , $requestData )
{
return parent :: discard ( $id , $requestData );
}
2021-06-14 13:30:26 +02:00
protected function acceptConnection ( $connector , $remoteCerebrate , $requestData )
{
2021-06-17 14:13:10 +02:00
$connection = $this -> getConnection ( $requestData );
$params = $this -> genBroodParam ( $remoteCerebrate , $connection , $connector , $requestData );
2021-06-21 14:30:32 +02:00
$connectorResult = $connector -> acceptConnectionWrapper ( $params );
2021-06-17 14:13:10 +02:00
$response = $this -> sendAcceptedRequestToRemote ( $params , $connectorResult );
2021-06-14 13:30:26 +02:00
return $response ;
}
protected function declineConnection ( $connector , $remoteCerebrate , $requestData )
{
2021-06-17 14:13:10 +02:00
$connection = $this -> getConnection ( $requestData );
$params = $this -> genBroodParam ( $remoteCerebrate , $connection , $connector , $requestData );
2021-06-21 14:30:32 +02:00
$connectorResult = $connector -> declineConnectionWrapper ( $params );
2021-06-17 14:13:10 +02:00
$response = $this -> sendDeclinedRequestToRemote ( $params , $connectorResult );
2021-06-14 13:30:26 +02:00
return $response ;
}
2021-06-17 14:13:10 +02:00
protected function sendAcceptedRequestToRemote ( $params , $connectorResult )
2021-06-14 13:30:26 +02:00
{
2021-06-17 14:13:10 +02:00
$response = $this -> Broods -> sendLocalToolAcceptedRequest ( $params , $connectorResult );
2021-06-21 14:30:32 +02:00
return $response ;
2021-06-14 13:30:26 +02:00
}
protected function sendDeclinedRequestToRemote ( $remoteCerebrate , $connectorResult )
{
2021-06-17 14:13:10 +02:00
$response = $this -> Broods -> sendLocalToolDeclinedRequest ( $params , $connectorResult );
2021-06-21 14:30:32 +02:00
return $response ;
2021-06-14 13:30:26 +02:00
}
2021-06-12 12:13:15 +02:00
}
2021-06-21 14:30:32 +02:00
class AcceptedRequestProcessor extends LocalToolInboxProcessor implements GenericInboxProcessorActionI {
2021-06-12 12:13:15 +02:00
public $action = 'AcceptedRequest' ;
protected $description ;
public function __construct () {
parent :: __construct ();
$this -> description = __ ( 'Handle Phase II of inter-connection when initial request has been accepted by the remote cerebrate.' );
}
protected function addValidatorRules ( $validator )
{
return $this -> addBaseValidatorRules ( $validator );
}
public function create ( $requestData ) {
2021-06-14 16:46:53 +02:00
$this -> validateConnectorName ( $requestData );
2021-06-12 12:13:15 +02:00
$this -> validateRequestData ( $requestData );
2021-06-14 16:46:53 +02:00
$connectorMeta = $this -> getConnectorMetaFromClassname ( $requestData [ 'data' ][ 'connectorName' ]);
$requestData [ 'title' ] = __ ( 'Inter-connection for {0} has been accepted' , $connectorMeta [ 'name' ]);
2021-06-12 12:13:15 +02:00
return parent :: create ( $requestData );
}
public function getViewVariables ( $request )
{
2021-06-14 16:46:53 +02:00
$request = $this -> attachRequestAssociatedData ( $request );
2021-06-12 12:13:15 +02:00
return [
'request' => $request ,
'progressStep' => 1 ,
];
}
2021-06-14 13:25:49 +02:00
public function process ( $id , $requestData , $inboxRequest )
2021-06-12 12:13:15 +02:00
{
2021-06-17 14:13:10 +02:00
$connector = $this -> getConnector ( $inboxRequest );
$remoteCerebrate = $this -> getIssuerBrood ( $inboxRequest );
2021-06-14 13:30:26 +02:00
$errors = [];
2021-06-17 14:13:10 +02:00
$connectorResult = [];
2021-06-21 14:30:32 +02:00
$thrownErrorMessage = '' ;
2021-06-17 14:13:10 +02:00
try {
2021-06-21 14:30:32 +02:00
$connectorResult = $this -> finaliseConnection ( $connector , $remoteCerebrate , $inboxRequest [ 'data' ]);
$connectionSuccessfull = ! empty ( $connectorResult [ 'success' ]);
2021-06-17 14:13:10 +02:00
} catch ( \Throwable $th ) {
$connectionSuccessfull = false ;
$errors = $th -> getMessage ();
}
$resultTitle = __ ( 'Could not finalize inter-connection for `{0}`\'s {1}' , $inboxRequest [ 'origin' ], $inboxRequest [ 'local_tool_name' ]);
2021-06-21 14:30:32 +02:00
$errors = $connectorResult [ 'errors' ] ? ? $thrownErrorMessage ;
2021-06-12 12:13:15 +02:00
if ( $connectionSuccessfull ) {
2021-06-17 14:13:10 +02:00
$resultTitle = __ ( 'Interconnection for `{0}`\'s {1} finalized' , $inboxRequest [ 'origin' ], $inboxRequest [ 'local_tool_name' ]);
2021-06-12 12:13:15 +02:00
$this -> discard ( $id , $requestData );
}
return $this -> genActionResult (
2021-06-21 14:30:32 +02:00
$connectorResult ,
2021-06-12 12:13:15 +02:00
$connectionSuccessfull ,
2021-06-14 13:30:26 +02:00
$resultTitle ,
$errors
2021-06-12 12:13:15 +02:00
);
}
public function discard ( $id , $requestData )
{
return parent :: discard ( $id , $requestData );
}
2021-06-14 13:30:26 +02:00
2021-06-21 14:30:32 +02:00
protected function finaliseConnection ( $connector , $remoteCerebrate , $requestData )
2021-06-14 13:30:26 +02:00
{
2021-06-17 14:13:10 +02:00
$connection = $this -> getConnection ( $requestData );
$params = $this -> genBroodParam ( $remoteCerebrate , $connection , $connector , $requestData );
2021-06-21 14:30:32 +02:00
$connectorResult = $connector -> finaliseConnectionWrapper ( $params );
return [
'success' => true
];
2021-06-14 13:30:26 +02:00
}
2021-06-12 12:13:15 +02:00
}
2021-06-21 14:30:32 +02:00
class DeclinedRequestProcessor extends LocalToolInboxProcessor implements GenericInboxProcessorActionI {
2021-06-12 12:13:15 +02:00
public $action = 'DeclinedRequest' ;
protected $description ;
public function __construct () {
parent :: __construct ();
$this -> description = __ ( 'Handle Phase II of MISP inter-connection when initial request has been declined by the remote cerebrate.' );
}
protected function addValidatorRules ( $validator )
{
return $this -> addBaseValidatorRules ( $validator );
}
public function create ( $requestData ) {
2021-06-14 16:46:53 +02:00
$this -> validateConnectorName ( $requestData );
2021-06-12 12:13:15 +02:00
$this -> validateRequestData ( $requestData );
2021-06-14 16:46:53 +02:00
$connectorMeta = $this -> getConnectorMetaFromClassname ( $requestData [ 'data' ][ 'connectorName' ]);
$requestData [ 'title' ] = __ ( 'Declined inter-connection for {0}' , $connectorMeta [ 'name' ]);
2021-06-12 12:13:15 +02:00
return parent :: create ( $requestData );
}
public function getViewVariables ( $request )
{
2021-06-14 16:46:53 +02:00
$request = $this -> attachRequestAssociatedData ( $request );
2021-06-12 12:13:15 +02:00
return [
'request' => $request ,
'progressStep' => 1 ,
'progressVariant' => 'danger' ,
'steps' => [
1 => [ 'icon' => 'times' , 'text' => __ ( 'Request Declined' ), 'confirmButton' => __ ( 'Clean-up' )],
2 => [ 'icon' => 'trash' , 'text' => __ ( 'Clean-up' )],
]
];
}
2021-06-14 13:25:49 +02:00
public function process ( $id , $requestData , $inboxRequest )
2021-06-12 12:13:15 +02:00
{
$connectionSuccessfull = false ;
$interConnectionResult = [];
if ( $connectionSuccessfull ) {
$this -> discard ( $id , $requestData );
}
return $this -> genActionResult (
$interConnectionResult ,
$connectionSuccessfull ,
2021-06-12 13:32:25 +02:00
$connectionSuccessfull ? __ ( 'Interconnection for `{0}`\'s {1} finalized' , $requestData [ 'origin' ], $requestData [ 'local_tool_name' ]) : __ ( 'Could not inter-connect `{0}`\'s {1}' , $requestData [ 'origin' ], $requestData [ 'local_tool_name' ]),
2021-06-12 12:13:15 +02:00
[]
);
}
public function discard ( $id , $requestData )
{
return parent :: discard ( $id , $requestData );
}
}