mirror of
https://github.com/BookStackApp/BookStack.git
synced 2025-05-06 17:20:07 +00:00
Cleaned up logic within ImageRepo
- Moved out extension check to ImageService as that seems more relevant. - Updated models to use static-style references instead of facade to align with common modern usage within the app. - Updated custom image_extension validation rule to use shared logic in image service.
This commit is contained in:
parent
43830a372f
commit
c7fea8fe08
5 changed files with 25 additions and 38 deletions
app
Entities/Tools
Http/Controllers/Images
Providers
Uploads
|
@ -9,6 +9,7 @@ use BookStack\Exceptions\ImageUploadException;
|
||||||
use BookStack\Facades\Theme;
|
use BookStack\Facades\Theme;
|
||||||
use BookStack\Theming\ThemeEvents;
|
use BookStack\Theming\ThemeEvents;
|
||||||
use BookStack\Uploads\ImageRepo;
|
use BookStack\Uploads\ImageRepo;
|
||||||
|
use BookStack\Uploads\ImageService;
|
||||||
use BookStack\Util\HtmlContentFilter;
|
use BookStack\Util\HtmlContentFilter;
|
||||||
use DOMDocument;
|
use DOMDocument;
|
||||||
use DOMNodeList;
|
use DOMNodeList;
|
||||||
|
@ -130,7 +131,7 @@ class PageContent
|
||||||
$imageInfo = $this->parseBase64ImageUri($uri);
|
$imageInfo = $this->parseBase64ImageUri($uri);
|
||||||
|
|
||||||
// Validate extension and content
|
// Validate extension and content
|
||||||
if (empty($imageInfo['data']) || !$imageRepo->imageExtensionSupported($imageInfo['extension'])) {
|
if (empty($imageInfo['data']) || !ImageService::isExtensionSupported($imageInfo['extension'])) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,27 +9,19 @@ use BookStack\Uploads\Image;
|
||||||
use BookStack\Uploads\ImageRepo;
|
use BookStack\Uploads\ImageRepo;
|
||||||
use BookStack\Uploads\ImageService;
|
use BookStack\Uploads\ImageService;
|
||||||
use Exception;
|
use Exception;
|
||||||
use Illuminate\Filesystem\Filesystem as File;
|
|
||||||
use Illuminate\Filesystem\FilesystemAdapter;
|
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Storage;
|
|
||||||
use Illuminate\Validation\ValidationException;
|
use Illuminate\Validation\ValidationException;
|
||||||
use League\Flysystem\Util;
|
|
||||||
|
|
||||||
class ImageController extends Controller
|
class ImageController extends Controller
|
||||||
{
|
{
|
||||||
protected $image;
|
|
||||||
protected $file;
|
|
||||||
protected $imageRepo;
|
protected $imageRepo;
|
||||||
protected $imageService;
|
protected $imageService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ImageController constructor.
|
* ImageController constructor.
|
||||||
*/
|
*/
|
||||||
public function __construct(Image $image, File $file, ImageRepo $imageRepo, ImageService $imageService)
|
public function __construct(ImageRepo $imageRepo, ImageService $imageService)
|
||||||
{
|
{
|
||||||
$this->image = $image;
|
|
||||||
$this->file = $file;
|
|
||||||
$this->imageRepo = $imageRepo;
|
$this->imageRepo = $imageRepo;
|
||||||
$this->imageService = $imageService;
|
$this->imageService = $imageService;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace BookStack\Providers;
|
namespace BookStack\Providers;
|
||||||
|
|
||||||
|
use BookStack\Uploads\ImageService;
|
||||||
use Illuminate\Support\Facades\Validator;
|
use Illuminate\Support\Facades\Validator;
|
||||||
use Illuminate\Support\ServiceProvider;
|
use Illuminate\Support\ServiceProvider;
|
||||||
|
|
||||||
|
@ -13,9 +14,8 @@ class CustomValidationServiceProvider extends ServiceProvider
|
||||||
public function boot(): void
|
public function boot(): void
|
||||||
{
|
{
|
||||||
Validator::extend('image_extension', function ($attribute, $value, $parameters, $validator) {
|
Validator::extend('image_extension', function ($attribute, $value, $parameters, $validator) {
|
||||||
$validImageExtensions = ['png', 'jpg', 'jpeg', 'gif', 'webp'];
|
$extension = strtolower($value->getClientOriginalExtension());
|
||||||
|
return ImageService::isExtensionSupported($extension);
|
||||||
return in_array(strtolower($value->getClientOriginalExtension()), $validImageExtensions);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Validator::extend('safe_url', function ($attribute, $value, $parameters, $validator) {
|
Validator::extend('safe_url', function ($attribute, $value, $parameters, $validator) {
|
||||||
|
|
|
@ -11,36 +11,18 @@ use Symfony\Component\HttpFoundation\File\UploadedFile;
|
||||||
|
|
||||||
class ImageRepo
|
class ImageRepo
|
||||||
{
|
{
|
||||||
protected $image;
|
|
||||||
protected $imageService;
|
protected $imageService;
|
||||||
protected $restrictionService;
|
protected $restrictionService;
|
||||||
protected $page;
|
|
||||||
|
|
||||||
protected static $supportedExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ImageRepo constructor.
|
* ImageRepo constructor.
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
Image $image,
|
|
||||||
ImageService $imageService,
|
ImageService $imageService,
|
||||||
PermissionService $permissionService,
|
PermissionService $permissionService
|
||||||
Page $page
|
|
||||||
) {
|
) {
|
||||||
$this->image = $image;
|
|
||||||
$this->imageService = $imageService;
|
$this->imageService = $imageService;
|
||||||
$this->restrictionService = $permissionService;
|
$this->restrictionService = $permissionService;
|
||||||
$this->page = $page;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the given image extension is supported by BookStack.
|
|
||||||
* The extension must not be altered in this function. This check should provide a guarantee
|
|
||||||
* that the provided extension is safe to use for the image to be saved.
|
|
||||||
*/
|
|
||||||
public function imageExtensionSupported(string $extension): bool
|
|
||||||
{
|
|
||||||
return in_array($extension, static::$supportedExtensions);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -48,7 +30,7 @@ class ImageRepo
|
||||||
*/
|
*/
|
||||||
public function getById($id): Image
|
public function getById($id): Image
|
||||||
{
|
{
|
||||||
return $this->image->findOrFail($id);
|
return Image::query()->findOrFail($id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -83,7 +65,7 @@ class ImageRepo
|
||||||
string $search = null,
|
string $search = null,
|
||||||
callable $whereClause = null
|
callable $whereClause = null
|
||||||
): array {
|
): array {
|
||||||
$imageQuery = $this->image->newQuery()->where('type', '=', strtolower($type));
|
$imageQuery = Image::query()->where('type', '=', strtolower($type));
|
||||||
|
|
||||||
if ($uploadedTo !== null) {
|
if ($uploadedTo !== null) {
|
||||||
$imageQuery = $imageQuery->where('uploaded_to', '=', $uploadedTo);
|
$imageQuery = $imageQuery->where('uploaded_to', '=', $uploadedTo);
|
||||||
|
@ -114,7 +96,7 @@ class ImageRepo
|
||||||
int $uploadedTo = null,
|
int $uploadedTo = null,
|
||||||
string $search = null
|
string $search = null
|
||||||
): array {
|
): array {
|
||||||
$contextPage = $this->page->findOrFail($uploadedTo);
|
$contextPage = Page::visible()->findOrFail($uploadedTo);
|
||||||
$parentFilter = null;
|
$parentFilter = null;
|
||||||
|
|
||||||
if ($filterType === 'book' || $filterType === 'page') {
|
if ($filterType === 'book' || $filterType === 'page') {
|
||||||
|
@ -205,7 +187,7 @@ class ImageRepo
|
||||||
*/
|
*/
|
||||||
public function destroyByType(string $imageType)
|
public function destroyByType(string $imageType)
|
||||||
{
|
{
|
||||||
$images = $this->image->where('type', '=', $imageType)->get();
|
$images = Image::query()->where('type', '=', $imageType)->get();
|
||||||
foreach ($images as $image) {
|
foreach ($images as $image) {
|
||||||
$this->destroyImage($image);
|
$this->destroyImage($image);
|
||||||
}
|
}
|
||||||
|
@ -218,10 +200,10 @@ class ImageRepo
|
||||||
*/
|
*/
|
||||||
public function loadThumbs(Image $image)
|
public function loadThumbs(Image $image)
|
||||||
{
|
{
|
||||||
$image->thumbs = [
|
$image->setAttribute('thumbs', [
|
||||||
'gallery' => $this->getThumbnail($image, 150, 150, false),
|
'gallery' => $this->getThumbnail($image, 150, 150, false),
|
||||||
'display' => $this->getThumbnail($image, 1680, null, true),
|
'display' => $this->getThumbnail($image, 1680, null, true),
|
||||||
];
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -26,6 +26,8 @@ class ImageService
|
||||||
protected $image;
|
protected $image;
|
||||||
protected $fileSystem;
|
protected $fileSystem;
|
||||||
|
|
||||||
|
protected static $supportedExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ImageService constructor.
|
* ImageService constructor.
|
||||||
*/
|
*/
|
||||||
|
@ -470,6 +472,16 @@ class ImageService
|
||||||
return $disk->response($path);
|
return $disk->response($path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the given image extension is supported by BookStack.
|
||||||
|
* The extension must not be altered in this function. This check should provide a guarantee
|
||||||
|
* that the provided extension is safe to use for the image to be saved.
|
||||||
|
*/
|
||||||
|
public static function isExtensionSupported(string $extension): bool
|
||||||
|
{
|
||||||
|
return in_array($extension, static::$supportedExtensions);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a storage path for the given image URL.
|
* Get a storage path for the given image URL.
|
||||||
* Ensures the path will start with "uploads/images".
|
* Ensures the path will start with "uploads/images".
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue