Skip to content

Commit 03bf80f

Browse files
authored
fix(file-upload): Catch leaked cacheable metadata when using token service to prevent fatal error. (#1134)
1 parent 68cde53 commit 03bf80f

3 files changed

Lines changed: 26 additions & 5 deletions

File tree

graphql.services.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ services:
153153
- '@token'
154154
- '@lock'
155155
- '@config.factory'
156+
- '@renderer'
156157

157158
plugin.manager.graphql.persisted_query:
158159
class: Drupal\graphql\Plugin\PersistedQueryPluginManager

src/GraphQL/Utility/FileUpload.php

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
use Drupal\Core\File\FileSystemInterface;
1313
use Drupal\Core\Lock\LockBackendInterface;
1414
use Drupal\Core\Logger\LoggerChannelInterface;
15+
use Drupal\Core\Render\RenderContext;
16+
use Drupal\Core\Render\RendererInterface;
1517
use Drupal\Core\Session\AccountProxyInterface;
1618
use Drupal\Core\StringTranslation\StringTranslationTrait;
1719
use Drupal\Core\Utility\Token;
@@ -85,6 +87,13 @@ class FileUpload {
8587
*/
8688
protected $systemFileConfig;
8789

90+
/**
91+
* The renderer service.
92+
*
93+
* @var \Drupal\Core\Render\RendererInterface
94+
*/
95+
protected $renderer;
96+
8897
/**
8998
* Constructor.
9099
*/
@@ -96,7 +105,8 @@ public function __construct(
96105
LoggerChannelInterface $logger,
97106
Token $token,
98107
LockBackendInterface $lock,
99-
ConfigFactoryInterface $config_factory
108+
ConfigFactoryInterface $config_factory,
109+
RendererInterface $renderer
100110
) {
101111
/** @var \Drupal\file\FileStorageInterface $file_storage */
102112
$file_storage = $entityTypeManager->getStorage('file');
@@ -108,6 +118,7 @@ public function __construct(
108118
$this->token = $token;
109119
$this->lock = $lock;
110120
$this->systemFileConfig = $config_factory->get('system.file');
121+
$this->renderer = $renderer;
111122
}
112123

113124
/**
@@ -374,9 +385,17 @@ protected function prepareFilename(string $filename, array &$validators): string
374385
protected function getUploadLocation(array $settings): string {
375386
$destination = trim($settings['file_directory'], '/');
376387

377-
// Replace tokens. As the tokens might contain HTML we convert it to plain
378-
// text.
379-
$destination = PlainTextOutput::renderFromHtml($this->token->replace($destination, []));
388+
// Replace tokens first. This might produce cacheable metadata if tokens
389+
// are used in the path. As this service is intended to be used in mutations
390+
// which are not cached at all, it's enough to just catch leaked metadata
391+
// and skip including them in current GraphQL field's context.
392+
$context = new RenderContext();
393+
$destination = $this->renderer->executeInRenderContext($context, function () use ($destination): string {
394+
return $this->token->replace($destination, []);
395+
});
396+
397+
// As the tokens might contain HTML we convert it to plain text.
398+
$destination = PlainTextOutput::renderFromHtml($destination);
380399
return $settings['uri_scheme'] . '://' . $destination;
381400
}
382401

tests/src/Kernel/Framework/UploadFileServiceTest.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,8 @@ public function testLockReleased() {
196196
\Drupal::service('logger.channel.graphql'),
197197
\Drupal::service('token'),
198198
$lock->reveal(),
199-
\Drupal::service('config.factory')
199+
\Drupal::service('config.factory'),
200+
\Drupal::service('renderer')
200201
);
201202

202203
// Create a file with 4 bytes.

0 commit comments

Comments
 (0)