From 57ee606e35b8e2cd2b5327cd47593a4925ff0b90 Mon Sep 17 00:00:00 2001 From: Ambroise Maupate Date: Fri, 8 Mar 2024 15:40:40 +0100 Subject: [PATCH] fix(Documents): Do not try to render private Document URLs even for thumbnails --- .../Exceptions/PrivateDocumentException.php | 9 +++++ .../src/Renderer/AbstractImageRenderer.php | 7 +++- lib/Documents/src/Renderer/VideoRenderer.php | 2 +- .../AbstractDocumentUrlGenerator.php | 36 ++++--------------- .../src/Controller/AppController.php | 1 + lib/RoadizCoreBundle/src/Entity/Document.php | 5 ++- .../src/Logger/DoctrineHandler.php | 2 +- .../src/Routing/DocumentUrlGenerator.php | 12 +------ .../TwigExtension/DocumentUrlExtension.php | 4 +-- .../AjaxSearchNodesSourcesController.php | 5 +-- .../src/Controllers/LoginController.php | 35 ++++++++---------- .../DocumentThumbnailSerializeSubscriber.php | 1 + 12 files changed, 51 insertions(+), 68 deletions(-) create mode 100644 lib/Documents/src/Exceptions/PrivateDocumentException.php diff --git a/lib/Documents/src/Exceptions/PrivateDocumentException.php b/lib/Documents/src/Exceptions/PrivateDocumentException.php new file mode 100644 index 00000000..133a0870 --- /dev/null +++ b/lib/Documents/src/Exceptions/PrivateDocumentException.php @@ -0,0 +1,9 @@ +getRelativePath())) { + if ( + isset($set['format']) && + isset($set['rule']) && + !$document->isPrivate() && + !empty($document->getRelativePath()) + ) { $this->documentUrlGenerator->setOptions($this->urlOptionsResolver->resolve($set['format'])); $this->documentUrlGenerator->setDocument($document); $path = $this->documentUrlGenerator->getUrl($absolute); diff --git a/lib/Documents/src/Renderer/VideoRenderer.php b/lib/Documents/src/Renderer/VideoRenderer.php index 109e0565..15a84e4b 100644 --- a/lib/Documents/src/Renderer/VideoRenderer.php +++ b/lib/Documents/src/Renderer/VideoRenderer.php @@ -78,7 +78,7 @@ protected function getPosterUrl( $document->hasThumbnails() ) { $thumbnail = $document->getThumbnails()->first(); - if ($thumbnail instanceof DocumentInterface) { + if (false !== $thumbnail) { $this->documentUrlGenerator->setOptions($options); $this->documentUrlGenerator->setDocument($thumbnail); return $this->documentUrlGenerator->getUrl($absolute); diff --git a/lib/Documents/src/UrlGenerators/AbstractDocumentUrlGenerator.php b/lib/Documents/src/UrlGenerators/AbstractDocumentUrlGenerator.php index 5208d1ad..2c05f7f6 100644 --- a/lib/Documents/src/UrlGenerators/AbstractDocumentUrlGenerator.php +++ b/lib/Documents/src/UrlGenerators/AbstractDocumentUrlGenerator.php @@ -7,6 +7,7 @@ use League\Flysystem\FilesystemOperator; use Psr\Cache\CacheItemPoolInterface; use Psr\Cache\InvalidArgumentException; +use RZ\Roadiz\Documents\Exceptions\PrivateDocumentException; use RZ\Roadiz\Documents\Models\DocumentInterface; use RZ\Roadiz\Documents\OptionsResolver\ViewOptionsResolver; use Symfony\Component\HttpFoundation\UrlHelper; @@ -15,35 +16,18 @@ abstract class AbstractDocumentUrlGenerator implements DocumentUrlGeneratorInter { protected ?DocumentInterface $document; protected array $options; - protected CacheItemPoolInterface $optionsCacheAdapter; protected ViewOptionsResolver $viewOptionsResolver; protected OptionsCompiler $optionCompiler; - protected FilesystemOperator $documentsStorage; - private UrlHelper $urlHelper; - /** - * @param FilesystemOperator $documentsStorage - * @param UrlHelper $urlHelper - * @param CacheItemPoolInterface $optionsCacheAdapter - * @param DocumentInterface|null $document - * @param array $options - * @throws InvalidArgumentException - */ public function __construct( - FilesystemOperator $documentsStorage, - UrlHelper $urlHelper, - CacheItemPoolInterface $optionsCacheAdapter, - DocumentInterface $document = null, + protected FilesystemOperator $documentsStorage, + protected UrlHelper $urlHelper, + protected CacheItemPoolInterface $optionsCacheAdapter, array $options = [] ) { - $this->document = $document; $this->viewOptionsResolver = new ViewOptionsResolver(); $this->optionCompiler = new OptionsCompiler(); - $this->optionsCacheAdapter = $optionsCacheAdapter; - $this->setOptions($options); - $this->documentsStorage = $documentsStorage; - $this->urlHelper = $urlHelper; } /** @@ -85,23 +69,17 @@ public function setDocument(DocumentInterface $document): static return $this; } - /** - * @param bool $absolute - * - * @return string - */ public function getUrl(bool $absolute = false): string { if (null === $this->document) { throw new \InvalidArgumentException('Cannot get URL from a NULL document'); } - - $mountPath = $this->document->getMountPath(); - if ($this->document->isPrivate()) { - throw new \InvalidArgumentException('Cannot get URL from a private document'); + throw new PrivateDocumentException('Cannot get URL from a private document'); } + $mountPath = $this->document->getMountPath(); + if (null !== $mountPath && ($this->options['noProcess'] === true || !$this->document->isProcessable())) { $publicUrl = $this->documentsStorage->publicUrl($mountPath); if ($absolute && \str_starts_with($publicUrl, '/')) { diff --git a/lib/RoadizCompatBundle/src/Controller/AppController.php b/lib/RoadizCompatBundle/src/Controller/AppController.php index ecae78dc..a34efc81 100644 --- a/lib/RoadizCompatBundle/src/Controller/AppController.php +++ b/lib/RoadizCompatBundle/src/Controller/AppController.php @@ -552,6 +552,7 @@ public function maintenanceAction(Request $request): Response * @param bool $allowClientCache Allows browser level cache * * @return Response + * @deprecated Use stateless routes and cache-control headers in your controllers */ public function makeResponseCachable( Request $request, diff --git a/lib/RoadizCoreBundle/src/Entity/Document.php b/lib/RoadizCoreBundle/src/Entity/Document.php index 92eeb139..073815c5 100644 --- a/lib/RoadizCoreBundle/src/Entity/Document.php +++ b/lib/RoadizCoreBundle/src/Entity/Document.php @@ -681,7 +681,10 @@ public function hasThumbnails(): bool */ public function getThumbnails(): Collection { - return $this->thumbnails; + // Filter private thumbnails + return $this->thumbnails->filter(function (DocumentInterface $thumbnail) { + return !$thumbnail->isPrivate(); + }); } public function setThumbnails(Collection $thumbnails): static diff --git a/lib/RoadizCoreBundle/src/Logger/DoctrineHandler.php b/lib/RoadizCoreBundle/src/Logger/DoctrineHandler.php index 058e1940..dbb55899 100644 --- a/lib/RoadizCoreBundle/src/Logger/DoctrineHandler.php +++ b/lib/RoadizCoreBundle/src/Logger/DoctrineHandler.php @@ -46,7 +46,7 @@ public function __construct( protected function getThumbnailSourcePath(?DocumentInterface $thumbnail): ?string { - if (null === $thumbnail) { + if (null === $thumbnail || $thumbnail->isPrivate()) { return null; } return $this->documentUrlGenerator diff --git a/lib/RoadizCoreBundle/src/Routing/DocumentUrlGenerator.php b/lib/RoadizCoreBundle/src/Routing/DocumentUrlGenerator.php index 78c17e6b..e329f2f8 100644 --- a/lib/RoadizCoreBundle/src/Routing/DocumentUrlGenerator.php +++ b/lib/RoadizCoreBundle/src/Routing/DocumentUrlGenerator.php @@ -13,23 +13,13 @@ final class DocumentUrlGenerator extends AbstractDocumentUrlGenerator { - private UrlGeneratorInterface $urlGenerator; - - /** - * @param FilesystemOperator $documentsStorage - * @param UrlHelper $urlHelper - * @param UrlGeneratorInterface $urlGenerator - * @param CacheItemPoolInterface $optionsCacheAdapter - * @throws InvalidArgumentException - */ public function __construct( FilesystemOperator $documentsStorage, UrlHelper $urlHelper, - UrlGeneratorInterface $urlGenerator, + private readonly UrlGeneratorInterface $urlGenerator, CacheItemPoolInterface $optionsCacheAdapter ) { parent::__construct($documentsStorage, $urlHelper, $optionsCacheAdapter); - $this->urlGenerator = $urlGenerator; } /** diff --git a/lib/RoadizCoreBundle/src/TwigExtension/DocumentUrlExtension.php b/lib/RoadizCoreBundle/src/TwigExtension/DocumentUrlExtension.php index 869d4d6b..945ffda6 100644 --- a/lib/RoadizCoreBundle/src/TwigExtension/DocumentUrlExtension.php +++ b/lib/RoadizCoreBundle/src/TwigExtension/DocumentUrlExtension.php @@ -5,7 +5,7 @@ namespace RZ\Roadiz\CoreBundle\TwigExtension; use RZ\Roadiz\Core\AbstractEntities\PersistableInterface; -use RZ\Roadiz\CoreBundle\Entity\Document; +use RZ\Roadiz\Documents\Models\DocumentInterface; use RZ\Roadiz\Documents\UrlGenerators\DocumentUrlGeneratorInterface; use Symfony\Component\OptionsResolver\Exception\InvalidArgumentException; use Twig\Error\RuntimeError; @@ -64,7 +64,7 @@ public function getUrl(PersistableInterface $mixed = null, array $criteria = []) } } - if ($mixed instanceof Document) { + if ($mixed instanceof DocumentInterface) { try { $absolute = false; if (isset($criteria['absolute'])) { diff --git a/lib/Rozier/src/AjaxControllers/AjaxSearchNodesSourcesController.php b/lib/Rozier/src/AjaxControllers/AjaxSearchNodesSourcesController.php index d90719c4..8f2e7115 100644 --- a/lib/Rozier/src/AjaxControllers/AjaxSearchNodesSourcesController.php +++ b/lib/Rozier/src/AjaxControllers/AjaxSearchNodesSourcesController.php @@ -92,9 +92,10 @@ protected function getNodeSourceData(NodesSources $source): array /** @var Translation $translation */ $translation = $source->getTranslation(); $displayableNSDoc = $source->getDocumentsByFields()->filter(function (NodesSourcesDocuments $nsDoc) { - return $nsDoc->getDocument()->isImage() || $nsDoc->getDocument()->isSvg(); + $doc = $nsDoc->getDocument(); + return !$doc->isPrivate() && ($doc->isImage() || $doc->isSvg()); })->first(); - if ($displayableNSDoc instanceof NodesSourcesDocuments) { + if (false !== $displayableNSDoc) { $thumbnail = $displayableNSDoc->getDocument(); $this->documentUrlGenerator->setDocument($thumbnail); $this->documentUrlGenerator->setOptions([ diff --git a/lib/Rozier/src/Controllers/LoginController.php b/lib/Rozier/src/Controllers/LoginController.php index 0e66ac8a..5714ba77 100644 --- a/lib/Rozier/src/Controllers/LoginController.php +++ b/lib/Rozier/src/Controllers/LoginController.php @@ -4,6 +4,7 @@ namespace Themes\Rozier\Controllers; +use RZ\Roadiz\CoreBundle\Bag\Settings; use RZ\Roadiz\CoreBundle\Entity\Document; use RZ\Roadiz\Documents\MediaFinders\RandomImageFinder; use RZ\Roadiz\Documents\UrlGenerators\DocumentUrlGeneratorInterface; @@ -14,31 +15,25 @@ class LoginController extends RozierApp { - private DocumentUrlGeneratorInterface $documentUrlGenerator; - private RandomImageFinder $randomImageFinder; - - /** - * @param DocumentUrlGeneratorInterface $documentUrlGenerator - * @param RandomImageFinder $randomImageFinder - */ public function __construct( - DocumentUrlGeneratorInterface $documentUrlGenerator, - RandomImageFinder $randomImageFinder + private readonly DocumentUrlGeneratorInterface $documentUrlGenerator, + private readonly RandomImageFinder $randomImageFinder, + private readonly Settings $settingsBag ) { - $this->documentUrlGenerator = $documentUrlGenerator; - $this->randomImageFinder = $randomImageFinder; } - /** - * @param Request $request - * - * @return Response - */ public function imageAction(Request $request): Response { $response = new JsonResponse(); - if (null !== $document = $this->getSettingsBag()->getDocument('login_image')) { - if ($document instanceof Document && $document->isProcessable()) { + $response->setPublic(); + $response->setMaxAge(600); + + if (null !== $document = $this->settingsBag->getDocument('login_image')) { + if ( + $document instanceof Document && + !$document->isPrivate() && + $document->isProcessable() + ) { $this->documentUrlGenerator->setDocument($document); $this->documentUrlGenerator->setOptions([ 'width' => 1920, @@ -49,7 +44,7 @@ public function imageAction(Request $request): Response $response->setData([ 'url' => $this->documentUrlGenerator->getUrl() ]); - return $this->makeResponseCachable($request, $response, 60, true); + return $response; } } @@ -62,6 +57,6 @@ public function imageAction(Request $request): Response $response->setData([ 'url' => '/themes/Rozier/static/assets/img/default_login.jpg' ]); - return $this->makeResponseCachable($request, $response, 60, true); + return $response; } } diff --git a/lib/Rozier/src/Serialization/DocumentThumbnailSerializeSubscriber.php b/lib/Rozier/src/Serialization/DocumentThumbnailSerializeSubscriber.php index 1e6bcc81..0b4e3456 100644 --- a/lib/Rozier/src/Serialization/DocumentThumbnailSerializeSubscriber.php +++ b/lib/Rozier/src/Serialization/DocumentThumbnailSerializeSubscriber.php @@ -37,6 +37,7 @@ public function onPostSerialize(ObjectEvent $event): void if ( $visitor instanceof SerializationVisitorInterface && $document instanceof Document && + !$document->isPrivate() && $context->hasAttribute('groups') && \is_array($context->getAttribute('groups')) && in_array('explorer_thumbnail', $context->getAttribute('groups'))