]> BookStack Code Mirror - bookstack/commitdiff
Merge branch 'master' into draw.io to fetch auth image changes
authorDan Brown <redacted>
Sat, 20 Jan 2018 14:06:44 +0000 (14:06 +0000)
committerDan Brown <redacted>
Sat, 20 Jan 2018 14:06:44 +0000 (14:06 +0000)
1  2 
app/Http/Controllers/ImageController.php
app/Repos/ImageRepo.php
app/Services/ImageService.php
routes/web.php

index 81e300a68c9950c6060860620bfe9179a04087de,d783507545d421ba63a536eaf5cbfeaaaf51dccd..c44b6e480429ab5f24292c0bc8bbab6c631fb789
@@@ -1,6 -1,7 +1,7 @@@
  <?php namespace BookStack\Http\Controllers;
  
  use BookStack\Exceptions\ImageUploadException;
+ use BookStack\Exceptions\NotFoundException;
  use BookStack\Repos\EntityRepo;
  use BookStack\Repos\ImageRepo;
  use Illuminate\Filesystem\Filesystem as File;
@@@ -28,6 -29,21 +29,21 @@@ class ImageController extends Controlle
          parent::__construct();
      }
  
+     /**
+      * Provide an image file from storage.
+      * @param string $path
+      * @return mixed
+      */
+     public function showImage(string $path)
+     {
+         $path = storage_path('uploads/images/' . $path);
+         if (!file_exists($path)) {
+             abort(404);
+         }
+         return response()->file($path);
+     }
      /**
       * Get all images for a specific type, Paginated
       * @param string $type
       * @param string $type
       * @param Request $request
       * @return \Illuminate\Http\JsonResponse
 +     * @throws \Exception
       */
      public function uploadByType($type, Request $request)
      {
          $this->validate($request, [
              'file' => 'is_image'
          ]);
 +        // TODO - Restrict & validate types
  
          $imageUpload = $request->file('file');
  
          try {
 -            $uploadedTo = $request->filled('uploaded_to') ? $request->get('uploaded_to') : 0;
 +            $uploadedTo = $request->get('uploaded_to', 0);
              $image = $this->imageRepo->saveNew($imageUpload, $type, $uploadedTo);
          } catch (ImageUploadException $e) {
              return response($e->getMessage(), 500);
          return response()->json($image);
      }
  
 +    /**
 +     * Upload a drawing to the system.
 +     * @param Request $request
 +     * @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\JsonResponse|\Symfony\Component\HttpFoundation\Response
 +     */
 +    public function uploadDrawing(Request $request)
 +    {
 +        $this->validate($request, [
 +            'image' => 'required|string',
 +            'uploaded_to' => 'required|integer'
 +        ]);
 +        $this->checkPermission('image-create-all');
 +        $imageBase64Data = $request->get('image');
 +
 +        try {
 +            $uploadedTo = $request->get('uploaded_to', 0);
 +            $image = $this->imageRepo->saveDrawing($imageBase64Data, $uploadedTo);
 +        } catch (ImageUploadException $e) {
 +            return response($e->getMessage(), 500);
 +        }
 +
 +        return response()->json($image);
 +    }
 +
 +    /**
 +     * Replace the data content of a drawing.
 +     * @param string $id
 +     * @param Request $request
 +     * @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\JsonResponse|\Symfony\Component\HttpFoundation\Response
 +     */
 +    public function replaceDrawing(string $id, Request $request)
 +    {
 +        $this->validate($request, [
 +            'image' => 'required|string'
 +        ]);
 +        $this->checkPermission('image-create-all');
 +
 +        $imageBase64Data = $request->get('image');
 +        $image = $this->imageRepo->getById($id);
 +        $this->checkOwnablePermission('image-update', $image);
 +
 +        try {
 +            $image = $this->imageRepo->replaceDrawingContent($image, $imageBase64Data);
 +        } catch (ImageUploadException $e) {
 +            return response($e->getMessage(), 500);
 +        }
 +
 +        return response()->json($image);
 +    }
 +
 +    /**
 +     * Get the content of an image based64 encoded.
 +     * @param $id
 +     * @return \Illuminate\Http\JsonResponse|mixed
 +     */
 +    public function getBase64Image($id)
 +    {
 +        $image = $this->imageRepo->getById($id);
 +        $imageData = $this->imageRepo->getImageData($image);
 +        if ($imageData === null) {
 +            return $this->jsonError("Image data could not be found");
 +        }
 +        return response()->json([
 +            'content' => base64_encode($imageData)
 +        ]);
 +    }
 +
      /**
       * Generate a sized thumbnail for an image.
       * @param $id
       * @param $height
       * @param $crop
       * @return \Illuminate\Http\JsonResponse
 +     * @throws ImageUploadException
 +     * @throws \Exception
       */
      public function getThumbnail($id, $width, $height, $crop)
      {
       * @param integer $imageId
       * @param Request $request
       * @return \Illuminate\Http\JsonResponse
 +     * @throws ImageUploadException
 +     * @throws \Exception
       */
      public function update($imageId, Request $request)
      {
diff --combined app/Repos/ImageRepo.php
index 492834446262d115a5a23ee38a44baa652ba3f9c,5f04a74b19ab9dd938a3655ec94506aca56b099a..3918d5f67c30b99ff45d14e89915fc4b9adf2ef5
@@@ -132,8 -132,6 +132,8 @@@ class ImageRep
       * @param  string $type
       * @param int $uploadedTo
       * @return Image
 +     * @throws \BookStack\Exceptions\ImageUploadException
 +     * @throws \Exception
       */
      public function saveNew(UploadedFile $uploadFile, $type, $uploadedTo = 0)
      {
          return $image;
      }
  
 +    /**
 +     * Save a drawing the the database;
 +     * @param string $base64Uri
 +     * @param int $uploadedTo
 +     * @return Image
 +     * @throws \BookStack\Exceptions\ImageUploadException
 +     */
 +    public function saveDrawing(string $base64Uri, int $uploadedTo)
 +    {
 +        $name = 'Drawing-' . user()->getShortName(40) . '-' . strval(time()) . '.png';
 +        $image = $this->imageService->saveNewFromBase64Uri($base64Uri, $name, 'drawing', $uploadedTo);
 +        return $image;
 +    }
 +
 +    /**
 +     * Replace the image content of a drawing.
 +     * @param Image $image
 +     * @param string $base64Uri
 +     * @return Image
 +     * @throws \BookStack\Exceptions\ImageUploadException
 +     */
 +    public function replaceDrawingContent(Image $image, string $base64Uri)
 +    {
 +        return $this->imageService->replaceImageDataFromBase64Uri($image, $base64Uri);
 +    }
 +
      /**
       * Update the details of an image via an array of properties.
       * @param Image $image
       * @param array $updateDetails
       * @return Image
 +     * @throws \BookStack\Exceptions\ImageUploadException
 +     * @throws \Exception
       */
      public function updateImageDetails(Image $image, $updateDetails)
      {
      /**
       * Load thumbnails onto an image object.
       * @param Image $image
 +     * @throws \BookStack\Exceptions\ImageUploadException
 +     * @throws \Exception
       */
      private function loadThumbs(Image $image)
      {
       * Get the thumbnail for an image.
       * If $keepRatio is true only the width will be used.
       * 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
       * @return string
 +     * @throws \BookStack\Exceptions\ImageUploadException
 +     * @throws \Exception
       */
      public function getThumbnail(Image $image, $width = 220, $height = 220, $keepRatio = false)
      {
          try {
              return $this->imageService->getThumbnail($image, $width, $height, $keepRatio);
-         } catch (FileNotFoundException $exception) {
-             $image->delete();
-             return [];
+         } catch (\Exception $exception) {
+             dd($exception);
+             return null;
          }
      }
  
 +    /**
 +     * Get the raw image data from an Image.
 +     * @param Image $image
 +     * @return null|string
 +     */
 +    public function getImageData(Image $image)
 +    {
 +        try {
 +            return $this->imageService->getImageData($image);
 +        } catch (\Exception $exception) {
 +            return null;
 +        }
 +    }
 +
  
  }
index 1da68ddf1829e599d1e893d622009598dfde2320,43375ee094355dd214e7cb9e77af1d328438de8b..5eea285e5fda62ab74e6afb683277cf4a5d798e6
@@@ -46,50 -46,6 +46,50 @@@ class ImageService extends UploadServic
          return $this->saveNew($imageName, $imageData, $type, $uploadedTo);
      }
  
 +    /**
 +     * Save a new image from a uri-encoded base64 string of data.
 +     * @param string $base64Uri
 +     * @param string $name
 +     * @param string $type
 +     * @param int $uploadedTo
 +     * @return Image
 +     * @throws ImageUploadException
 +     */
 +    public function saveNewFromBase64Uri(string $base64Uri, string $name, string $type, $uploadedTo = 0)
 +    {
 +        $splitData = explode(';base64,', $base64Uri);
 +        if (count($splitData) < 2) {
 +            throw new ImageUploadException("Invalid base64 image data provided");
 +        }
 +        $data = base64_decode($splitData[1]);
 +        return $this->saveNew($name, $data, $type, $uploadedTo);
 +    }
 +
 +    /**
 +     * Replace the data for an image via a Base64 encoded string.
 +     * @param Image $image
 +     * @param string $base64Uri
 +     * @return Image
 +     * @throws ImageUploadException
 +     */
 +    public function replaceImageDataFromBase64Uri(Image $image, string $base64Uri)
 +    {
 +        $splitData = explode(';base64,', $base64Uri);
 +        if (count($splitData) < 2) {
 +            throw new ImageUploadException("Invalid base64 image data provided");
 +        }
 +        $data = base64_decode($splitData[1]);
 +        $storage = $this->getStorage();
 +
 +        try {
 +            $storage->put($image->path, $data);
 +        } catch (Exception $e) {
 +            throw new ImageUploadException(trans('errors.path_not_writable', ['filePath' => $image->path]));
 +        }
 +
 +        return $image;
 +    }
 +
      /**
       * Gets an image from url and saves it to the database.
       * @param             $url
  
          $imagePath = '/uploads/images/' . $type . '/' . Date('Y-m-M') . '/';
  
-         if ($this->isLocal()) $imagePath = '/public' . $imagePath;
          while ($storage->exists($imagePath . $imageName)) {
              $imageName = str_random(3) . $imageName;
          }
              throw new ImageUploadException(trans('errors.path_not_writable', ['filePath' => $fullPath]));
          }
  
-         if ($this->isLocal()) $fullPath = str_replace_first('/public', '', $fullPath);
          $imageDetails = [
              'name'       => $imageName,
              'path'       => $fullPath,
              $imageDetails['updated_by'] = $userId;
          }
  
-         $image = Image::forceCreate($imageDetails);
+         $image = (new Image());
+         $image->forceFill($imageDetails)->save();
          return $image;
      }
  
       */
      protected function getPath(Image $image)
      {
-         return ($this->isLocal()) ? ('public/' . $image->path) : $image->path;
+         return $image->path;
      }
  
      /**
       * Get the thumbnail for an image.
       * If $keepRatio is true only the width will be used.
       * Checks the cache then storage to avoid creating / accessing the filesystem on every check.
-      *
       * @param Image $image
       * @param int $width
       * @param int $height
          }
  
          $storage = $this->getStorage();
          if ($storage->exists($thumbFilePath)) {
              return $this->getPublicUrl($thumbFilePath);
          }
          } catch (Exception $e) {
              if ($e instanceof \ErrorException || $e instanceof NotSupportedException) {
                  throw new ImageUploadException(trans('errors.cannot_create_thumbs'));
-             } else {
-                 throw $e;
              }
+             throw $e;
          }
  
          if ($keepRatio) {
          return $this->getPublicUrl($thumbFilePath);
      }
  
 +    /**
 +     * Get the raw data content from an image.
 +     * @param Image $image
 +     * @return string
 +     * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
 +     */
 +    public function getImageData(Image $image)
 +    {
 +        $imagePath = $this->getPath($image);
 +        $storage = $this->getStorage();
 +        return $storage->get($imagePath);
 +    }
 +
      /**
       * Destroys an Image object along with its files and thumbnails.
       * @param Image $image
                      $storageUrl = 'https://s3-' . $storageDetails['region'] . '.amazonaws.com/' . $storageDetails['bucket'];
                  }
              }
              $this->storageUrl = $storageUrl;
          }
  
-         if ($this->isLocal()) $filePath = str_replace_first('public/', '', $filePath);
-         return ($this->storageUrl == false ? rtrim(baseUrl(''), '/') : rtrim($this->storageUrl, '/')) . $filePath;
+         $basePath = ($this->storageUrl == false) ? baseUrl('/') : $this->storageUrl;
+         return rtrim($basePath, '/') . $filePath;
      }
  
  
diff --combined routes/web.php
index 08c919e26875564ac8d527bea114d37e935eeae7,06805714d7b644bf3beff65699c8b0473d6df315..a69e672e47ee7a1999b248397c64850045b0aacc
@@@ -5,6 -5,9 +5,9 @@@ Route::get('/translations', 'HomeContro
  // Authenticated routes...
  Route::group(['middleware' => 'auth'], function () {
  
+     Route::get('/uploads/images/{path}', 'ImageController@showImage')
+         ->where('path', '.*$');
      Route::group(['prefix' => 'pages'], function() {
          Route::get('/recently-created', 'PageController@showRecentlyCreated');
          Route::get('/recently-updated', 'PageController@showRecentlyUpdated');
          Route::get('/user/all/{page}', 'ImageController@getAllForUserType');
          // Standard get, update and deletion for all types
          Route::get('/thumb/{id}/{width}/{height}/{crop}', 'ImageController@getThumbnail');
 +        Route::get('/base64/{id}', 'ImageController@getBase64Image');
          Route::put('/update/{imageId}', 'ImageController@update');
 +        Route::post('/drawing/upload', 'ImageController@uploadDrawing');
 +        Route::put('/drawing/upload/{id}', 'ImageController@replaceDrawing');
          Route::post('/{type}/upload', 'ImageController@uploadByType');
          Route::get('/{type}/all', 'ImageController@getAllByType');
          Route::get('/{type}/all/{page}', 'ImageController@getAllByType');
          Route::get('/{type}/search/{page}', 'ImageController@searchByType');
          Route::get('/gallery/{filter}/{page}', 'ImageController@getGalleryFiltered');
 -        Route::delete('/{imageId}', 'ImageController@destroy');
 +        Route::delete('/{id}', 'ImageController@destroy');
      });
  
      // Attachments routes