tapis_job-1.4.1-alpha1/src/Controller/JobInputFileController.php

src/Controller/JobInputFileController.php
<?php

namespace Drupal\tapis_job\Controller;

use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Config\ImmutableConfig;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\file\FileInterface;
use Drupal\jwt\Transcoder\JwtTranscoderInterface;
use Drupal\tapis_job\TapisProvider\TapisJobProviderInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

/**
 * Class JobInputFileController.
 *
 * This class is used to create a controller
 * that allows Tapis to download a job's input file.
 *
 * @package Drupal\tapis_job\Controller
 */
class JobInputFileController extends ControllerBase {

  /**
   * The Tapis Job provider.
   *
   * @var \Drupal\tapis_job\TapisProvider\TapisJobProviderInterface
   */

  protected TapisJobProviderInterface $tapisJobProvider;

  /**
   * The JWT transcoder service.
   *
   * @var \Drupal\jwt\Transcoder\JwtTranscoderInterface
   */
  protected JwtTranscoderInterface $jwtTranscoder;

  /**
   * The configuration factory.
   *
   * @var \Drupal\Core\Config\ConfigFactoryInterface|\Drupal\Core\Config\ImmutableConfig
   */
  protected ConfigFactoryInterface|ImmutableConfig $config;

  /**
   * The entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

  /**
   * JobOutputController constructor.
   *
   * @param \Drupal\tapis_job\TapisProvider\TapisJobProviderInterface $tapisJobProvider
   *   The Tapis Job provider.
   * @param \Drupal\jwt\Transcoder\JwtTranscoderInterface $jwt_transcoder
   *   The JWT transcoder service.
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   The configuration factory.
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
   *   The entity type manager.
   */
  public function __construct(TapisJobProviderInterface $tapisJobProvider,
                              JwtTranscoderInterface $jwt_transcoder,
                              ConfigFactoryInterface $config_factory,
                              EntityTypeManagerInterface $entityTypeManager) {
    $this->tapisJobProvider = $tapisJobProvider;
    $this->jwtTranscoder = $jwt_transcoder;
    $this->config = $config_factory->get('tapis_job.config');
    $this->entityTypeManager = $entityTypeManager;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('tapis_job.tapis_job_provider'),
      $container->get('jwt.transcoder'),
      $container->get('config.factory'),
      $container->get('entity_type.manager')
    );
  }

  /**
   * Download a job's input file.
   *
   * @param \Drupal\file\FileInterface $file
   *   The file interface.
   * @param string $filename
   *   The file name.
   * @param \Symfony\Component\HttpFoundation\Request $request
   *   The HTTP request.
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException|\Drupal\jwt\Transcoder\JwtDecodeException
   */
  public function getJobInputFile(FileInterface $file, string $filename, Request $request) {
    /*
     * Note how we define the $filename parameter as the trailing path parameter
     * for this controller (see routing.yml for this method)
     * but we don't use it anywhere.
     *
     * The reason we have the route structured like this is
     * because Tapis detects the filename to download to,
     * based on the suffix of this download url (instead of reading from
     * the Content-Disposition response header).
     * So, if we don't have this extra path parameter,
     * Tapis will download the file as <file id> instead
     * (since that's the second to last trailing part of this url,
     * after the filename parameter).
     */
    if (!$file) {
      return new Response('File not found.', 404);
    }

    if ($request->getMethod() !== "GET") {
      return new Response('', 405);
    }

    $jwt_token = $request->query->get('token');
    // $config = \Drupal::config('tapis_job.config');
    $jwt_secret_key_id = $this->config->get("webhook_jwt_secret_key_id");

    if ($jwt_secret_key_id) {
      // A JWT secret key has been configured,
      // so use it to verify the JWT token.
      if (!$jwt_token) {
        return new Response('', 401);
      }
      // $jwt_secret_key = \Drupal::entityTypeManager()->getStorage('key')->load($jwt_secret_key_id);
      /** @var \Drupal\key\KeyInterface $jwt_secret_key */
      $jwt_secret_key = $this->entityTypeManager->getStorage('key')->load($jwt_secret_key_id);
      if (!$jwt_secret_key) {
        return new Response('', 401);
      }

      // Verify the JWT token.
      // $jwt_transcoder = \Drupal::service('jwt.transcoder');.
      $this->jwtTranscoder->setKey($jwt_secret_key);
      // This will throw an exception if the token is invalid.
      $jwt = $this->jwtTranscoder->decode($jwt_token);

      // Verify that the subject of the JWT token matches the file id
      // note: here we match on file id and NOT job uuid,
      // because when generating in the input file
      // download urls for the job submission request,
      // we have not yet made the job, so we don't have
      // a job uuid to match against.
      if ((string) $jwt->getClaim('sub') !== (string) $file->id()) {
        return new Response('', 401);
      }
    }

    $uri = $file->getFileUri();
    $response = new BinaryFileResponse($uri);

    \Drupal::logger('tapis_job')->info('Downloaded input file: ' . $file->getFilename() . ' (file id: ' . $file->id() . '), mime type: ' . $file->getMimeType());

    // Optional: Set headers to force download.
    $response->headers->set('Content-Type', $file->getMimeType());
    $response->headers->set('Content-Disposition', 'attachment; filename="' . $file->getFilename() . '";');
    return $response;
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc