diff --git a/_config/config.yml b/_config/config.yml index b07b70be3..6dc6f3eb3 100644 --- a/_config/config.yml +++ b/_config/config.yml @@ -18,6 +18,7 @@ SilverStripe\Core\Injector\Injector: class: SilverStripe\AssetAdmin\Model\ThumbnailGenerator properties: Generates: true + thumbnailMethod: 'Fill' SilverStripe\AssetAdmin\Controller\AssetAdmin: properties: ThumbnailGenerator: '%$SilverStripe\AssetAdmin\Model\ThumbnailGenerator.assetadmin' @@ -53,3 +54,4 @@ SilverStripe\Core\Injector\Injector: class: SilverStripe\AssetAdmin\Model\ThumbnailGenerator properties: Generates: false + thumbnailMethod: 'Fill' diff --git a/code/Forms/UploadField.php b/code/Forms/UploadField.php index 7f5e95f92..898cc6b12 100644 --- a/code/Forms/UploadField.php +++ b/code/Forms/UploadField.php @@ -42,13 +42,13 @@ class UploadField extends FormField implements FileHandleField * @config * @var int */ - private static $thumbnail_width = 60; + private static $thumbnail_width = 120; /** * @config * @var int */ - private static $thumbnail_height = 60; + private static $thumbnail_height = 120; /** * Set if uploading new files is enabled. diff --git a/code/GraphQL/Resolvers/FileTypeResolver.php b/code/GraphQL/Resolvers/FileTypeResolver.php index aecd7049a..f3ae946f2 100644 --- a/code/GraphQL/Resolvers/FileTypeResolver.php +++ b/code/GraphQL/Resolvers/FileTypeResolver.php @@ -90,12 +90,27 @@ public static function resolveFileSmallThumbnail($object) */ public static function resolveFileThumbnail($object) { + // If we're allowed to generate thumbnails for this file, tell the generator it's allowed to do it. + $generator = static::singleton()->getThumbnailGenerator(); + $idsAllowed = FolderTypeResolver::getIdsAllowedToGenerateThumbnails(); + $shouldGenerateThumbnail = !empty($idsAllowed) && in_array($object->ID, $idsAllowed); + if ($shouldGenerateThumbnail) { + $origGenerates = $generator->getGenerates(); + $generator->setGenerates(true); + } + // Make large thumbnail $width = AssetAdmin::config()->uninherited('thumbnail_width'); $height = AssetAdmin::config()->uninherited('thumbnail_height'); - return static::singleton() - ->getThumbnailGenerator() - ->generateThumbnailLink($object, $width, $height); + + try { + return $generator->generateThumbnailLink($object, $width, $height); + } finally { + // Make sure to set the generates value back to what it was, regardless of what happens + if ($shouldGenerateThumbnail) { + $generator->setGenerates($origGenerates); + } + } } /** diff --git a/code/GraphQL/Resolvers/FolderTypeResolver.php b/code/GraphQL/Resolvers/FolderTypeResolver.php index a67183fa4..d7d1663d4 100644 --- a/code/GraphQL/Resolvers/FolderTypeResolver.php +++ b/code/GraphQL/Resolvers/FolderTypeResolver.php @@ -18,10 +18,20 @@ use InvalidArgumentException; use Exception; use Closure; +use SilverStripe\AssetAdmin\Controller\AssetAdmin; use SilverStripe\ORM\DataQuery; class FolderTypeResolver { + /** + * Any IDs of files which we're allowed to generate thumbnails for. + * The intention is to (as much as is feasible) only allow generating thumbnails + * during asset admin graphQL requests and not for requests that could be performed + * by an attacker. + * @internal + */ + private static array $idsAllowedToGenerateThumbnails = []; + /** * @param Folder $object * @param array $args @@ -73,6 +83,17 @@ public static function resolveFolderChildren( $canViewList = $list->filter('ID', $canViewIDs ?: 0) ->limit(null); + // If we haven't already marked IDs as being okay to generate thumbnails, + // and we have a safe limit for the number of children, + // mark these children as being okay to generate thumbnails for. + if (empty(self::$idsAllowedToGenerateThumbnails) + && !empty($args['limit']) + && is_numeric($args['limit']) + && (int)$args['limit'] <= AssetAdmin::config()->get('page_length') + ) { + self::$idsAllowedToGenerateThumbnails = $canViewIDs; + } + return $canViewList; } @@ -181,4 +202,9 @@ public static function sortChildren(array $context): Closure return $list; }; } + + public static function getIdsAllowedToGenerateThumbnails(): array + { + return self::$idsAllowedToGenerateThumbnails; + } } diff --git a/code/Model/ThumbnailGenerator.php b/code/Model/ThumbnailGenerator.php index 66225b5b1..535030fd0 100644 --- a/code/Model/ThumbnailGenerator.php +++ b/code/Model/ThumbnailGenerator.php @@ -60,11 +60,16 @@ class ThumbnailGenerator ]; /** - * @var string - * @config + * @var string The default method to use for generating thumbnails if a specific method hasn't been + * set for a given generator instance. */ private static $method = 'FitMax'; + /** + * The method that this generator instance will use to generate thumbnails. + */ + private string $thumbnailMethod = ''; + /** * Generate thumbnail and return the "src" property for this thumbnail * @@ -108,7 +113,7 @@ public function generateThumbnail(AssetContainer $file, $width, $height) } // Make large thumbnail - $method = $this->config()->get('method'); + $method = $this->getThumbnailMethod(); return $file->$method($width, $height); } @@ -173,4 +178,25 @@ public function setGenerates($generates) $this->generates = $generates; return $this; } + + /** + * Get the method which will be used to generate thumbnails. + */ + public function getThumbnailMethod(): string + { + if ($this->thumbnailMethod) { + return $this->thumbnailMethod; + } + return static::config()->get('method'); + } + + /** + * Set the method which will be used to generate thumbnails. + * Pass an empty string to reset to the default method. + */ + public function setThumbnailMethod(string $method): static + { + $this->thumbnailMethod = $method; + return $this; + } }