<?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; } }