mirror of
https://github.com/VueFileManager/vuefilemanager.git
synced 2026-04-18 16:22:14 +00:00
- zip implementation for users
This commit is contained in:
@@ -3,11 +3,13 @@
|
|||||||
namespace App\Console;
|
namespace App\Console;
|
||||||
|
|
||||||
use App\Console\Commands\Deploy;
|
use App\Console\Commands\Deploy;
|
||||||
|
|
||||||
// use App\Console\Commands\SetupDevelopmentEnvironment;
|
// use App\Console\Commands\SetupDevelopmentEnvironment;
|
||||||
use App\Console\Commands\SetupDevEnvironment;
|
use App\Console\Commands\SetupDevEnvironment;
|
||||||
use App\Console\Commands\SetupProductionEnvironment;
|
use App\Console\Commands\SetupProductionEnvironment;
|
||||||
use App\Console\Commands\UpgradeApp;
|
use App\Console\Commands\UpgradeApp;
|
||||||
use App\Share;
|
use App\Share;
|
||||||
|
use App\Zip;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Illuminate\Console\Scheduling\Schedule;
|
use Illuminate\Console\Scheduling\Schedule;
|
||||||
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
||||||
@@ -36,6 +38,10 @@ class Kernel extends ConsoleKernel
|
|||||||
$this->delete_expired_shared_links();
|
$this->delete_expired_shared_links();
|
||||||
})->everyMinute();
|
})->everyMinute();
|
||||||
|
|
||||||
|
$schedule->call(function () {
|
||||||
|
$this->delete_old_zips();
|
||||||
|
})->everySixHours();
|
||||||
|
|
||||||
// Run queue jobs every minute
|
// Run queue jobs every minute
|
||||||
$schedule->command('queue:work --tries=3')
|
$schedule->command('queue:work --tries=3')
|
||||||
->everyMinute()
|
->everyMinute()
|
||||||
@@ -54,6 +60,24 @@ class Kernel extends ConsoleKernel
|
|||||||
require base_path('routes/console.php');
|
require base_path('routes/console.php');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete old zips
|
||||||
|
*/
|
||||||
|
protected function delete_old_zips(): void
|
||||||
|
{
|
||||||
|
// Get all zips
|
||||||
|
$zips = Zip::where('created_at', '<=', Carbon::now()->subDay()->toDateTimeString())->get();
|
||||||
|
|
||||||
|
$zips->each(function ($zip) {
|
||||||
|
|
||||||
|
// Delete zip file
|
||||||
|
\Storage::disk('local')->delete('zip/' . $zip->basename);
|
||||||
|
|
||||||
|
// Delete zip record
|
||||||
|
$zip->delete();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get and delete expired shared links
|
* Get and delete expired shared links
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -3,9 +3,11 @@
|
|||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
use App\FileManagerFolder;
|
use App\FileManagerFolder;
|
||||||
|
use App\Http\Tools\Editor;
|
||||||
use App\Http\Tools\Guardian;
|
use App\Http\Tools\Guardian;
|
||||||
use App\Share;
|
use App\Share;
|
||||||
use App\User;
|
use App\User;
|
||||||
|
use App\Zip;
|
||||||
use Illuminate\Support\Arr;
|
use Illuminate\Support\Arr;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
@@ -14,7 +16,11 @@ use Illuminate\Http\Request;
|
|||||||
use App\FileManagerFile;
|
use App\FileManagerFile;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
|
use Illuminate\Http\Exceptions\HttpResponseException;
|
||||||
|
use Madnest\Madzipper\Facades\Madzipper;
|
||||||
use Response;
|
use Response;
|
||||||
|
use League\Flysystem\FileNotFoundException;
|
||||||
|
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||||
|
|
||||||
class FileAccessController extends Controller
|
class FileAccessController extends Controller
|
||||||
{
|
{
|
||||||
@@ -86,11 +92,36 @@ class FileAccessController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Store user download size
|
// Store user download size
|
||||||
$request->user()->record_download((int) $file->getRawOriginal('filesize'));
|
$request->user()->record_download((int)$file->getRawOriginal('filesize'));
|
||||||
|
|
||||||
return $this->download_file($file);
|
return $this->download_file($file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get generated zip for user
|
||||||
|
*
|
||||||
|
* @param $id
|
||||||
|
* @return \Symfony\Component\HttpFoundation\StreamedResponse
|
||||||
|
*/
|
||||||
|
public function get_zip($id)
|
||||||
|
{
|
||||||
|
$zip = Zip::where('id', $id)
|
||||||
|
->where('user_id', Auth::id())
|
||||||
|
->first();
|
||||||
|
|
||||||
|
$zip_path = 'zip/' . $zip->basename;
|
||||||
|
|
||||||
|
$header = [
|
||||||
|
"Content-Type" => 'application/zip',
|
||||||
|
"Content-Length" => Storage::size($zip_path),
|
||||||
|
"Accept-Ranges" => "bytes",
|
||||||
|
"Content-Range" => "bytes 0-600/" . Storage::size($zip_path),
|
||||||
|
"Content-Disposition" => "attachment; filename=" . $zip->basename,
|
||||||
|
];
|
||||||
|
|
||||||
|
return Storage::download($zip_path, $zip->basename, $header);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get file public
|
* Get file public
|
||||||
*
|
*
|
||||||
@@ -118,7 +149,7 @@ class FileAccessController extends Controller
|
|||||||
$this->check_file_access($shared, $file);
|
$this->check_file_access($shared, $file);
|
||||||
|
|
||||||
// Store user download size
|
// Store user download size
|
||||||
User::find($shared->user_id)->record_download((int) $file->getRawOriginal('filesize'));
|
User::find($shared->user_id)->record_download((int)$file->getRawOriginal('filesize'));
|
||||||
|
|
||||||
return $this->download_file($file);
|
return $this->download_file($file);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ use App\Http\Requests\FileFunctions\UploadRequest;
|
|||||||
use App\Http\Tools\Demo;
|
use App\Http\Tools\Demo;
|
||||||
use Illuminate\Contracts\Routing\ResponseFactory;
|
use Illuminate\Contracts\Routing\ResponseFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Http\Tools\Guardian;
|
use App\Http\Tools\Guardian;
|
||||||
@@ -175,7 +176,7 @@ class EditItemsController extends Controller
|
|||||||
return Demo::response_204();
|
return Demo::response_204();
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach($request->input('data') as $file){
|
foreach ($request->input('data') as $file) {
|
||||||
$unique_id = $file['unique_id'];
|
$unique_id = $file['unique_id'];
|
||||||
|
|
||||||
// Check permission to delete item for authenticated editor
|
// Check permission to delete item for authenticated editor
|
||||||
@@ -204,9 +205,9 @@ class EditItemsController extends Controller
|
|||||||
// Delete item
|
// Delete item
|
||||||
Editor::delete_item($file, $unique_id);
|
Editor::delete_item($file, $unique_id);
|
||||||
|
|
||||||
// Return response
|
// Return response
|
||||||
}
|
}
|
||||||
return response(null, 204);
|
return response(null, 204);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -232,7 +233,7 @@ class EditItemsController extends Controller
|
|||||||
// Check shared permission
|
// Check shared permission
|
||||||
if (!is_editor($shared)) abort(403);
|
if (!is_editor($shared)) abort(403);
|
||||||
|
|
||||||
foreach($request->input('data') as $file){
|
foreach ($request->input('data') as $file) {
|
||||||
$unique_id = $file['unique_id'];
|
$unique_id = $file['unique_id'];
|
||||||
|
|
||||||
// Get file|folder item
|
// Get file|folder item
|
||||||
@@ -316,6 +317,28 @@ class EditItemsController extends Controller
|
|||||||
return $new_file;
|
return $new_file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User download multiple files via zip
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function user_zip_multiple_files(Request $request)
|
||||||
|
{
|
||||||
|
// Get requested files
|
||||||
|
$files = FileManagerFile::whereUserId(Auth::id())
|
||||||
|
->whereIn('unique_id', $request->input('files'))
|
||||||
|
->get();
|
||||||
|
|
||||||
|
$zip = Editor::zip_files($files);
|
||||||
|
|
||||||
|
// Get file
|
||||||
|
return response([
|
||||||
|
'url' => route('zip', $zip->id),
|
||||||
|
'name' => $zip->basename,
|
||||||
|
], 200);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Move item for authenticated master|editor user
|
* Move item for authenticated master|editor user
|
||||||
*
|
*
|
||||||
@@ -341,7 +364,7 @@ class EditItemsController extends Controller
|
|||||||
$shared = get_shared($request->cookie('shared_token'));
|
$shared = get_shared($request->cookie('shared_token'));
|
||||||
|
|
||||||
// Check access to requested directory
|
// Check access to requested directory
|
||||||
Guardian::check_item_access($to_unique_id, $shared);
|
Guardian::check_item_access($to_unique_id, $shared);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move item
|
// Move item
|
||||||
@@ -374,7 +397,7 @@ class EditItemsController extends Controller
|
|||||||
// Check shared permission
|
// Check shared permission
|
||||||
if (!is_editor($shared)) abort(403);
|
if (!is_editor($shared)) abort(403);
|
||||||
|
|
||||||
foreach($request->input('items') as $item) {
|
foreach ($request->input('items') as $item) {
|
||||||
|
|
||||||
$unique_id = $item['unique_id'];
|
$unique_id = $item['unique_id'];
|
||||||
$moving_unique_id = $unique_id;
|
$moving_unique_id = $unique_id;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ use App\FileManagerFile;
|
|||||||
use App\FileManagerFolder;
|
use App\FileManagerFolder;
|
||||||
use App\Http\Requests\FileFunctions\RenameItemRequest;
|
use App\Http\Requests\FileFunctions\RenameItemRequest;
|
||||||
use App\User;
|
use App\User;
|
||||||
|
use App\Zip;
|
||||||
use Aws\Exception\MultipartUploadException;
|
use Aws\Exception\MultipartUploadException;
|
||||||
use Aws\S3\MultipartUploader;
|
use Aws\S3\MultipartUploader;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
@@ -18,11 +19,81 @@ use Illuminate\Support\Facades\Log;
|
|||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
use Intervention\Image\ImageManagerStatic as Image;
|
use Intervention\Image\ImageManagerStatic as Image;
|
||||||
|
use League\Flysystem\FileNotFoundException;
|
||||||
|
use Madnest\Madzipper\Facades\Madzipper;
|
||||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||||
|
|
||||||
|
|
||||||
class Editor
|
class Editor
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Zip selected files, store it in /zip folder and retrieve zip record
|
||||||
|
*
|
||||||
|
* @param $files
|
||||||
|
* @return mixed
|
||||||
|
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
|
||||||
|
*/
|
||||||
|
public static function zip_files($files)
|
||||||
|
{
|
||||||
|
// Local storage instance
|
||||||
|
$disk_local = Storage::disk('local');
|
||||||
|
|
||||||
|
// Create zip directory
|
||||||
|
if (!$disk_local->exists('zip')) {
|
||||||
|
$disk_local->makeDirectory('zip');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move file to local storage from external storage service
|
||||||
|
if (!is_storage_driver('local')) {
|
||||||
|
|
||||||
|
// Create temp directory
|
||||||
|
if (!$disk_local->exists('temp')) {
|
||||||
|
$disk_local->makeDirectory('temp');
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($files as $file) {
|
||||||
|
try {
|
||||||
|
$disk_local->put('temp/' . $file['basename'], Storage::get('file-manager/' . $file['basename']));
|
||||||
|
} catch (FileNotFoundException $e) {
|
||||||
|
throw new HttpException(404, 'File not found');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get zip path
|
||||||
|
$zip_name = Str::random(16) . '.zip';
|
||||||
|
$zip_path = 'zip/' . $zip_name;
|
||||||
|
|
||||||
|
// Create zip
|
||||||
|
$zip = Madzipper::make(storage_path() . '/app/' . $zip_path);
|
||||||
|
|
||||||
|
// Get files folder on local storage drive
|
||||||
|
$files_directory = is_storage_driver('local') ? 'file-manager' : 'temp';
|
||||||
|
|
||||||
|
// Add files to zip
|
||||||
|
$files->each(function ($file) use ($zip, $files_directory) {
|
||||||
|
$zip->addString($file['name'], File::get(storage_path() . '/app/' . $files_directory . '/' . $file['basename']));
|
||||||
|
});
|
||||||
|
|
||||||
|
// Close zip
|
||||||
|
$zip->close();
|
||||||
|
|
||||||
|
// Delete temporary files
|
||||||
|
if (!is_storage_driver('local')) {
|
||||||
|
|
||||||
|
$files->each(function ($file) use ($disk_local) {
|
||||||
|
$disk_local->delete('temp/' . $file['basename']);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store zip record
|
||||||
|
return Zip::create([
|
||||||
|
'user_id' => Auth::id(),
|
||||||
|
'basename' => $zip_name,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create new directory
|
* Create new directory
|
||||||
*
|
*
|
||||||
@@ -206,7 +277,7 @@ class Editor
|
|||||||
// Get user id
|
// Get user id
|
||||||
$user_id = is_null($shared) ? Auth::id() : $shared->user_id;
|
$user_id = is_null($shared) ? Auth::id() : $shared->user_id;
|
||||||
|
|
||||||
foreach($request->input('items') as $item) {
|
foreach ($request->input('items') as $item) {
|
||||||
$unique_id = $item['unique_id'];
|
$unique_id = $item['unique_id'];
|
||||||
|
|
||||||
if ($item['type'] === 'folder') {
|
if ($item['type'] === 'folder') {
|
||||||
@@ -309,8 +380,8 @@ class Editor
|
|||||||
];
|
];
|
||||||
|
|
||||||
// Store user upload size
|
// Store user upload size
|
||||||
if($request->user()){
|
if ($request->user()) {
|
||||||
|
|
||||||
// If upload a loged user
|
// If upload a loged user
|
||||||
$request->user()->record_upload($file_size);
|
$request->user()->record_upload($file_size);
|
||||||
|
|
||||||
|
|||||||
27
app/Zip.php
Normal file
27
app/Zip.php
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
|
class Zip extends Model
|
||||||
|
{
|
||||||
|
protected $guarded = ['id'];
|
||||||
|
|
||||||
|
public $incrementing = false;
|
||||||
|
|
||||||
|
protected $keyType = 'string';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate uuid
|
||||||
|
*/
|
||||||
|
protected static function boot()
|
||||||
|
{
|
||||||
|
parent::boot();
|
||||||
|
|
||||||
|
static::creating(function ($model) {
|
||||||
|
$model->id = (string)Str::uuid();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -25,6 +25,7 @@
|
|||||||
"laravel/ui": "^2.0",
|
"laravel/ui": "^2.0",
|
||||||
"league/flysystem-aws-s3-v3": "^1.0",
|
"league/flysystem-aws-s3-v3": "^1.0",
|
||||||
"league/flysystem-cached-adapter": "^1.0",
|
"league/flysystem-cached-adapter": "^1.0",
|
||||||
|
"madnest/madzipper": "^1.1",
|
||||||
"teamtnt/laravel-scout-tntsearch-driver": "^8.3"
|
"teamtnt/laravel-scout-tntsearch-driver": "^8.3"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
|
|||||||
59
composer.lock
generated
59
composer.lock
generated
@@ -4,7 +4,7 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "aadbe31a952d26aab5730369e2bf4089",
|
"content-hash": "2753a719196cd76d1bd7ee346540266c",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "asm89/stack-cors",
|
"name": "asm89/stack-cors",
|
||||||
@@ -2778,6 +2778,62 @@
|
|||||||
],
|
],
|
||||||
"time": "2020-07-01T11:33:50+00:00"
|
"time": "2020-07-01T11:33:50+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "madnest/madzipper",
|
||||||
|
"version": "v1.1.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/madnest/madzipper.git",
|
||||||
|
"reference": "fd1d8199d04eac103eed9355c9bba680dcf8b89b"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/madnest/madzipper/zipball/fd1d8199d04eac103eed9355c9bba680dcf8b89b",
|
||||||
|
"reference": "fd1d8199d04eac103eed9355c9bba680dcf8b89b",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-zip": "*",
|
||||||
|
"illuminate/filesystem": "^6.18|^7.0|^8.0",
|
||||||
|
"illuminate/support": "^6.18|^7.0|^8.0",
|
||||||
|
"php": ">=7.2.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"mockery/mockery": "^1.3",
|
||||||
|
"orchestra/testbench": "^5.1",
|
||||||
|
"phpunit/phpunit": "^8.0|^9.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"laravel": {
|
||||||
|
"providers": [
|
||||||
|
"Madnest\\Madzipper\\MadzipperServiceProvider"
|
||||||
|
],
|
||||||
|
"aliases": {
|
||||||
|
"Madzipper": "Madnest\\Madzipper\\Madzipper"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Madnest\\Madzipper\\": "src/Madnest/Madzipper"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Jakub Theimer",
|
||||||
|
"email": "theimer@madne.st",
|
||||||
|
"homepage": "https://madne.st",
|
||||||
|
"role": "Developer"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Wannabe successor of Chumper/Zipper package for Laravel",
|
||||||
|
"time": "2020-12-01T23:44:14+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "moneyphp/money",
|
"name": "moneyphp/money",
|
||||||
"version": "v3.3.1",
|
"version": "v3.3.1",
|
||||||
@@ -7809,6 +7865,7 @@
|
|||||||
"faker",
|
"faker",
|
||||||
"fixtures"
|
"fixtures"
|
||||||
],
|
],
|
||||||
|
"abandoned": true,
|
||||||
"time": "2019-12-12T13:22:17+00:00"
|
"time": "2019-12-12T13:22:17+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -165,6 +165,7 @@ return [
|
|||||||
TeamTNT\Scout\TNTSearchScoutServiceProvider::class,
|
TeamTNT\Scout\TNTSearchScoutServiceProvider::class,
|
||||||
Intervention\Image\ImageServiceProvider::class,
|
Intervention\Image\ImageServiceProvider::class,
|
||||||
Laravel\Passport\PassportServiceProvider::class,
|
Laravel\Passport\PassportServiceProvider::class,
|
||||||
|
Madnest\Madzipper\MadzipperServiceProvider::class,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Package Service Providers...
|
* Package Service Providers...
|
||||||
@@ -232,6 +233,7 @@ return [
|
|||||||
'Image' => Intervention\Image\Facades\Image::class,
|
'Image' => Intervention\Image\Facades\Image::class,
|
||||||
'Stripe' => Cartalyst\Stripe\Laravel\Facades\Stripe::class,
|
'Stripe' => Cartalyst\Stripe\Laravel\Facades\Stripe::class,
|
||||||
'Crawler' => Jaybizzle\LaravelCrawlerDetect\Facades\LaravelCrawlerDetect::class,
|
'Crawler' => Jaybizzle\LaravelCrawlerDetect\Facades\LaravelCrawlerDetect::class,
|
||||||
|
'Madzipper' => Madnest\Madzipper\Madzipper::class,
|
||||||
],
|
],
|
||||||
|
|
||||||
'deploy_secret' => env('APP_DEPLOY_SECRET'),
|
'deploy_secret' => env('APP_DEPLOY_SECRET'),
|
||||||
|
|||||||
33
database/migrations/2020_12_13_155309_create_zips_table.php
Normal file
33
database/migrations/2020_12_13_155309_create_zips_table.php
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class CreateZipsTable extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::create('zips', function (Blueprint $table) {
|
||||||
|
$table->uuid('id')->primary();
|
||||||
|
$table->bigInteger('user_id');
|
||||||
|
$table->text('basename');
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('zips');
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because one or more lines are too long
2
public/js/main.js
vendored
2
public/js/main.js
vendored
File diff suppressed because one or more lines are too long
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"/chunks/files~chunks/shared-files~chunks/shared-page.js": "/chunks/files~chunks/shared-files~chunks/shared-page.js?id=ece1ced9bca9d528bbe1",
|
"/chunks/files~chunks/shared-files~chunks/shared-page.js": "/chunks/files~chunks/shared-files~chunks/shared-page.js?id=ae25473bd0c8446ee973",
|
||||||
"/js/main.js": "/js/main.js?id=3dd10beca4336e12197c",
|
"/js/main.js": "/js/main.js?id=29faff102887d66a2ebd",
|
||||||
"/css/app.css": "/css/app.css?id=8f6d5dcb7110a726e142",
|
"/css/app.css": "/css/app.css?id=8f6d5dcb7110a726e142",
|
||||||
"/chunks/admin.js": "/chunks/admin.js?id=5c1ef019716afc67775b",
|
"/chunks/admin.js": "/chunks/admin.js?id=5c1ef019716afc67775b",
|
||||||
"/chunks/admin-account.js": "/chunks/admin-account.js?id=16cd99641f6c1cb6788a",
|
"/chunks/admin-account.js": "/chunks/admin-account.js?id=16cd99641f6c1cb6788a",
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
{{ $t('context_menu.move') }}
|
{{ $t('context_menu.move') }}
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="menu-option" @click="shareItem" v-if="$checkPermission('master')">
|
<li class="menu-option" @click="shareItem" v-if="$checkPermission('master')">
|
||||||
<div class="icon">
|
<div class="icon">
|
||||||
<link-icon size="17"></link-icon>
|
<link-icon size="17"></link-icon>
|
||||||
</div>
|
</div>
|
||||||
@@ -131,12 +131,12 @@
|
|||||||
}}
|
}}
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="menu-option" @click="shareCancel" v-if="this.fileInfoDetail.length > 1 && !multiSelectContextMenu">
|
<li class="menu-option" @click="shareCancel" v-if="this.fileInfoDetail.length > 1 && !multiSelectContextMenu">
|
||||||
<div class="icon">
|
<div class="icon">
|
||||||
<link-icon size="17"></link-icon>
|
<link-icon size="17"></link-icon>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-label">
|
<div class="text-label">
|
||||||
{{$t('context_menu.share_cancel')}}
|
{{ $t('context_menu.share_cancel') }}
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="menu-option" @click="deleteItem">
|
<li class="menu-option" @click="deleteItem">
|
||||||
@@ -365,18 +365,18 @@ export default {
|
|||||||
TrashIcon,
|
TrashIcon,
|
||||||
LinkIcon,
|
LinkIcon,
|
||||||
StarIcon,
|
StarIcon,
|
||||||
EyeIcon,
|
EyeIcon
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters(['user', 'fileInfoDetail']),
|
...mapGetters(['user', 'fileInfoDetail']),
|
||||||
multiSelectContextMenu() {
|
multiSelectContextMenu() {
|
||||||
|
|
||||||
// If is context Menu open on multi selected items open just options for the multi selected items
|
// If is context Menu open on multi selected items open just options for the multi selected items
|
||||||
if(this.fileInfoDetail.length > 1 && this.fileInfoDetail.includes(this.item)) {
|
if (this.fileInfoDetail.length > 1 && this.fileInfoDetail.includes(this.item)) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
// If is context Menu open for the non selected item open options for the single item
|
// If is context Menu open for the non selected item open options for the single item
|
||||||
if(this.fileInfoDetail.length < 2 || !this.fileInfoDetail.includes(this.item)) {
|
if (this.fileInfoDetail.length < 2 || !this.fileInfoDetail.includes(this.item)) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -399,7 +399,7 @@ export default {
|
|||||||
},
|
},
|
||||||
isInFavourites() {
|
isInFavourites() {
|
||||||
return this.favourites.find((el) => el.unique_id == this.item.unique_id)
|
return this.favourites.find((el) => el.unique_id == this.item.unique_id)
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@@ -436,41 +436,26 @@ export default {
|
|||||||
this.favourites &&
|
this.favourites &&
|
||||||
!this.favourites.find((el) => el.unique_id == this.item.unique_id)
|
!this.favourites.find((el) => el.unique_id == this.item.unique_id)
|
||||||
) {
|
) {
|
||||||
//Add to favourite folder that is not selected
|
// Add to favourite folder that is not selected
|
||||||
if(!this.fileInfoDetail.includes(this.item)){
|
if (!this.fileInfoDetail.includes(this.item)) {
|
||||||
this.$store.dispatch('addToFavourites', this.item)
|
this.$store.dispatch('addToFavourites', this.item)
|
||||||
}
|
}
|
||||||
|
|
||||||
//Add to favourites all selected folders
|
// Add to favourites all selected folders
|
||||||
if(this.fileInfoDetail.includes(this.item)) {
|
if (this.fileInfoDetail.includes(this.item)) {
|
||||||
this.$store.dispatch('addToFavourites', null)
|
this.$store.dispatch('addToFavourites', null)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.$store.dispatch('removeFromFavourites', this.item)
|
this.$store.dispatch('removeFromFavourites', this.item)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
downloadItem() {
|
downloadItem() {
|
||||||
//Download no selected item
|
|
||||||
if(!this.fileInfoDetail.includes(this.item)) {
|
|
||||||
this.$downloadFile(
|
|
||||||
this.item.file_url,
|
|
||||||
this.item.name + '.' + this.item.mimetype
|
|
||||||
)
|
|
||||||
}
|
|
||||||
// Download all selected items
|
|
||||||
if(this.fileInfoDetail.includes(this.item)) {
|
|
||||||
|
|
||||||
var files = this.fileInfoDetail;
|
// Zip and download multiple files
|
||||||
|
if (this.fileInfoDetail.length > 1)
|
||||||
var interval = setInterval(() => {
|
this.$store.dispatch('downloadFiles')
|
||||||
|
else {
|
||||||
let file = files.pop()
|
this.$downloadFile(this.item.file_url, this.item.name + '.' + this.item.mimetype)
|
||||||
|
|
||||||
this.$downloadFile(file.file_url,file.name + '.' + file.mimetype)
|
|
||||||
|
|
||||||
if (files.length === 0)
|
|
||||||
clearInterval(interval)
|
|
||||||
}, 300)
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ItemDetail() {
|
ItemDetail() {
|
||||||
@@ -481,13 +466,12 @@ export default {
|
|||||||
this.$store.dispatch('fileInfoToggle', true)
|
this.$store.dispatch('fileInfoToggle', true)
|
||||||
},
|
},
|
||||||
deleteItem() {
|
deleteItem() {
|
||||||
// Dispatch remove item
|
|
||||||
// If is context menu open on non selected item delete this single item
|
// If is context menu open on non selected item delete this single item
|
||||||
if(!this.fileInfoDetail.includes(this.item)){
|
if (!this.fileInfoDetail.includes(this.item)) {
|
||||||
this.$store.dispatch('deleteItem', this.item)
|
this.$store.dispatch('deleteItem', this.item)
|
||||||
}
|
}
|
||||||
// If is context menu open to multi selected items dele this selected items
|
// If is context menu open to multi selected items dele this selected items
|
||||||
if(this.fileInfoDetail.includes(this.item)) {
|
if (this.fileInfoDetail.includes(this.item)) {
|
||||||
this.$store.dispatch('deleteItem')
|
this.$store.dispatch('deleteItem')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -549,7 +533,6 @@ export default {
|
|||||||
this.positionY = container.offsetTop + 51
|
this.positionY = container.offsetTop + 51
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
item(newValue, oldValue) {
|
item(newValue, oldValue) {
|
||||||
|
|||||||
42
resources/js/store/modules/fileFunctions.js
vendored
42
resources/js/store/modules/fileFunctions.js
vendored
@@ -1,11 +1,31 @@
|
|||||||
import i18n from '@/i18n/index'
|
import i18n from '@/i18n/index'
|
||||||
import router from '@/router'
|
import router from '@/router'
|
||||||
import {events} from '@/bus'
|
import {events} from '@/bus'
|
||||||
|
import { Store } from 'vuex'
|
||||||
import {last} from 'lodash'
|
import {last} from 'lodash'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { Store } from 'vuex'
|
import Vue from "vue"
|
||||||
|
|
||||||
|
|
||||||
const actions = {
|
const actions = {
|
||||||
|
downloadFiles: ({ getters }) => {
|
||||||
|
let files = []
|
||||||
|
|
||||||
|
// get unique_ids of selected files
|
||||||
|
getters.fileInfoDetail.forEach(file => files.push(file.unique_id))
|
||||||
|
|
||||||
|
let route = '/download'
|
||||||
|
|
||||||
|
axios.post(route, {
|
||||||
|
files: files
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
Vue.prototype.$downloadFile(response.data.url, response.data.name)
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
Vue.prototype.$isSomethingWrong()
|
||||||
|
})
|
||||||
|
},
|
||||||
moveItem: ({commit, getters, dispatch}, {to_item ,noSelectedItem}) => {
|
moveItem: ({commit, getters, dispatch}, {to_item ,noSelectedItem}) => {
|
||||||
|
|
||||||
let itemsToMove = []
|
let itemsToMove = []
|
||||||
@@ -49,7 +69,7 @@ const actions = {
|
|||||||
dispatch('getAppData')
|
dispatch('getAppData')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.catch(() => isSomethingWrong())
|
.catch(() => Vue.prototype.$isSomethingWrong())
|
||||||
},
|
},
|
||||||
createFolder: ({commit, getters, dispatch}, folderName) => {
|
createFolder: ({commit, getters, dispatch}, folderName) => {
|
||||||
|
|
||||||
@@ -74,7 +94,7 @@ const actions = {
|
|||||||
dispatch('getFolderTree')
|
dispatch('getFolderTree')
|
||||||
|
|
||||||
})
|
})
|
||||||
.catch(() => isSomethingWrong())
|
.catch(() => Vue.prototype.$isSomethingWrong())
|
||||||
},
|
},
|
||||||
renameItem: ({commit, getters, dispatch}, data) => {
|
renameItem: ({commit, getters, dispatch}, data) => {
|
||||||
|
|
||||||
@@ -101,7 +121,7 @@ const actions = {
|
|||||||
if (data.type === 'folder' && getters.currentFolder.location === 'public')
|
if (data.type === 'folder' && getters.currentFolder.location === 'public')
|
||||||
dispatch('getFolderTree')
|
dispatch('getFolderTree')
|
||||||
})
|
})
|
||||||
.catch(() => isSomethingWrong())
|
.catch(() => Vue.prototype.$isSomethingWrong())
|
||||||
},
|
},
|
||||||
uploadFiles: ({commit, getters}, {form, fileSize, totalUploadedSize}) => {
|
uploadFiles: ({commit, getters}, {form, fileSize, totalUploadedSize}) => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
@@ -210,7 +230,7 @@ const actions = {
|
|||||||
to_home: restoreToHome,
|
to_home: restoreToHome,
|
||||||
_method: 'patch'
|
_method: 'patch'
|
||||||
})
|
})
|
||||||
.catch(() => isSomethingWrong())
|
.catch(() => Vue.prototype.$isSomethingWrong())
|
||||||
},
|
},
|
||||||
deleteItem: ({commit, getters, dispatch}, noSelectedItem) => {
|
deleteItem: ({commit, getters, dispatch}, noSelectedItem) => {
|
||||||
|
|
||||||
@@ -290,7 +310,7 @@ const actions = {
|
|||||||
dispatch('getFolderTree')
|
dispatch('getFolderTree')
|
||||||
|
|
||||||
})
|
})
|
||||||
.catch(() => isSomethingWrong())
|
.catch(() => Vue.prototype.$isSomethingWrong())
|
||||||
},
|
},
|
||||||
emptyTrash: ({commit, getters}) => {
|
emptyTrash: ({commit, getters}) => {
|
||||||
|
|
||||||
@@ -308,18 +328,10 @@ const actions = {
|
|||||||
// Remove file preview
|
// Remove file preview
|
||||||
commit('CLEAR_FILEINFO_DETAIL')
|
commit('CLEAR_FILEINFO_DETAIL')
|
||||||
})
|
})
|
||||||
.catch(() => isSomethingWrong())
|
.catch(() => Vue.prototype.$isSomethingWrong())
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show error message
|
|
||||||
function isSomethingWrong() {
|
|
||||||
events.$emit('alert:open', {
|
|
||||||
title: i18n.t('popup_error.title'),
|
|
||||||
message: i18n.t('popup_error.message'),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
actions,
|
actions,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,6 @@
|
|||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
// Stripe WebHook
|
// Stripe WebHook
|
||||||
Route::post('/stripe/webhook', 'WebhookController@handleWebhook');
|
Route::post('/stripe/webhook', 'WebhookController@handleWebhook');
|
||||||
|
|
||||||
@@ -30,6 +29,8 @@ Route::get('/file/{name}/public/{token}', 'FileAccessController@get_file_public'
|
|||||||
Route::group(['middleware' => ['auth:api', 'auth.shared', 'auth.master', 'scope:master,editor,visitor']], function () {
|
Route::group(['middleware' => ['auth:api', 'auth.shared', 'auth.master', 'scope:master,editor,visitor']], function () {
|
||||||
Route::get('/thumbnail/{name}', 'FileAccessController@get_thumbnail')->name('thumbnail');
|
Route::get('/thumbnail/{name}', 'FileAccessController@get_thumbnail')->name('thumbnail');
|
||||||
Route::get('/file/{name}', 'FileAccessController@get_file')->name('file');
|
Route::get('/file/{name}', 'FileAccessController@get_file')->name('file');
|
||||||
|
Route::post('/download', 'FileFunctions\EditItemsController@user_zip_multiple_files');
|
||||||
|
Route::get('/zip/{id}', 'FileAccessController@get_zip')->name('zip');
|
||||||
});
|
});
|
||||||
|
|
||||||
// Get user invoice
|
// Get user invoice
|
||||||
|
|||||||
@@ -1,59 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Tests\Unit;
|
|
||||||
|
|
||||||
use App\User;
|
|
||||||
// use Illuminate\Foundation\Testing\DatabaseMigrations;
|
|
||||||
use Tests\TestCase;
|
|
||||||
use App\FileManagerFile;
|
|
||||||
use Laravel\Passport\Passport;
|
|
||||||
use Illuminate\Auth\AuthenticationException;
|
|
||||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
||||||
|
|
||||||
class BulkTest extends TestCase
|
|
||||||
{
|
|
||||||
// use DatabaseMigrations;
|
|
||||||
use RefreshDatabase;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @test
|
|
||||||
*/
|
|
||||||
|
|
||||||
public function bulk_delete_user ()
|
|
||||||
{
|
|
||||||
$this->withoutExceptionHandling();
|
|
||||||
|
|
||||||
$data ='{
|
|
||||||
"data": [
|
|
||||||
{
|
|
||||||
"force_delete": false,
|
|
||||||
"type": "file",
|
|
||||||
"unique_id": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"force_delete": false,
|
|
||||||
"type": "file",
|
|
||||||
"unique_id": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"force_delete": false,
|
|
||||||
"type": "file",
|
|
||||||
"unique_id": 2
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}';
|
|
||||||
|
|
||||||
$user = factory(User::class)->create();
|
|
||||||
|
|
||||||
factory(FileManagerFile::class, 3)->create();
|
|
||||||
|
|
||||||
$this->assertDatabaseCount('file_manager_files', 3);
|
|
||||||
|
|
||||||
$this->actingAs($user)->withoutMiddleware()->json('POST','/api/remove-item', json_decode($data , true))
|
|
||||||
->assertStatus(201);
|
|
||||||
|
|
||||||
// $this->assertDatabaseCount('file_manager_files', 3);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user