diff --git a/app/Http/Controllers/ImageController.php b/app/Http/Controllers/ImageController.php index 36e44c755..7820f6f91 100644 --- a/app/Http/Controllers/ImageController.php +++ b/app/Http/Controllers/ImageController.php @@ -20,8 +20,8 @@ class ImageController extends Controller /** * ImageController constructor. - * @param Image $image - * @param File $file + * @param Image $image + * @param File $file * @param ImageRepo $imageRepo */ public function __construct(Image $image, File $file, ImageRepo $imageRepo) @@ -34,6 +34,7 @@ class ImageController extends Controller /** * Get all images for a specific type, Paginated + * @param string $type * @param int $page * @return \Illuminate\Http\JsonResponse */ @@ -56,7 +57,7 @@ class ImageController extends Controller /** * Handles image uploads for use on pages. - * @param string $type + * @param string $type * @param Request $request * @return \Illuminate\Http\JsonResponse */ @@ -64,13 +65,15 @@ class ImageController extends Controller { $this->checkPermission('image-create-all'); $this->validate($request, [ - 'file' => 'image|mimes:jpeg,gif,png' + 'file' => 'image|mimes:jpeg,gif,png', + 'uploaded_to' => 'integer|exists:pages,id' ]); $imageUpload = $request->file('file'); try { - $image = $this->imageRepo->saveNew($imageUpload, $type); + $uploadedTo = $request->has('uploaded_to') ? $request->get('uploaded_to') : 0; + $image = $this->imageRepo->saveNew($imageUpload, $type, $uploadedTo); } catch (ImageUploadException $e) { return response($e->getMessage(), 500); } @@ -96,7 +99,7 @@ class ImageController extends Controller /** * Update image details - * @param $imageId + * @param integer $imageId * @param Request $request * @return \Illuminate\Http\JsonResponse */ @@ -114,8 +117,8 @@ class ImageController extends Controller /** * Deletes an image and all thumbnail/image files * @param PageRepo $pageRepo - * @param Request $request - * @param int $id + * @param Request $request + * @param int $id * @return \Illuminate\Http\JsonResponse */ public function destroy(PageRepo $pageRepo, Request $request, $id) diff --git a/app/Repos/ImageRepo.php b/app/Repos/ImageRepo.php index d41909ac5..2e2624a6e 100644 --- a/app/Repos/ImageRepo.php +++ b/app/Repos/ImageRepo.php @@ -3,6 +3,7 @@ use BookStack\Image; use BookStack\Services\ImageService; +use BookStack\Services\RestrictionService; use Setting; use Symfony\Component\HttpFoundation\File\UploadedFile; @@ -11,16 +12,19 @@ class ImageRepo protected $image; protected $imageService; + protected $restictionService; /** * ImageRepo constructor. - * @param Image $image + * @param Image $image * @param ImageService $imageService + * @param RestrictionService $restrictionService */ - public function __construct(Image $image, ImageService $imageService) + public function __construct(Image $image, ImageService $imageService, RestrictionService $restrictionService) { $this->image = $image; $this->imageService = $imageService; + $this->restictionService = $restrictionService; } @@ -34,13 +38,12 @@ class ImageRepo return $this->image->findOrFail($id); } - /** * Gets a load images paginated, filtered by image type. * @param string $type - * @param int $page - * @param int $pageSize - * @param bool|int $userFilter + * @param int $page + * @param int $pageSize + * @param bool|int $userFilter * @return array */ public function getPaginatedByType($type, $page = 0, $pageSize = 24, $userFilter = false) @@ -51,6 +54,7 @@ class ImageRepo $images = $images->where('created_by', '=', $userFilter); } + $images = $this->restictionService->filterRelatedPages($images, 'images', 'uploaded_to'); $images = $images->orderBy('created_at', 'desc')->skip($pageSize * $page)->take($pageSize + 1)->get(); $hasMore = count($images) > $pageSize; @@ -68,12 +72,13 @@ class ImageRepo /** * Save a new image into storage and return the new image. * @param UploadedFile $uploadFile - * @param string $type + * @param string $type + * @param int $uploadedTo * @return Image */ - public function saveNew(UploadedFile $uploadFile, $type) + public function saveNew(UploadedFile $uploadFile, $type, $uploadedTo = 0) { - $image = $this->imageService->saveNewFromUpload($uploadFile, $type); + $image = $this->imageService->saveNewFromUpload($uploadFile, $type, $uploadedTo); $this->loadThumbs($image); return $image; } @@ -123,9 +128,9 @@ class ImageRepo * Checks the cache then storage to avoid creating / accessing the filesystem on every check. * * @param Image $image - * @param int $width - * @param int $height - * @param bool $keepRatio + * @param int $width + * @param int $height + * @param bool $keepRatio * @return string */ public function getThumbnail(Image $image, $width = 220, $height = 220, $keepRatio = false) diff --git a/app/Services/ImageService.php b/app/Services/ImageService.php index aefc8a4fb..dd965c90f 100644 --- a/app/Services/ImageService.php +++ b/app/Services/ImageService.php @@ -41,14 +41,16 @@ class ImageService /** * Saves a new image from an upload. * @param UploadedFile $uploadedFile - * @param string $type + * @param string $type + * @param int $uploadedTo * @return mixed + * @throws ImageUploadException */ - public function saveNewFromUpload(UploadedFile $uploadedFile, $type) + public function saveNewFromUpload(UploadedFile $uploadedFile, $type, $uploadedTo = 0) { $imageName = $uploadedFile->getClientOriginalName(); $imageData = file_get_contents($uploadedFile->getRealPath()); - return $this->saveNew($imageName, $imageData, $type); + return $this->saveNew($imageName, $imageData, $type, $uploadedTo); } @@ -73,10 +75,11 @@ class ImageService * @param string $imageName * @param string $imageData * @param string $type + * @param int $uploadedTo * @return Image * @throws ImageUploadException */ - private function saveNew($imageName, $imageData, $type) + private function saveNew($imageName, $imageData, $type, $uploadedTo = 0) { $storage = $this->getStorage(); $secureUploads = setting('app-secure-images'); @@ -100,7 +103,8 @@ class ImageService 'name' => $imageName, 'path' => $fullPath, 'url' => $this->getPublicUrl($fullPath), - 'type' => $type + 'type' => $type, + 'uploaded_to' => $uploadedTo ]; if (auth()->user() && auth()->user()->id !== 0) { diff --git a/app/Services/RestrictionService.php b/app/Services/RestrictionService.php index 6bc612bb0..d20724866 100644 --- a/app/Services/RestrictionService.php +++ b/app/Services/RestrictionService.php @@ -50,10 +50,10 @@ class RestrictionService public function enforcePageRestrictions($query, $action = 'view') { // Prevent drafts being visible to others. - $query = $query->where(function($query) { + $query = $query->where(function ($query) { $query->where('draft', '=', false); if ($this->currentUser) { - $query->orWhere(function($query) { + $query->orWhere(function ($query) { $query->where('draft', '=', true)->where('created_by', '=', $this->currentUser->id); }); } @@ -264,6 +264,30 @@ class RestrictionService }); } + /** + * Filters pages that are a direct relation to another item. + * @param $query + * @param $tableName + * @param $entityIdColumn + * @return mixed + */ + public function filterRelatedPages($query, $tableName, $entityIdColumn) + { + if ($this->isAdmin) return $query; + $this->currentAction = 'view'; + $tableDetails = ['tableName' => $tableName, 'entityIdColumn' => $entityIdColumn]; + return $query->where(function ($query) use (&$tableDetails) { + $query->where(function ($query) use (&$tableDetails) { + $query->whereExists(function ($query) use (&$tableDetails) { + $query->select('*')->from('pages')->whereRaw('pages.id=' . $tableDetails['tableName'] . '.' . $tableDetails['entityIdColumn']) + ->where(function ($query) { + $this->pageRestrictionQuery($query); + }); + })->orWhere($tableDetails['entityIdColumn'], '=', 0); + }); + }); + } + /** * The query to check the restrictions on an entity. * @param $query diff --git a/database/migrations/2016_03_13_082138_image_entities_and_page_drafts.php b/database/migrations/2016_03_13_082138_add_page_drafts.php similarity index 54% rename from database/migrations/2016_03_13_082138_image_entities_and_page_drafts.php rename to database/migrations/2016_03_13_082138_add_page_drafts.php index 0852372f1..794ee6a5f 100644 --- a/database/migrations/2016_03_13_082138_image_entities_and_page_drafts.php +++ b/database/migrations/2016_03_13_082138_add_page_drafts.php @@ -3,7 +3,7 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; -class ImageEntitiesAndPageDrafts extends Migration +class AddPageDrafts extends Migration { /** * Run the migrations. @@ -12,12 +12,6 @@ class ImageEntitiesAndPageDrafts extends Migration */ public function up() { - Schema::table('images', function (Blueprint $table) { - $table->string('entity_type', 100); - $table->integer('entity_id'); - $table->index(['entity_type', 'entity_id']); - }); - Schema::table('pages', function(Blueprint $table) { $table->boolean('draft')->default(false); $table->index('draft'); @@ -31,12 +25,6 @@ class ImageEntitiesAndPageDrafts extends Migration */ public function down() { - Schema::table('images', function (Blueprint $table) { - $table->dropIndex(['entity_type', 'entity_id']); - $table->dropColumn('entity_type'); - $table->dropColumn('entity_id'); - }); - Schema::table('pages', function (Blueprint $table) { $table->dropColumn('draft'); }); diff --git a/resources/assets/js/controllers.js b/resources/assets/js/controllers.js index f3c80f73e..29a448265 100644 --- a/resources/assets/js/controllers.js +++ b/resources/assets/js/controllers.js @@ -13,6 +13,7 @@ module.exports = function (ngApp, events) { $scope.hasMore = false; $scope.imageUpdateSuccess = false; $scope.imageDeleteSuccess = false; + $scope.uploadedTo = $attrs.uploadedTo; var page = 0; var previousClickTime = 0; diff --git a/resources/assets/js/directives.js b/resources/assets/js/directives.js index 72d35d455..71b35fb42 100644 --- a/resources/assets/js/directives.js +++ b/resources/assets/js/directives.js @@ -110,7 +110,8 @@ module.exports = function (ngApp, events) { scope: { uploadUrl: '@', eventSuccess: '=', - eventError: '=' + eventError: '=', + uploadedTo: '@' }, link: function (scope, element, attrs) { var dropZone = new DropZone(element[0].querySelector('.dropzone-container'), { @@ -120,6 +121,8 @@ module.exports = function (ngApp, events) { dz.on('sending', function (file, xhr, data) { var token = window.document.querySelector('meta[name=token]').getAttribute('content'); data.append('_token', token); + var uploadedTo = typeof scope.uploadedTo === 'undefined' ? 0 : scope.uploadedTo; + data.append('uploaded_to', uploadedTo); }); if (typeof scope.eventSuccess !== 'undefined') dz.on('success', scope.eventSuccess); dz.on('success', function (file, data) { diff --git a/resources/views/pages/create.blade.php b/resources/views/pages/create.blade.php index f532cc2b6..2c6403e48 100644 --- a/resources/views/pages/create.blade.php +++ b/resources/views/pages/create.blade.php @@ -13,5 +13,5 @@ @include('pages/form', ['model' => $draft]) - @include('partials/image-manager', ['imageType' => 'gallery']) + @include('partials/image-manager', ['imageType' => 'gallery', 'uploaded_to' => $draft->id]) @stop \ No newline at end of file diff --git a/resources/views/pages/edit.blade.php b/resources/views/pages/edit.blade.php index 751ed79c7..0ad06fc53 100644 --- a/resources/views/pages/edit.blade.php +++ b/resources/views/pages/edit.blade.php @@ -14,6 +14,6 @@ @include('pages/form', ['model' => $page]) - @include('partials/image-manager', ['imageType' => 'gallery']) + @include('partials/image-manager', ['imageType' => 'gallery', 'uploaded_to' => $page->id]) @stop \ No newline at end of file diff --git a/resources/views/partials/image-manager.blade.php b/resources/views/partials/image-manager.blade.php index bf7bf445c..a394975d8 100644 --- a/resources/views/partials/image-manager.blade.php +++ b/resources/views/partials/image-manager.blade.php @@ -1,4 +1,4 @@ -
+
@@ -22,7 +22,7 @@

Images

- +