From 586f0bba68fa8f6a4b04e426389da2a2a25e52be Mon Sep 17 00:00:00 2001 From: carodej Date: Fri, 24 Apr 2020 12:50:11 +0200 Subject: [PATCH] protected sharing update --- app/Http/Controllers/Auth/AuthController.php | 4 +- app/Http/Controllers/FileAccessController.php | 149 +++++++++++------- .../FileFunctions/EditController.php | 79 ++++++++-- .../FileFunctions/ShareController.php | 3 +- .../Sharing/FileSharingController.php | 68 +++++--- app/Http/Middleware/CookieAuth.php | 6 +- ...user_scope_to_file_manager_files_table.php | 32 ++++ ...er_scope_to_file_manager_folders_table.php | 32 ++++ public/mix-manifest.json | 48 +++++- .../FilesView/ContextMenu.vue | 4 +- .../FilesView/FileInfoPanel.vue | 46 +++++- .../FilesView/FileItemGrid.vue | 6 +- .../FilesView/FileItemList.vue | 11 +- .../FilesView/MobileMenu.vue | 2 +- resources/js/helpers.js | 6 +- resources/js/main.js | 4 + resources/js/store/modules/fileBrowser.js | 8 +- resources/js/store/modules/fileFunctions.js | 19 ++- resources/js/store/modules/sharing.js | 12 +- resources/js/views/Shared/SharedContent.vue | 20 ++- routes/api.php | 48 +++--- routes/web.php | 3 + 22 files changed, 446 insertions(+), 164 deletions(-) create mode 100644 database/migrations/2020_04_24_055817_add_user_scope_to_file_manager_files_table.php create mode 100644 database/migrations/2020_04_24_080943_add_user_scope_to_file_manager_folders_table.php diff --git a/app/Http/Controllers/Auth/AuthController.php b/app/Http/Controllers/Auth/AuthController.php index 6170a55c..911ecfa6 100644 --- a/app/Http/Controllers/Auth/AuthController.php +++ b/app/Http/Controllers/Auth/AuthController.php @@ -59,7 +59,7 @@ class AuthController extends Controller $data = json_decode($response->content(), true); - return response('Login Successfull!', 200)->cookie('token', $data['access_token'], 43200); + return response('Login Successfull!', 200)->cookie('access_token', $data['access_token'], 43200); } else { return $response; @@ -118,7 +118,7 @@ class AuthController extends Controller $token->delete(); }); - return response('Logout successfull', 200)->cookie('token', '', -1); + return response('Logout successfull', 200)->cookie('access_token', '', -1); } /** diff --git a/app/Http/Controllers/FileAccessController.php b/app/Http/Controllers/FileAccessController.php index f81907a8..5e5a0fa6 100644 --- a/app/Http/Controllers/FileAccessController.php +++ b/app/Http/Controllers/FileAccessController.php @@ -2,52 +2,19 @@ namespace App\Http\Controllers; +use App\FileManagerFolder; +use App\Share; +use Illuminate\Support\Arr; use Illuminate\Support\Facades\Auth; +use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\File; use Illuminate\Http\Request; use App\FileManagerFile; +use Illuminate\Support\Str; use Response; class FileAccessController extends Controller { - /** - * Get file - * - * @param $filename - * @return mixed - */ - public function get_file($filename) - { - // Get user id - $user_id = Auth::id(); - - // Get file record - $file = FileManagerFile::withTrashed() - ->where('user_id', $user_id) - ->where('basename', $filename) - ->firstOrFail(); - - // Get file path - $path = storage_path() . '/app/file-manager/' . $file->basename; - - // Check if file exist - if (!File::exists($path)) abort(404); - - $file = File::get($path); - $type = File::mimeType($path); - $size = File::size($path); - - // Create response - $response = Response::make($file, 200); - $response->header("Content-Type", $type); - $response->header("Content-Disposition", 'attachment; filename=' . $filename); - $response->header("Content-Length", $size); - $response->header("Accept-Ranges", "bytes"); - $response->header("Content-Range", "bytes 0-" . $size . "/" . $size); - - return $response; - } - /** * Get avatar * @@ -73,12 +40,13 @@ class FileAccessController extends Controller } /** - * Get image thumbnail + * Get file * + * @param Request $request * @param $filename * @return mixed */ - public function get_thumbnail($filename) + public function get_file(Request $request, $filename) { // Get user id $user_id = Auth::id(); @@ -86,26 +54,57 @@ class FileAccessController extends Controller // Get file record $file = FileManagerFile::withTrashed() ->where('user_id', $user_id) + ->where('basename', $filename) + ->firstOrFail(); + + // Check user permission + if ( ! $request->user()->tokenCan('master') ) { + $this->check_access($request, $file); + } + + // Format pretty filename + $file_pretty_name = $file->name . '.' . $file->mimetype; + + // Get file path + $path = storage_path() . '/app/file-manager/' . $file->basename; + + // Check if file exist + if (!File::exists($path)) abort(404); + + $file = File::get($path); + $type = File::mimeType($path); + $size = File::size($path); + + // Create response + $response = Response::make($file, 200); + $response->header("Content-Type", $type); + $response->header("Content-Disposition", 'attachment; filename=' . $file_pretty_name); + $response->header("Content-Length", $size); + $response->header("Accept-Ranges", "bytes"); + $response->header("Content-Range", "bytes 0-" . $size . "/" . $size); + + return $response; + } + + /** + * Get image thumbnail + * + * @param Request $request + * @param $filename + * @return mixed + */ + public function get_thumbnail(Request $request, $filename) + { + // Get file record + $file = FileManagerFile::withTrashed() + ->where('user_id', $request->user()->id) ->where('thumbnail', $filename) ->firstOrFail(); - /* if ($request->has('token')) { - - // Get sharing record - $shared = Share::where('token', $request->token)->firstOrFail(); - - // Get all children folders - $foldersIds = FileManagerFolder::with('folders:id,parent_id,unique_id,name') - ->where('user_id', $user_id) - ->where('parent_id', $shared->item_id) - ->get(); - - // Get all authorized parent folders by shared folder as root of tree - $authorized_parent_folder_ids = Arr::flatten([filter_folders_ids($foldersIds), $shared->item_id]); - - // Check user access - if ( ! in_array($file->folder_id, $authorized_parent_folder_ids)) abort(401); - }*/ + // Check user permission + if ( ! $request->user()->tokenCan('master') ) { + $this->check_access($request, $file); + } // Get file path $path = storage_path() . '/app/file-manager/' . $file->getOriginal('thumbnail'); @@ -122,4 +121,40 @@ class FileAccessController extends Controller return $response; } + + /** + * Check user file access + * + * @param $request + */ + protected function check_access($request, $file): void + { + // check if shared_token cookie exist + if (! $request->hasCookie('shared_token')) abort('401'); + + // Get shared token + $shared = Share::where(DB::raw('BINARY `token`'), $request->cookie('shared_token')) + ->first(); + + // Check by parent folder permission + if ($shared->type === 'folder') { + + // Get all children folders + $foldersIds = FileManagerFolder::with('folders:id,parent_id,unique_id,name') + ->where('user_id', $shared->user_id) + ->where('parent_id', $shared->item_id) + ->get(); + + // Get all authorized parent folders by shared folder as root of tree + $accessible_folder_ids = Arr::flatten([filter_folders_ids($foldersIds), $shared->item_id]); + + // Check user access + if (!in_array($file->folder_id, $accessible_folder_ids)) abort(403); + } + + // Check by single file permission + if ($shared->type === 'file') { + if ($shared->item_id !== $file->unique_id) abort(403); + } + } } diff --git a/app/Http/Controllers/FileFunctions/EditController.php b/app/Http/Controllers/FileFunctions/EditController.php index 5d4f960a..baf27f13 100644 --- a/app/Http/Controllers/FileFunctions/EditController.php +++ b/app/Http/Controllers/FileFunctions/EditController.php @@ -5,6 +5,7 @@ namespace App\Http\Controllers\FileFunctions; use App\Share; use Illuminate\Support\Arr; use Illuminate\Support\Facades\Auth; +use Illuminate\Support\Facades\DB; use Intervention\Image\ImageManagerStatic as Image; use Illuminate\Support\Facades\Validator; use Illuminate\Support\Facades\Storage; @@ -26,6 +27,11 @@ class EditController extends Controller */ public function create_folder(Request $request) { + // Check permission to create folder for authenticated public editor + if ( ! $request->user()->tokenCan('master') ) { + $this->check_access($request, $request->parent_id); + } + // Validate request $validator = Validator::make($request->all(), [ 'parent_id' => 'required|integer', @@ -45,6 +51,7 @@ class EditController extends Controller 'name' => $request->has('name') ? $request->input('name') : 'New Folder', 'type' => 'folder', 'unique_id' => $this->get_unique_id(), + 'user_scope' => $request->user()->token()->scopes[0], ]); // Return new folder @@ -79,6 +86,11 @@ class EditController extends Controller ->where('user_id', $user_id) ->firstOrFail(); + // Check permission to rename for authenticated public editor + if ( ! $request->user()->tokenCan('master') ) { + $this->check_access($request, $item->unique_id); + } + $item->name = $request->name; $item->save(); @@ -88,6 +100,11 @@ class EditController extends Controller ->where('user_id', $user_id) ->firstOrFail(); + // Check permission to rename for authenticated public editor + if ( ! $request->user()->tokenCan('master') ) { + $this->check_access($request, $item->folder_id); + } + $item->name = $request->name; $item->save(); } @@ -127,6 +144,11 @@ class EditController extends Controller ->where('unique_id', $request->unique_id) ->first(); + // Check permission to delete for authenticated public editor + if ( ! $request->user()->tokenCan('master') ) { + $this->check_access($request, $folder->unique_id); + } + // Force delete children files if ($request->force_delete) { @@ -170,6 +192,11 @@ class EditController extends Controller ->where('unique_id', $request->unique_id) ->first(); + // Check permission to delete for authenticated public editor + if ( ! $request->user()->tokenCan('master') ) { + $this->check_access($request, $file->folder_id); + } + if ($request->force_delete) { // Delete file @@ -196,9 +223,13 @@ class EditController extends Controller */ public function upload_item(Request $request) { + // Check permission to upload for authenticated public editor + if ( ! $request->user()->tokenCan('master') ) { + $this->check_access($request, $request->parent_id); + } + // Check if user can upload if (config('vuefilemanager.limit_storage_by_capacity') && user_storage_percentage() >= 100) { - abort(423, 'You exceed your storage limit!'); } @@ -248,15 +279,16 @@ class EditController extends Controller // Store file $new_file = FileManagerFile::create([ - 'user_id' => Auth::id(), - 'name' => pathinfo($file->getClientOriginalName())['filename'], - 'basename' => $filename, - 'folder_id' => $folder_id, - 'mimetype' => $file->getClientOriginalExtension(), - 'filesize' => $filesize, - 'type' => $filetype, - 'thumbnail' => $thumbnail, - 'unique_id' => $this->get_unique_id(), + 'user_id' => Auth::id(), + 'name' => pathinfo($file->getClientOriginalName())['filename'], + 'basename' => $filename, + 'folder_id' => $folder_id, + 'mimetype' => $file->getClientOriginalExtension(), + 'filesize' => $filesize, + 'type' => $filetype, + 'thumbnail' => $thumbnail, + 'unique_id' => $this->get_unique_id(), + 'user_scope' => $request->user()->token()->scopes[0], ]); return $new_file; @@ -327,4 +359,31 @@ class EditController extends Controller return $unique_id; } + + /** + * Check if user has access to requested folder + * + * @param $request + */ + protected function check_access($request, $parent_id): void + { + // check if shared_token cookie exist + if (! $request->hasCookie('shared_token')) abort('401'); + + // Get shared token + $shared = Share::where(DB::raw('BINARY `token`'), $request->cookie('shared_token')) + ->firstOrFail(); + + // Get all children folders + $foldersIds = FileManagerFolder::with('folders:id,parent_id,unique_id,name') + ->where('user_id', $shared->user_id) + ->where('parent_id', $shared->item_id) + ->get(); + + // Get all authorized parent folders by shared folder as root of tree + $accessible_folder_ids = Arr::flatten([filter_folders_ids($foldersIds), $shared->item_id]); + + // Check user access + if (!in_array($parent_id, $accessible_folder_ids)) abort(403); + } } \ No newline at end of file diff --git a/app/Http/Controllers/FileFunctions/ShareController.php b/app/Http/Controllers/FileFunctions/ShareController.php index d9bf9904..e453190a 100644 --- a/app/Http/Controllers/FileFunctions/ShareController.php +++ b/app/Http/Controllers/FileFunctions/ShareController.php @@ -5,6 +5,7 @@ namespace App\Http\Controllers\FileFunctions; use Illuminate\Contracts\Routing\ResponseFactory; use App\Http\Controllers\Controller; use Illuminate\Support\Facades\Auth; +use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Hash; use Illuminate\Http\Request; use Illuminate\Support\Arr; @@ -28,7 +29,7 @@ class ShareController extends Controller // Generate unique token $token = Str::random(16); - } while (Share::where('token', $token)->exists()); + } while (Share::where(DB::raw('BINARY `token`'), $token)->exists()); // Create shared options $options = [ diff --git a/app/Http/Controllers/Sharing/FileSharingController.php b/app/Http/Controllers/Sharing/FileSharingController.php index 8f852ed6..8be39bbc 100644 --- a/app/Http/Controllers/Sharing/FileSharingController.php +++ b/app/Http/Controllers/Sharing/FileSharingController.php @@ -3,6 +3,9 @@ namespace App\Http\Controllers\Sharing; use App\Http\Controllers\Controller; +use Illuminate\Contracts\View\Factory; +use Illuminate\Support\Facades\Cookie; +use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Collection; use Illuminate\Http\Request; @@ -14,16 +17,42 @@ use App\Share; class FileSharingController extends Controller { + + /** + * Show page index and delete access_token & shared_token cookie + * + * @return Factory|\Illuminate\View\View + */ + public function index($token) + { + // Get shared token + $shared = Share::where(DB::raw('BINARY `token`'), $token) + ->firstOrFail(['token', 'item_id', 'type', 'permission', 'protected']); + + // Delete old access_token if exist + Cookie::queue('access_token', '', -1); + + // Set cookies + if ($shared->protected) { + + // Set shared token + Cookie::queue('shared_token', $token, 43200); + } + + // Return page index + return view("index"); + } + /** * Get shared record * * @param Request $request * @return mixed */ - public function index($token) + public function show($token) { // Get sharing record - return Share::where('token', $token) + return Share::where(DB::raw('BINARY `token`'), $token) ->firstOrFail(['token', 'item_id', 'type', 'permission', 'protected']); } @@ -39,7 +68,7 @@ class FileSharingController extends Controller // TODO: validacia // Get sharing record - $shared = Share::where('token', $token)->firstOrFail(); + $shared = Share::where(DB::raw('BINARY `token`'), $token)->firstOrFail(); // Check password if (!Hash::check($request->password, $shared->password)) { @@ -54,12 +83,12 @@ class FileSharingController extends Controller $scope = !is_null($shared->permission) ? $shared->permission : 'visitor'; // Generate token for visitor/editor - $token = $user->createToken('token', [$scope])->accessToken; + $token = $user->createToken('access_token', [$scope])->accessToken; // Return authorize token with shared options return response(Arr::except($shared, ['password', 'user_id', 'updated_at', 'created_at']), 200) ->cookie('shared_token', $shared->token, 43200) - ->cookie('token', $token, 43200); + ->cookie('access_token', $token, 43200); } /** @@ -72,14 +101,11 @@ class FileSharingController extends Controller public function browse_private(Request $request, $unique_id) { // Check if token exist - if (!$request->has('token')) + if (! $request->hasCookie('shared_token') ) abort(404, "Sorry, you don't request any content"); // Get sharing record - $shared = Share::where('token', $request->token)->firstOrFail(); - - // Check directory authentication - $this->check_authenticated_access($request); + $shared = Share::where('token', $request->cookie('shared_token'))->firstOrFail(); // Check if user can get directory $this->check_folder_access($unique_id, $shared); @@ -104,15 +130,10 @@ class FileSharingController extends Controller * @param $unique_id * @return Collection */ - public function browse_public(Request $request, $unique_id) + public function browse_public($token, $unique_id) { - - // Check if token exist - if (!$request->has('token')) - abort(404, "Sorry, you don't request any content"); - // Get sharing record - $shared = Share::where('token', $request->token)->firstOrFail(); + $shared = Share::where(DB::raw('BINARY `token`'), $token)->firstOrFail(); // Abort if folder is protected if ($shared->protected) { @@ -154,7 +175,7 @@ class FileSharingController extends Controller public function file_public($token) { // Get sharing record - $shared = Share::where('token', $token)->firstOrFail(); + $shared = Share::where(DB::raw('BINARY `token`'), $token)->firstOrFail(); // Abort if file is protected if ($shared->protected) { @@ -173,13 +194,10 @@ class FileSharingController extends Controller * @param $token * @return mixed */ - public function file_private(Request $request, $token) + public function file_private(Request $request) { // Get sharing record - $shared = Share::where('token', $token)->firstOrFail(); - - // Check file authentication - $this->check_authenticated_access($request); + $shared = Share::where('token', $request->cookie('shared_token'))->firstOrFail(); // Return record return FileManagerFile::where('user_id', $shared->user_id) @@ -202,10 +220,10 @@ class FileSharingController extends Controller ->get(); // Get all authorized parent folders by shared folder as root of tree - $authorized_parent_folder_ids = Arr::flatten([filter_folders_ids($foldersIds), $shared->item_id]); + $accessible_folder_ids = Arr::flatten([filter_folders_ids($foldersIds), $shared->item_id]); // Check user access - if (!in_array($unique_id, $authorized_parent_folder_ids)) abort(401); + if (!in_array($unique_id, $accessible_folder_ids)) abort(401); } /** diff --git a/app/Http/Middleware/CookieAuth.php b/app/Http/Middleware/CookieAuth.php index 1e910820..4dd43550 100644 --- a/app/Http/Middleware/CookieAuth.php +++ b/app/Http/Middleware/CookieAuth.php @@ -17,11 +17,11 @@ class CookieAuth public function handle($request, Closure $next) { if (!$request->bearerToken()) { - if ($request->hasCookie('token')) { + if ($request->hasCookie('access_token')) { - $token = $request->cookie('token'); + $access_token = $request->cookie('access_token'); - $request->headers->add(['Authorization' => 'Bearer ' . $token]); + $request->headers->add(['Authorization' => 'Bearer ' . $access_token]); } else { abort(401); diff --git a/database/migrations/2020_04_24_055817_add_user_scope_to_file_manager_files_table.php b/database/migrations/2020_04_24_055817_add_user_scope_to_file_manager_files_table.php new file mode 100644 index 00000000..ae0b3772 --- /dev/null +++ b/database/migrations/2020_04_24_055817_add_user_scope_to_file_manager_files_table.php @@ -0,0 +1,32 @@ +string('user_scope')->after('type')->default('master'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('file_manager_files', function (Blueprint $table) { + // + }); + } +} diff --git a/database/migrations/2020_04_24_080943_add_user_scope_to_file_manager_folders_table.php b/database/migrations/2020_04_24_080943_add_user_scope_to_file_manager_folders_table.php new file mode 100644 index 00000000..99eb3230 --- /dev/null +++ b/database/migrations/2020_04_24_080943_add_user_scope_to_file_manager_folders_table.php @@ -0,0 +1,32 @@ +string('user_scope')->after('type')->default('master'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('file_manager_folders', function (Blueprint $table) { + // + }); + } +} diff --git a/public/mix-manifest.json b/public/mix-manifest.json index 3fc06eac..6448a87f 100644 --- a/public/mix-manifest.json +++ b/public/mix-manifest.json @@ -254,5 +254,51 @@ "/js/main.4ca90bdb0b28a0bac77f.hot-update.js": "/js/main.4ca90bdb0b28a0bac77f.hot-update.js", "/js/main.84c1025500258c824186.hot-update.js": "/js/main.84c1025500258c824186.hot-update.js", "/js/main.801e23504da473fa4b55.hot-update.js": "/js/main.801e23504da473fa4b55.hot-update.js", - "/js/main.32006f8d1211bd1ac2d7.hot-update.js": "/js/main.32006f8d1211bd1ac2d7.hot-update.js" + "/js/main.32006f8d1211bd1ac2d7.hot-update.js": "/js/main.32006f8d1211bd1ac2d7.hot-update.js", + "/js/main.6a8d550c3990db7478c9.hot-update.js": "/js/main.6a8d550c3990db7478c9.hot-update.js", + "/js/main.5004134af690ec32aab1.hot-update.js": "/js/main.5004134af690ec32aab1.hot-update.js", + "/js/main.41634a1144614d807088.hot-update.js": "/js/main.41634a1144614d807088.hot-update.js", + "/js/main.d5f5f898597444704b60.hot-update.js": "/js/main.d5f5f898597444704b60.hot-update.js", + "/js/main.1e664feef8de56e212bf.hot-update.js": "/js/main.1e664feef8de56e212bf.hot-update.js", + "/js/main.7d581e0210378fd8757b.hot-update.js": "/js/main.7d581e0210378fd8757b.hot-update.js", + "/js/main.43b5aacba74bd554e95c.hot-update.js": "/js/main.43b5aacba74bd554e95c.hot-update.js", + "/js/main.ad3ea3b4851e9f50bb7f.hot-update.js": "/js/main.ad3ea3b4851e9f50bb7f.hot-update.js", + "/js/main.bdf1d8ae0bd5f0c94dff.hot-update.js": "/js/main.bdf1d8ae0bd5f0c94dff.hot-update.js", + "/js/main.69ba7f1ac532e280a94a.hot-update.js": "/js/main.69ba7f1ac532e280a94a.hot-update.js", + "/js/main.d987f755c87ecbfa5a54.hot-update.js": "/js/main.d987f755c87ecbfa5a54.hot-update.js", + "/js/main.0c8af3123ef7c883d969.hot-update.js": "/js/main.0c8af3123ef7c883d969.hot-update.js", + "/js/main.187b03b68915fef4bcb1.hot-update.js": "/js/main.187b03b68915fef4bcb1.hot-update.js", + "/js/main.dffcb583fa1d4ecffc97.hot-update.js": "/js/main.dffcb583fa1d4ecffc97.hot-update.js", + "/js/main.ddca0fc165dac2a29682.hot-update.js": "/js/main.ddca0fc165dac2a29682.hot-update.js", + "/js/main.c17ff75670faa18dd933.hot-update.js": "/js/main.c17ff75670faa18dd933.hot-update.js", + "/js/main.c3eb6b86b455442d8462.hot-update.js": "/js/main.c3eb6b86b455442d8462.hot-update.js", + "/js/main.77c52a7cc53e20947fd7.hot-update.js": "/js/main.77c52a7cc53e20947fd7.hot-update.js", + "/js/main.a616e4cc7a01e8eed242.hot-update.js": "/js/main.a616e4cc7a01e8eed242.hot-update.js", + "/js/main.112dc6ed841f7b808cd8.hot-update.js": "/js/main.112dc6ed841f7b808cd8.hot-update.js", + "/js/main.803859a312ac4e748eff.hot-update.js": "/js/main.803859a312ac4e748eff.hot-update.js", + "/js/main.20cbb4dd19418a5ff851.hot-update.js": "/js/main.20cbb4dd19418a5ff851.hot-update.js", + "/js/main.e25f013b63dc4f541703.hot-update.js": "/js/main.e25f013b63dc4f541703.hot-update.js", + "/js/main.77b2e8162a148bf7a03e.hot-update.js": "/js/main.77b2e8162a148bf7a03e.hot-update.js", + "/js/main.a0f4da8f4727cc6aa706.hot-update.js": "/js/main.a0f4da8f4727cc6aa706.hot-update.js", + "/js/main.810f0d4e727c93679a80.hot-update.js": "/js/main.810f0d4e727c93679a80.hot-update.js", + "/js/main.5953d70bc531273f9b20.hot-update.js": "/js/main.5953d70bc531273f9b20.hot-update.js", + "/js/main.af6b95d41bf9c597c9d1.hot-update.js": "/js/main.af6b95d41bf9c597c9d1.hot-update.js", + "/js/main.b47cb69eb422e75a2ab1.hot-update.js": "/js/main.b47cb69eb422e75a2ab1.hot-update.js", + "/js/main.4147f07ef2cb895c2cfa.hot-update.js": "/js/main.4147f07ef2cb895c2cfa.hot-update.js", + "/js/main.2804ef0f8afb2870c619.hot-update.js": "/js/main.2804ef0f8afb2870c619.hot-update.js", + "/js/main.375bcf3d9411d45c5e8c.hot-update.js": "/js/main.375bcf3d9411d45c5e8c.hot-update.js", + "/js/main.92e2e5e9645d0695e9d8.hot-update.js": "/js/main.92e2e5e9645d0695e9d8.hot-update.js", + "/js/main.ba0c049a37bf7b2a6b79.hot-update.js": "/js/main.ba0c049a37bf7b2a6b79.hot-update.js", + "/js/main.1ef909b95fa306a007d7.hot-update.js": "/js/main.1ef909b95fa306a007d7.hot-update.js", + "/js/main.890b46569bf4f0d2d100.hot-update.js": "/js/main.890b46569bf4f0d2d100.hot-update.js", + "/js/main.c93eb7f3891224263841.hot-update.js": "/js/main.c93eb7f3891224263841.hot-update.js", + "/js/main.e8ed183cd2e394932a9d.hot-update.js": "/js/main.e8ed183cd2e394932a9d.hot-update.js", + "/js/main.a77ed20147d5635562a9.hot-update.js": "/js/main.a77ed20147d5635562a9.hot-update.js", + "/js/main.4ed3ccf3488d1d2a2734.hot-update.js": "/js/main.4ed3ccf3488d1d2a2734.hot-update.js", + "/js/main.0d144f90bc5ed08d20d7.hot-update.js": "/js/main.0d144f90bc5ed08d20d7.hot-update.js", + "/js/main.d0f95d4ae27cb5a01879.hot-update.js": "/js/main.d0f95d4ae27cb5a01879.hot-update.js", + "/js/main.591c675411457ff698d7.hot-update.js": "/js/main.591c675411457ff698d7.hot-update.js", + "/js/main.cccd40ca7d095723a593.hot-update.js": "/js/main.cccd40ca7d095723a593.hot-update.js", + "/js/main.a109b65ef389a64af5d7.hot-update.js": "/js/main.a109b65ef389a64af5d7.hot-update.js", + "/js/main.22245e61bfcf217f706c.hot-update.js": "/js/main.22245e61bfcf217f706c.hot-update.js" } diff --git a/resources/js/components/VueFileManagerComponents/FilesView/ContextMenu.vue b/resources/js/components/VueFileManagerComponents/FilesView/ContextMenu.vue index 86f66fc4..f9f19d11 100644 --- a/resources/js/components/VueFileManagerComponents/FilesView/ContextMenu.vue +++ b/resources/js/components/VueFileManagerComponents/FilesView/ContextMenu.vue @@ -70,7 +70,7 @@ -