From 3c71be5d45755f46cde218e34a6410cdfc215867 Mon Sep 17 00:00:00 2001 From: formsdev <136701234+formsdev@users.noreply.github.com> Date: Wed, 16 Aug 2023 14:29:07 +0530 Subject: [PATCH] Storage support for local disk (#165) * Storage support for local disk * UI change ai feature page --------- Co-authored-by: Julien Nahum --- .../Content/FileUploadController.php | 28 +++++++++++++++++++ app/Http/Controllers/Forms/FormController.php | 8 +++--- .../Forms/FormSubmissionController.php | 4 +-- .../Forms/PublicFormController.php | 6 ++-- app/Http/Middleware/VerifyCsrfToken.php | 3 +- app/Jobs/Form/StoreFormSubmissionJob.php | 8 +++--- app/Providers/AppServiceProvider.php | 13 ++++++++- app/Rules/StorageFile.php | 2 +- .../js/components/pages/welcome/AiFeature.vue | 9 ++++-- resources/js/plugins/vapor.js | 20 +++++++++++++ resources/views/spa.blade.php | 3 +- routes/web.php | 15 ++++++++++ 12 files changed, 99 insertions(+), 20 deletions(-) create mode 100644 app/Http/Controllers/Content/FileUploadController.php diff --git a/app/Http/Controllers/Content/FileUploadController.php b/app/Http/Controllers/Content/FileUploadController.php new file mode 100644 index 0000000..62e6423 --- /dev/null +++ b/app/Http/Controllers/Content/FileUploadController.php @@ -0,0 +1,28 @@ +file('file')->storeAs(PublicFormController::TMP_FILE_UPLOAD_PATH, $uuid); + + return response()->json([ + 'uuid' => $uuid, + 'key' => $path + ], 201); + } +} diff --git a/app/Http/Controllers/Forms/FormController.php b/app/Http/Controllers/Forms/FormController.php index 6c99b7b..5865f1d 100644 --- a/app/Http/Controllers/Forms/FormController.php +++ b/app/Http/Controllers/Forms/FormController.php @@ -177,12 +177,12 @@ class FormController extends Controller // Make sure we retrieve the file in tmp storage, move it to persistent $fileName = PublicFormController::TMP_FILE_UPLOAD_PATH.'/'.$fileNameParser->uuid;; - if (!Storage::disk('s3')->exists($fileName)) { + if (!Storage::exists($fileName)) { // File not found, we skip return null; } $newPath = self::ASSETS_UPLOAD_PATH.'/'.$fileNameParser->getMovedFileName(); - Storage::disk('s3')->move($fileName, $newPath); + Storage::move($fileName, $newPath); return $this->success([ 'message' => 'File uploaded.', @@ -199,12 +199,12 @@ class FormController extends Controller $this->authorize('view', $form); $path = Str::of(PublicFormController::FILE_UPLOAD_PATH)->replace('?', $form->id).'/'.$fileName; - if (!Storage::disk('s3')->exists($path)) { + if (!Storage::exists($path)) { return $this->error([ 'message' => 'File not found.' ]); } - return redirect()->to(Storage::disk('s3')->temporaryUrl($path, now()->addMinutes(5))); + return redirect()->to(Storage::temporaryUrl($path, now()->addMinutes(5))); } } diff --git a/app/Http/Controllers/Forms/FormSubmissionController.php b/app/Http/Controllers/Forms/FormSubmissionController.php index ba7a8f8..75d1a90 100644 --- a/app/Http/Controllers/Forms/FormSubmissionController.php +++ b/app/Http/Controllers/Forms/FormSubmissionController.php @@ -57,14 +57,14 @@ class FormSubmissionController extends Controller $fileName = Str::of(PublicFormController::FILE_UPLOAD_PATH)->replace('?', $id).'/' .urldecode($fileName); - if (!Storage::disk('s3')->exists($fileName)) { + if (!Storage::exists($fileName)) { return $this->error([ 'message' => 'File not found.', ], 404); } return redirect( - Storage::disk('s3')->temporaryUrl($fileName, now()->addMinute()) + Storage::temporaryUrl($fileName, now()->addMinute()) ); } } diff --git a/app/Http/Controllers/Forms/PublicFormController.php b/app/Http/Controllers/Forms/PublicFormController.php index 69f7e67..8856ba7 100644 --- a/app/Http/Controllers/Forms/PublicFormController.php +++ b/app/Http/Controllers/Forms/PublicFormController.php @@ -66,14 +66,14 @@ class PublicFormController extends Controller public function showAsset($assetFileName) { $path = FormController::ASSETS_UPLOAD_PATH.'/'.$assetFileName; - if (!Storage::disk('s3')->exists($path)) { + if (!Storage::exists($path)) { return $this->error([ 'message' => 'File not found.', 'file_name' => $assetFileName ]); } - - return redirect()->to(Storage::disk('s3')->temporaryUrl($path, now()->addMinutes(5))); + + return redirect()->to(Storage::temporaryUrl($path, now()->addMinutes(5))); } public function answer(AnswerFormRequest $request) diff --git a/app/Http/Middleware/VerifyCsrfToken.php b/app/Http/Middleware/VerifyCsrfToken.php index 81cca90..7d14bf7 100644 --- a/app/Http/Middleware/VerifyCsrfToken.php +++ b/app/Http/Middleware/VerifyCsrfToken.php @@ -13,6 +13,7 @@ class VerifyCsrfToken extends Middleware */ protected $except = [ 'stripe/webhook', - 'vapor/signed-storage-url' + 'vapor/signed-storage-url', + 'upload-file' ]; } diff --git a/app/Jobs/Form/StoreFormSubmissionJob.php b/app/Jobs/Form/StoreFormSubmissionJob.php index cf15f08..c12d932 100644 --- a/app/Jobs/Form/StoreFormSubmissionJob.php +++ b/app/Jobs/Form/StoreFormSubmissionJob.php @@ -140,7 +140,7 @@ class StoreFormSubmissionJob implements ShouldQueue private function isSkipForUpload($value) { $newPath = Str::of(PublicFormController::FILE_UPLOAD_PATH)->replace('?', $this->form->id); - return Storage::disk('s3')->exists($newPath.'/'.$value); + return Storage::exists($newPath.'/'.$value); } /** @@ -165,7 +165,7 @@ class StoreFormSubmissionJob implements ShouldQueue // Make sure we retrieve the file in tmp storage, move it to persistent $fileName = PublicFormController::TMP_FILE_UPLOAD_PATH.'/'.$fileNameParser->uuid; - if (!Storage::disk('s3')->exists($fileName)) { + if (!Storage::exists($fileName)) { // File not found, we skip return null; } @@ -178,7 +178,7 @@ class StoreFormSubmissionJob implements ShouldQueue 'form_id' => $this->form->id, 'form_slug' => $this->form->slug, ]); - Storage::disk('s3')->move($fileName, $completeNewFilename); + Storage::move($fileName, $completeNewFilename); return $fileNameParser->getMovedFileName(); } @@ -193,7 +193,7 @@ class StoreFormSubmissionJob implements ShouldQueue $newPath = Str::of(PublicFormController::FILE_UPLOAD_PATH)->replace('?', $this->form->id); $completeNewFilename = $newPath.'/'.$fileName; - Storage::disk('s3')->put($completeNewFilename, base64_decode(explode(',', $value)[1])); + Storage::put($completeNewFilename, base64_decode(explode(',', $value)[1])); return $fileName; } diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index cdb7f10..dd0a30f 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -8,7 +8,8 @@ use Illuminate\Support\ServiceProvider; use Laravel\Cashier\Cashier; use Laravel\Dusk\DuskServiceProvider; use Illuminate\Support\Facades\Validator; - +use Illuminate\Support\Facades\Storage; +use Illuminate\Support\Facades\URL; class AppServiceProvider extends ServiceProvider { /** @@ -18,6 +19,16 @@ class AppServiceProvider extends ServiceProvider */ public function boot() { + if(config('filesystems.default') === 'local'){ + Storage::disk('local')->buildTemporaryUrlsUsing(function ($path, $expiration, $options) { + return URL::temporarySignedRoute( + 'local.temp', + $expiration, + array_merge($options, ['path' => $path]) + ); + }); + } + JsonResource::withoutWrapping(); Cashier::calculateTaxes(); diff --git a/app/Rules/StorageFile.php b/app/Rules/StorageFile.php index 49e67a9..f2f0a30 100644 --- a/app/Rules/StorageFile.php +++ b/app/Rules/StorageFile.php @@ -43,7 +43,7 @@ class StorageFile implements Rule // This is use when updating a record, and file uploads aren't changed. if($this->form){ $newPath = Str::of(PublicFormController::FILE_UPLOAD_PATH)->replace('?', $this->form->id); - if(Storage::disk('s3')->exists($newPath.'/'.$value)){ + if(Storage::exists($newPath.'/'.$value)){ return true; } } diff --git a/resources/js/components/pages/welcome/AiFeature.vue b/resources/js/components/pages/welcome/AiFeature.vue index ad45468..c24fdad 100644 --- a/resources/js/components/pages/welcome/AiFeature.vue +++ b/resources/js/components/pages/welcome/AiFeature.vue @@ -62,13 +62,16 @@ -
- +
+ Get started for free - + Get started for free + + Learn more +
diff --git a/resources/js/plugins/vapor.js b/resources/js/plugins/vapor.js index d3a6f0a..ceb45f4 100644 --- a/resources/js/plugins/vapor.js +++ b/resources/js/plugins/vapor.js @@ -15,6 +15,26 @@ Vue.mixin({ * Store a file in S3 and return its UUID, key, and other information. */ async storeFile (file, options = {}) { + if(!window.config.s3_enabled) { // If not s3 then upload to local temp + if (typeof options.progress === 'undefined') { + options.progress = () => {} + } + const cleanAxios = axios.create() + let formData = new FormData(); + formData.append('file', file); + const response = await cleanAxios.post('/upload-file', formData, { + headers: { + 'Content-Type': 'multipart/form-data' + }, + onUploadProgress: (progressEvent) => { + options.progress(progressEvent.loaded / progressEvent.total) + } + }) + + response.data.extension = file.name.split('.').pop() + return response.data + } + const response = await axios.post(options.signedStorageUrl ? options.signedStorageUrl : '/vapor/signed-storage-url', { bucket: options.bucket || '', content_type: options.contentType || file.type, diff --git a/resources/views/spa.blade.php b/resources/views/spa.blade.php index f9dc12d..0be87c3 100644 --- a/resources/views/spa.blade.php +++ b/resources/views/spa.blade.php @@ -13,7 +13,8 @@ 'google_analytics_code' => config('services.google_analytics_code'), 'amplitude_code' => config('services.amplitude_code'), 'crisp_website_id' => config('services.crisp_website_id'), - 'ai_features_enabled' => !is_null(config('services.openai.api_key')) + 'ai_features_enabled' => !is_null(config('services.openai.api_key')), + 's3_enabled' => config('filesystems.default') === 's3' ]; @endphp diff --git a/routes/web.php b/routes/web.php index 04d97e2..a7abe4f 100644 --- a/routes/web.php +++ b/routes/web.php @@ -1,6 +1,8 @@ middleware([]); +Route::post( + '/upload-file', + [\App\Http\Controllers\Content\FileUploadController::class, 'upload'] +)->middleware([]); +Route::get('local/temp/{path}', function (Request $request, string $path){ + if (!$request->hasValidSignature()) { + abort(401); + } + $response = Response::make(Storage::get($path), 200); + $response->header("Content-Type", Storage::mimeType($path)); + return $response; +})->where('path', '(.*)')->name('local.temp'); + Route::get('/sitemap.xml', [\App\Http\Controllers\SitemapController::class, 'getSitemap'])->name('sitemap');