-
François Agneray authoredFrançois Agneray authored
StartTaskCreateArchiveAction.php 4.69 KiB
<?php
/*
* This file is part of Anis Server.
*
* (c) Laboratoire d'Astrophysique de Marseille / CNRS
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace App\Action;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;
use Slim\Exception\HttpBadRequestException;
use Slim\Exception\HttpNotFoundException;
use Doctrine\ORM\EntityManagerInterface;
use PhpAmqpLib\Connection\AbstractConnection;
use PhpAmqpLib\Message\AMQPMessage;
/**
* @author François Agneray <francois.agneray@lam.fr>
* @package App\Action
*/
final class StartTaskCreateArchiveAction extends AbstractAction
{
/**
* Contains RabbitMQ connection socket
*
* @var AbstractConnection
*/
private $rmq;
/**
* Contains settings to handle Json Web Token (app/settings.php)
*
* @var array
*/
private $settings;
/**
* Create the classe before call __invoke to execute the action
*
* @param EntityManagerInterface $em Doctrine Entity Manager Interface
* @param AbstractConnection $rmq RabbitMQ connection socket
* @param array $settings Settings about token
*/
public function __construct(
EntityManagerInterface $em,
AbstractConnection $rmq,
array $settings
) {
parent::__construct($em);
$this->rmq = $rmq;
$this->settings = $settings;
}
/**
* `GET` Starts an asynchronous task, through rabbitmq, to build an archive
*
* @param ServerRequestInterface $request PSR-7 This object represents the HTTP request
* @param ResponseInterface $response PSR-7 This object represents the HTTP response
* @param string[] $args This table contains information transmitted in the URL (see routes.php)
*
* @return ResponseInterface
*/
public function __invoke(
ServerRequestInterface $request,
ResponseInterface $response,
array $args
): ResponseInterface {
if ($request->getMethod() === OPTIONS) {
return $response->withHeader('Access-Control-Allow-Methods', 'GET, OPTIONS');
}
// Search the correct dataset with primary key
$datasetName = $args['dname'];
$dataset = $this->em->find('App\Entity\Dataset', $datasetName);
// If dataset is not found 404
if (is_null($dataset)) {
throw new HttpNotFoundException(
$request,
'Dataset with name ' . $datasetName . ' is not found'
);
}
$token = '';
// If instance is private and authorization enabled
$instance = $dataset->getDatasetFamily()->getInstance();
if (!$instance->getPublic() && boolval($this->settings['enabled'])) {
$this->verifyInstanceAuthorization(
$request,
$instance->getName(),
explode(',', $this->settings['admin_roles'])
);
$token = $request->getHeader('Authorization')[0];
}
// If dataset is private and authorization enabled
if (!$dataset->getPublic() && boolval($this->settings['enabled'])) {
$this->verifyDatasetAuthorization(
$request,
$dataset->getName(),
explode(',', $this->settings['admin_roles'])
);
$token = $request->getHeader('Authorization')[0];
}
$queryParams = $request->getQueryParams();
// The parameter "a" is mandatory
if (!array_key_exists('a', $queryParams)) {
throw new HttpBadRequestException(
$request,
'Param a is required for this request'
);
}
// Create the name of the future archive
$archiveName = 'archive_' . $dataset->getName() . '_' . (new \DateTime())->format('Y-m-d\TH:i:s') . '.zip';
$archiveId = uniqid();
// Publish message in the archive queue
$channel = $this->rmq->channel();
$channel->queue_declare('archive', false, false, false, false);
$msg = new AMQPMessage(json_encode(array(
'archive_id' => $archiveId,
'dataset_name' => $datasetName,
'query' => $request->getUri()->getQuery(),
'param_a' => $queryParams['a'],
'token' => $token
)));
$channel->basic_publish($msg, '', 'archive');
// Just returns the future archive name
$payload = json_encode(array('archive_name' => $archiveName, 'archive_id' => $archiveId));
$response->getBody()->write($payload);
return $response;
}
}