From 092b6d6378175720debbcce14d026e8705b5d3cc Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Fri, 2 Sep 2022 14:21:43 +0100 Subject: [PATCH] Added test and handling for local_secure_restricted in exports --- app/Entities/Tools/ExportFormatter.php | 3 +-- app/Uploads/ImageService.php | 12 ++++++++++ tests/Uploads/ImageTest.php | 33 ++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/app/Entities/Tools/ExportFormatter.php b/app/Entities/Tools/ExportFormatter.php index 97902db82..9e4d63cf7 100644 --- a/app/Entities/Tools/ExportFormatter.php +++ b/app/Entities/Tools/ExportFormatter.php @@ -235,7 +235,7 @@ class ExportFormatter $linksOutput = []; preg_match_all("/\/i", $htmlContent, $linksOutput); - // Replace image src with base64 encoded image strings + // Update relative links to be absolute, with instance url if (isset($linksOutput[0]) && count($linksOutput[0]) > 0) { foreach ($linksOutput[0] as $index => $linkMatch) { $oldLinkString = $linkMatch; @@ -248,7 +248,6 @@ class ExportFormatter } } - // Replace any relative links with system domain return $htmlContent; } diff --git a/app/Uploads/ImageService.php b/app/Uploads/ImageService.php index a82fecdd7..ec2f6da54 100644 --- a/app/Uploads/ImageService.php +++ b/app/Uploads/ImageService.php @@ -501,6 +501,14 @@ class ImageService } $storagePath = $this->adjustPathForStorageDisk($storagePath); + + // Apply access control when local_secure_restricted images are active + if ($this->usingSecureRestrictedImages()) { + if (!$this->checkUserHasAccessToRelationOfImageAtPath($storagePath)) { + return null; + } + } + $storage = $this->getStorageDisk(); $imageData = null; if ($storage->exists($storagePath)) { @@ -548,6 +556,10 @@ class ImageService */ protected function checkUserHasAccessToRelationOfImageAtPath(string $path): bool { + if (strpos($path, '/uploads/images/') === 0) { + $path = substr($path, 15); + } + // Strip thumbnail element from path if existing $originalPathSplit = array_filter(explode('/', $path), function(string $part) { $resizedDir = (strpos($part, 'thumbs-') === 0 || strpos($part, 'scaled-') === 0); diff --git a/tests/Uploads/ImageTest.php b/tests/Uploads/ImageTest.php index 3beba2007..2a3023a9e 100644 --- a/tests/Uploads/ImageTest.php +++ b/tests/Uploads/ImageTest.php @@ -377,6 +377,39 @@ class ImageTest extends TestCase } } + public function test_secure_restricted_image_access_controlled_in_exports() + { + config()->set('filesystems.images', 'local_secure_restricted'); + $this->asEditor(); + $galleryFile = $this->getTestImage('my-secure-restricted-export-test.png'); + + /** @var Page $pageA */ + /** @var Page $pageB */ + $pageA = Page::query()->first(); + $pageB = Page::query()->where('id', '!=', $pageA->id)->first(); + $expectedPath = storage_path('uploads/images/gallery/' . date('Y-m') . '/my-secure-restricted-export-test.png'); + + $upload = $this->asEditor()->call('POST', '/images/gallery', ['uploaded_to' => $pageA->id], [], ['file' => $galleryFile], []); + $upload->assertOk(); + + $imageUrl = json_decode($upload->getContent(), true)['url']; + $pageB->html .= ""; + $pageB->save(); + + $encodedImageContent = base64_encode(file_get_contents($expectedPath)); + $export = $this->get($pageB->getUrl('/export/html')); + $this->assertStringContainsString($encodedImageContent, $export->getContent()); + + $this->setEntityRestrictions($pageA, [], []); + + $export = $this->get($pageB->getUrl('/export/html')); + $this->assertStringNotContainsString($encodedImageContent, $export->getContent()); + + if (file_exists($expectedPath)) { + unlink($expectedPath); + } + } + public function test_image_delete() { $page = Page::query()->first();