mirror of
				https://github.com/BookStackApp/BookStack.git
				synced 2025-11-03 02:13:16 +03:00 
			
		
		
		
	Ensured uploaded system images remain public
Also added tests to cover local_secure image storage. Fixes #725
This commit is contained in:
		@@ -225,7 +225,6 @@ class ImageRepo
 | 
				
			|||||||
        try {
 | 
					        try {
 | 
				
			||||||
            return $this->imageService->getThumbnail($image, $width, $height, $keepRatio);
 | 
					            return $this->imageService->getThumbnail($image, $width, $height, $keepRatio);
 | 
				
			||||||
        } catch (\Exception $exception) {
 | 
					        } catch (\Exception $exception) {
 | 
				
			||||||
            dd($exception);
 | 
					 | 
				
			||||||
            return null;
 | 
					            return null;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,10 +14,6 @@ class AttachmentService extends UploadService
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    protected function getStorage()
 | 
					    protected function getStorage()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if ($this->storageInstance !== null) {
 | 
					 | 
				
			||||||
            return $this->storageInstance;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $storageType = config('filesystems.default');
 | 
					        $storageType = config('filesystems.default');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Override default location if set to local public to ensure not visible.
 | 
					        // Override default location if set to local public to ensure not visible.
 | 
				
			||||||
@@ -25,9 +21,7 @@ class AttachmentService extends UploadService
 | 
				
			|||||||
            $storageType = 'local_secure';
 | 
					            $storageType = 'local_secure';
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->storageInstance = $this->fileSystem->disk($storageType);
 | 
					        return $this->fileSystem->disk($storageType);
 | 
				
			||||||
 | 
					 | 
				
			||||||
        return $this->storageInstance;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -31,6 +31,23 @@ class ImageService extends UploadService
 | 
				
			|||||||
        parent::__construct($fileSystem);
 | 
					        parent::__construct($fileSystem);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get the storage that will be used for storing images.
 | 
				
			||||||
 | 
					     * @param string $type
 | 
				
			||||||
 | 
					     * @return \Illuminate\Contracts\Filesystem\Filesystem
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    protected function getStorage($type = '')
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $storageType = config('filesystems.default');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Override default location if set to local public to ensure not visible.
 | 
				
			||||||
 | 
					        if ($type === 'system' && $storageType === 'local_secure') {
 | 
				
			||||||
 | 
					            $storageType = 'local';
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $this->fileSystem->disk($storageType);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Saves a new image from an upload.
 | 
					     * Saves a new image from an upload.
 | 
				
			||||||
     * @param UploadedFile $uploadedFile
 | 
					     * @param UploadedFile $uploadedFile
 | 
				
			||||||
@@ -119,7 +136,7 @@ class ImageService extends UploadService
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    private function saveNew($imageName, $imageData, $type, $uploadedTo = 0)
 | 
					    private function saveNew($imageName, $imageData, $type, $uploadedTo = 0)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $storage = $this->getStorage();
 | 
					        $storage = $this->getStorage($type);
 | 
				
			||||||
        $secureUploads = setting('app-secure-images');
 | 
					        $secureUploads = setting('app-secure-images');
 | 
				
			||||||
        $imageName = str_replace(' ', '-', $imageName);
 | 
					        $imageName = str_replace(' ', '-', $imageName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -205,7 +222,7 @@ class ImageService extends UploadService
 | 
				
			|||||||
            return $this->getPublicUrl($thumbFilePath);
 | 
					            return $this->getPublicUrl($thumbFilePath);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $storage = $this->getStorage();
 | 
					        $storage = $this->getStorage($image->type);
 | 
				
			||||||
        if ($storage->exists($thumbFilePath)) {
 | 
					        if ($storage->exists($thumbFilePath)) {
 | 
				
			||||||
            return $this->getPublicUrl($thumbFilePath);
 | 
					            return $this->getPublicUrl($thumbFilePath);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -289,6 +306,7 @@ class ImageService extends UploadService
 | 
				
			|||||||
     * @param User $user
 | 
					     * @param User $user
 | 
				
			||||||
     * @param int $size
 | 
					     * @param int $size
 | 
				
			||||||
     * @return mixed
 | 
					     * @return mixed
 | 
				
			||||||
 | 
					     * @throws Exception
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public function saveUserGravatar(User $user, $size = 500)
 | 
					    public function saveUserGravatar(User $user, $size = 500)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,11 +11,6 @@ class UploadService
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    protected $fileSystem;
 | 
					    protected $fileSystem;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * @var FileSystemInstance
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    protected $storageInstance;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * FileService constructor.
 | 
					     * FileService constructor.
 | 
				
			||||||
@@ -32,14 +27,8 @@ class UploadService
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    protected function getStorage()
 | 
					    protected function getStorage()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if ($this->storageInstance !== null) {
 | 
					 | 
				
			||||||
            return $this->storageInstance;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $storageType = config('filesystems.default');
 | 
					        $storageType = config('filesystems.default');
 | 
				
			||||||
        $this->storageInstance = $this->fileSystem->disk($storageType);
 | 
					        return $this->fileSystem->disk($storageType);
 | 
				
			||||||
 | 
					 | 
				
			||||||
        return $this->storageInstance;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@@ -53,13 +42,4 @@ class UploadService
 | 
				
			|||||||
        $folders = $this->getStorage()->directories($path);
 | 
					        $folders = $this->getStorage()->directories($path);
 | 
				
			||||||
        return (count($files) === 0 && count($folders) === 0);
 | 
					        return (count($files) === 0 && count($folders) === 0);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Check if using a local filesystem.
 | 
					 | 
				
			||||||
     * @return bool
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    protected function isLocal()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        return strtolower(config('filesystems.default')) === 'local';
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,7 +21,7 @@ class ImageTest extends TestCase
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    protected function getTestImage($fileName)
 | 
					    protected function getTestImage($fileName)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return new \Illuminate\Http\UploadedFile($this->getTestImageFilePath(), $fileName, 'image/jpeg', 5238);
 | 
					        return new \Illuminate\Http\UploadedFile($this->getTestImageFilePath(), $fileName, 'image/png', 5238);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@@ -86,7 +86,42 @@ class ImageTest extends TestCase
 | 
				
			|||||||
            'updated_by' => $admin->id,
 | 
					            'updated_by' => $admin->id,
 | 
				
			||||||
            'name' => $imageName
 | 
					            'name' => $imageName
 | 
				
			||||||
        ]);
 | 
					        ]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function test_secure_images_uploads_to_correct_place()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        config()->set('filesystems.default', 'local_secure');
 | 
				
			||||||
 | 
					        $this->asEditor();
 | 
				
			||||||
 | 
					        $galleryFile = $this->getTestImage('my-secure-test-upload');
 | 
				
			||||||
 | 
					        $page = Page::first();
 | 
				
			||||||
 | 
					        $expectedPath = storage_path('uploads/images/gallery/' . Date('Y-m-M') . '/my-secure-test-upload');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $upload = $this->call('POST', '/images/gallery/upload', ['uploaded_to' => $page->id], [], ['file' => $galleryFile], []);
 | 
				
			||||||
 | 
					        $upload->assertStatus(200);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->assertTrue(file_exists($expectedPath), 'Uploaded image not found at path: '. $expectedPath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (file_exists($expectedPath)) {
 | 
				
			||||||
 | 
					            unlink($expectedPath);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function test_system_images_remain_public()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        config()->set('filesystems.default', 'local_secure');
 | 
				
			||||||
 | 
					        $this->asEditor();
 | 
				
			||||||
 | 
					        $galleryFile = $this->getTestImage('my-system-test-upload');
 | 
				
			||||||
 | 
					        $page = Page::first();
 | 
				
			||||||
 | 
					        $expectedPath = public_path('uploads/images/system/' . Date('Y-m-M') . '/my-system-test-upload');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $upload = $this->call('POST', '/images/system/upload', ['uploaded_to' => $page->id], [], ['file' => $galleryFile], []);
 | 
				
			||||||
 | 
					        $upload->assertStatus(200);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->assertTrue(file_exists($expectedPath), 'Uploaded image not found at path: '. $expectedPath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (file_exists($expectedPath)) {
 | 
				
			||||||
 | 
					            unlink($expectedPath);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function test_image_delete()
 | 
					    public function test_image_delete()
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user